Simple configuration API.

Allow the log directory to be changed.
remotes/origin/master-1.0.x
Jason Ish 17 years ago committed by Victor Julien
parent c73f4334d0
commit e3b538c7d7

@ -1,6 +1,5 @@
bin_PROGRAMS = eidps
eidps_SOURCES = eidps.c eidps.h \
config.c config.h \
packet-queue.c packet-queue.h \
threads.c threads.h \
source-nfq.c source-nfq.h \
@ -98,7 +97,8 @@ counters.c counter.h \
app-layer-detect-proto.c app-layer-detect-proto.h \
app-layer-parser.c app-layer-parser.h \
app-layer-http.c app-layer-http.h \
app-layer-protos.h
app-layer-protos.h \
conf.c conf.h
# set the include path found by configure
INCLUDES= $(all_includes)

@ -14,6 +14,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -23,6 +24,7 @@
#include "debug.h"
#include "detect.h"
#include "flow.h"
#include "conf.h"
#include "threadvars.h"
#include "tm-modules.h"
@ -33,6 +35,8 @@
#include "util-unittest.h"
#define DEFAULT_LOG_FILENAME "alert-debug.log"
int AlertDebuglog (ThreadVars *, Packet *, void *, PacketQueue *);
int AlertDebuglogIPv4(ThreadVars *, Packet *, void *, PacketQueue *);
int AlertDebuglogIPv6(ThreadVars *, Packet *, void *, PacketQueue *);
@ -204,11 +208,13 @@ int AlertDebuglogThreadInit(ThreadVars *t, void *initdata, void **data)
}
memset(aft, 0, sizeof(AlertDebuglogThread));
/* XXX */
char *path = "/var/log/eidps/alert-debug.log";
aft->fp = fopen(path, "w");
char log_path[PATH_MAX], *log_dir;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
snprintf(log_path, PATH_MAX, "%s/%s", log_dir, DEFAULT_LOG_FILENAME);
aft->fp = fopen(log_path, "w");
if (aft->fp == NULL) {
printf("ERROR: failed to open %s: %s\n", path, strerror(errno));
printf("ERROR: failed to open %s: %s\n", log_path, strerror(errno));
return -1;
}

@ -18,6 +18,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -27,12 +28,15 @@
#include "debug.h"
#include "detect.h"
#include "flow.h"
#include "conf.h"
#include "threadvars.h"
#include "tm-modules.h"
#include "util-unittest.h"
#define DEFAULT_LOG_FILENAME "fast.log"
int AlertFastlog (ThreadVars *, Packet *, void *, PacketQueue *);
int AlertFastlogIPv4(ThreadVars *, Packet *, void *, PacketQueue *);
int AlertFastlogIPv6(ThreadVars *, Packet *, void *, PacketQueue *);
@ -155,11 +159,13 @@ int AlertFastlogThreadInit(ThreadVars *t, void *initdata, void **data)
}
memset(aft, 0, sizeof(AlertFastlogThread));
/* XXX */
char *path = "/var/log/eidps/fast.log";
aft->fp = fopen(path, "w");
char log_path[PATH_MAX], *log_dir;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
snprintf(log_path, PATH_MAX, "%s/%s", log_dir, DEFAULT_LOG_FILENAME);
aft->fp = fopen(log_path, "w");
if (aft->fp == NULL) {
printf("ERROR: failed to open %s: %s\n", path, strerror(errno));
printf("ERROR: failed to open %s: %s\n", log_path, strerror(errno));
return -1;
}

@ -18,6 +18,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -27,6 +28,7 @@
#include "debug.h"
#include "detect.h"
#include "flow.h"
#include "conf.h"
#include "threadvars.h"
#include "tm-modules.h"
@ -86,7 +88,7 @@ typedef struct AlertUnifiedAlertPacketHeader_ {
} AlertUnifiedAlertPacketHeader;
int AlertUnifiedAlertCreateFile(ThreadVars *t, AlertUnifiedAlertThread *aun) {
char filename[2048]; /* XXX some sane default? */
char filename[PATH_MAX];
int ret;
/* get the time so we can have a filename with seconds since epoch
@ -98,7 +100,10 @@ int AlertUnifiedAlertCreateFile(ThreadVars *t, AlertUnifiedAlertThread *aun) {
gettimeofday(&ts, NULL);
/* create the filename to use */
snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, "/var/log/eidps", "unified.alert", (uint32_t)ts.tv_sec);
char *log_dir;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, log_dir, "unified.alert", (uint32_t)ts.tv_sec);
/* XXX filename & location */
aun->fp = fopen(filename, "wb");

@ -18,6 +18,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -27,6 +28,7 @@
#include "debug.h"
#include "detect.h"
#include "flow.h"
#include "conf.h"
#include "threadvars.h"
#include "tm-modules.h"
@ -88,7 +90,7 @@ typedef struct AlertUnifiedLogPacketHeader_ {
} AlertUnifiedLogPacketHeader;
int AlertUnifiedLogCreateFile(ThreadVars *t, AlertUnifiedLogThread *aun) {
char filename[2048]; /* XXX some sane default? */
char filename[PATH_MAX]; /* XXX some sane default? */
int ret;
/* get the time so we can have a filename with seconds since epoch
@ -100,7 +102,10 @@ int AlertUnifiedLogCreateFile(ThreadVars *t, AlertUnifiedLogThread *aun) {
gettimeofday(&ts, NULL);
/* create the filename to use */
snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, "/var/log/eidps", "unified.log", (uint32_t)ts.tv_sec);
char *log_dir;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
snprintf(filename, sizeof(filename), "%s/%s.%" PRIu32, log_dir, "unified.log", (uint32_t)ts.tv_sec);
/* XXX filename & location */
aun->fp = fopen(filename, "wb");

@ -0,0 +1,326 @@
/* Copyright (c) 2009 Open Information Security Foundation
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This file provides a basic configuration system for the IDPS
* engine.
*
* NOTE: Setting values should only be done from one thread during
* engine initialization. Multiple threads should be able access read
* configuration data. Allowing run time changes to the configuration
* will require some locks.
*
* \author Endace Technology Limited
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "eidps-common.h"
#include "conf.h"
#include "util-hash.h"
#include "util-unittest.h"
#undef CONF_DEBUG
#ifdef CONF_DEBUG
#define DPRINTF(x) do { printf x ; } while (0)
#else
#define DPRINTF(x)
#endif /* CONF_DEBUG */
#define CONF_HASH_TBL_SIZE 1024
static HashTable *conf_hash = NULL;
/**
* Structure of a configuration parameter.
*/
struct conf_node {
char *name;
char *val;
int allow_override;
};
/**
* \brief Function to generate the hash of a configuration value.
*
* This is a callback function provided to HashTable for creating the
* hash key. Its a simple wrapper around the generic hash function
* the passes on the configuration parameter name.
*
* \retval The hash ID of the configuration parameters name.
*/
static uint32_t
ConfHashFunc(HashTable *ht, void *data, uint16_t len)
{
struct conf_node *cn = (struct conf_node *)data;
uint32_t hash;
hash = HashTableGenericHash(ht, cn->name, strlen(cn->name));
DPRINTF(("%s: %s -> %" PRIu32 "\n", __func__, cn->name, hash));
return hash;
}
/**
* \brief Function to compare 2 hash nodes.
*
* This is a callback function provided to the HashTable for comparing
* 2 nodes.
*
* \retval 1 if equivalant otherwise 0.
*/
static char
ConfHashComp(void *a, uint16_t a_len, void *b, uint16_t b_len)
{
struct conf_node *ca = (struct conf_node *)a;
struct conf_node *cb = (struct conf_node *)b;
if (strcmp(ca->name, cb->name) == 0)
return 1;
else
return 0;
}
/**
* \brief Callback function to free a hash node.
*/
static void ConfHashFree(void *data)
{
struct conf_node *cn = (struct conf_node *)data;
DPRINTF(("%s: Freeing configuration parameter '%s'\n", __func__, cn->name));
free(cn->name);
free(cn->val);
free(cn);
}
/**
* \brief Initialize the configuration system.
*/
void
ConfInit(void)
{
/* Prevent double initialization. */
if (conf_hash != NULL) {
DPRINTF(("%s: Already initialized.\n", __func__));
return;
}
conf_hash = HashTableInit(CONF_HASH_TBL_SIZE, ConfHashFunc, ConfHashComp,
ConfHashFree);
if (conf_hash == NULL) {
fprintf(stderr,
"ERROR: Failed to allocate memory for configuration, aborting.\n");
exit(1);
}
DPRINTF(("%s: Configuration module initialized.\n", __func__));
}
/**
* \brief Set a configuration value.
*
* \param name The name of the configuration parameter to set.
* \param val The value of the configuration parameter.
* \param allow_override Can a subsequent set override this value.
*
* \retval 1 if the value was set otherwise 0.
*/
int
ConfSet(char *name, char *val, int allow_override)
{
struct conf_node lookup_key, *conf_node;
lookup_key.name = name;
conf_node = HashTableLookup(conf_hash, &lookup_key, sizeof(lookup_key));
if (conf_node != NULL) {
if (!allow_override) {
return 0;
}
HashTableRemove(conf_hash, conf_node, sizeof(*conf_node));
}
conf_node = calloc(1, sizeof(*conf_node));
if (conf_node == NULL) {
return 0;
}
conf_node->name = strdup(name);
conf_node->val = strdup(val);
conf_node->allow_override = allow_override;
if (HashTableAdd(conf_hash, conf_node, sizeof(*conf_node)) != 0) {
fprintf(stderr, "ERROR: Failed to set configuration parameter %s\n",
name);
exit(1);
}
DPRINTF(("%s: Configuration parameter '%s' set.\n", __func__, name));
return 1;
}
/**
* \brief Retrieve a configuration value.
*
* \param name Name of configuration parameter to get.
* \param vptr Pointer that will be set to the configuration value parameter.
* Note that this is just a reference to the actual value, not a copy.
*
* \retval 1 will be returned if the name is found, otherwise 0 will
* be returned.
*/
int
ConfGet(char *name, char **vptr)
{
struct conf_node lookup_key;
struct conf_node *conf_node;
lookup_key.name = name;
conf_node = HashTableLookup(conf_hash, &lookup_key, sizeof(lookup_key));
if (conf_node == NULL) {
DPRINTF(("%s: Failed to lookup configuration parameter '%s'\n",
__func__, name));
return 0;
}
else {
*vptr = conf_node->val;
return 1;
}
}
/**
* \brief Remove a configuration parameter from the configuration db.
*
* \param name The name of the configuration parameter to remove.
*
* \retval Returns 1 if the parameter was removed, otherwise 0 is returned
* most likely indicating the parameter was not set.
*/
int
ConfRemove(char *name)
{
struct conf_node cn;
cn.name = name;
if (HashTableRemove(conf_hash, &cn, sizeof(cn)) == 0)
return 1;
else
return 0;
}
#ifdef UNITTESTS
/**
* Lookup a non-existant value.
*/
static int
ConfTestGetNonExistant(void)
{
char name[] = "non-existant-value";
char *value;
return !ConfGet(name, &value);
}
/**
* Set then lookup a value.
*/
static int
ConfTestSetAndGet(void)
{
char name[] = "some-name";
char value[] = "some-value";
char *value0;
if (ConfSet(name, value, 1) != 1)
return 0;
if (ConfGet(name, &value0) != 1)
return 0;
if (strcmp(value, value0) != 0)
return 0;
/* Cleanup. */
ConfRemove(name);
return 1;
}
/**
* Test that overriding a value is allowed provided allow_override is
* true and that the config parameter gets the new value.
*/
static int
ConfTestOverrideValue1(void)
{
char name[] = "some-name";
char value0[] = "some-value";
char value1[] = "new-value";
char *val;
int rc;
if (ConfSet(name, value0, 1) != 1)
return 0;
if (ConfSet(name, value1, 1) != 1)
return 0;
if (ConfGet(name, &val) != 1)
return 0;
rc = !strcmp(val, value1);
/* Cleanup. */
ConfRemove(name);
return rc;
}
/**
* Test that overriding a value is not allowed provided that
* allow_override is false and make sure the value was not overrided.
*/
static int
ConfTestOverrideValue2(void)
{
char name[] = "some-name";
char value0[] = "some-value";
char value1[] = "new-value";
char *val;
int rc;
if (ConfSet(name, value0, 0) != 1)
return 0;
if (ConfSet(name, value1, 0) != 0)
return 0;
if (ConfGet(name, &val) != 1)
return 0;
rc = !strcmp(val, value0);
/* Cleanup. */
ConfRemove(name);
return rc;
}
void
ConfRegisterTests(void)
{
UtRegisterTest("ConfTestGetNonExistant", ConfTestGetNonExistant, 1);
UtRegisterTest("ConfTestSetAndGet", ConfTestSetAndGet, 1);
UtRegisterTest("ConfTestOverrideValue1", ConfTestOverrideValue1, 1);
UtRegisterTest("ConfTestOverrideValue2", ConfTestOverrideValue2, 1);
}
#endif /* UNITTESTS */

@ -0,0 +1,33 @@
/* Copyright (c) 2009 Open Information Security Foundation
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \author Endace Technology Limited
*/
#ifndef __CONF_H__
#define __CONF_H__
/**
* The default log directory.
*/
#define DEFAULT_LOG_DIR "/var/log/eidps"
void ConfInit(void);
int ConfGet(char *name, char **vptr);
int ConfSet(char *name, char *val, int allow_override);
void ConfRegisterTests();
#endif /* ! __CONF_H__ */

@ -1,84 +0,0 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <sys/signal.h>
/** \todo These are covered by HAVE_* macros */
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <pcre.h>
#include "eidps-common.h"
static pcre *config_pcre = NULL;
static pcre_extra *config_pcre_extra = NULL;
#define CONFIG_PCRE "^\\s*([a-z]+)\\s*(.*)$"
int LoadConfig ( void ) {
char line[8192] = "";
char *regexstr = CONFIG_PCRE;
const char *eb;
int eo;
int opts = 0;
int ret = 0;
#define MAX_SUBSTRINGS 30
int ov[MAX_SUBSTRINGS];
FILE *fp = fopen("eidps.conf", "r");
if (fp == NULL) printf("ERROR: fopen failed %s\n", strerror(errno));
//opts |= PCRE_UNGREEDY;
config_pcre = pcre_compile(regexstr, opts, &eb, &eo, NULL);
if(config_pcre == NULL)
{
printf("pcre compile of \"%s\" failed at offset %" PRId32 ": %s\n", regexstr, eo, eb);
exit(1);
}
config_pcre_extra = pcre_study(config_pcre, 0, &eb);
if(eb != NULL)
{
printf("pcre study failed: %s\n", eb);
exit(1);
}
while (fgets(line,sizeof(line),fp) != NULL) {
//printf("LoadConfig: %s", line);
ret = pcre_exec(config_pcre, config_pcre_extra, line, strlen(line), 0, 0, ov, MAX_SUBSTRINGS);
if (ret != 3) {
//printf("pcre_exec failed: ret %" PRId32 ", optstr \"%s\"\n", ret, line);
continue;
}
//printf("LoadConfig: pcre_exec returned %" PRId32 "\n", ret);
const char *all, *name, *value;
pcre_get_substring(line, ov, MAX_SUBSTRINGS, 0, &all);
pcre_get_substring(line, ov, MAX_SUBSTRINGS, 1, &name);
pcre_get_substring(line, ov, MAX_SUBSTRINGS, 2, &value);
printf("LoadConfig: name \"%s\" value \"%s\"\n", name, value);
}
return 0;
/** \todo Currently unused */
#if 0
error:
return -1;
#endif
}

@ -12,12 +12,40 @@
#include "tm-modules.h"
#include "tm-threads.h"
#include "util-unittest.h"
#include "conf.h"
/** \todo config api */
#define LOGPATH "/var/log/eidps/stats.log"
/** \todo Get the default log directory from some global resource. */
#define DEFAULT_LOG_FILENAME "stats.log"
static PerfOPIfaceContext *perf_op_ctx = NULL;
/**
* \brief Get the filename with path to the stats log file.
*
* This function returns a string containing the log filename. It
* uses allocated memory simply to drop into the existing code a
* little better where a strdup was used. So as before, it is up to
* the caller to free the memory.
*
* \retval An allocated string containing the log filename or NULL on
* a failure.
*/
static char *
PerfGetLogFilename(void)
{
char *log_dir;
char *log_filename;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
log_filename = malloc(PATH_MAX);
if (log_filename == NULL)
return NULL;
snprintf(log_filename, PATH_MAX, "%s/%s", log_dir, DEFAULT_LOG_FILENAME);
return log_filename;
}
/**
* \brief Initializes the perf counter api. Things are hard coded currently.
* More work to be done when we implement multiple interfaces
@ -42,7 +70,7 @@ void PerfInitOPCtx(void)
perf_op_ctx->iface = IFACE_FILE;
if ( (perf_op_ctx->file = strdup(LOGPATH)) == NULL) {
if ( (perf_op_ctx->file = PerfGetLogFilename()) == NULL) {
printf("error allocating memory\n");
exit(0);
}

@ -830,6 +830,7 @@ void usage(const char *progname)
printf("\t-r <path>: run in pcap file/offline mode\n");
printf("\t-q <qid> : run in inline nfqueue mode\n");
printf("\t-s <path>: path to signature file (optional)\n");
printf("\t-l <dir> : default log directory\n");
#ifdef UNITTESTS
printf("\t-u : run the unittests and exit\n");
#endif /* UNITTESTS */
@ -853,7 +854,10 @@ int main(int argc, char **argv)
setup_signal_handler(SIGHUP, handle_sighup);
//pthread_sigmask(SIG_BLOCK, &set, 0);
while ((opt = getopt(argc, argv, "hi:q:r:us:")) != -1) {
/* Initialize the configuration module. */
ConfInit();
while ((opt = getopt(argc, argv, "hi:l:q:r:us:")) != -1) {
switch (opt) {
case 'h':
usage(argv[0]);
@ -863,6 +867,12 @@ int main(int argc, char **argv)
mode = MODE_PCAP_DEV;
pcap_dev = optarg;
break;
case 'l':
if (ConfSet("default-log-dir", optarg, 0) != 1) {
fprintf(stderr, "ERROR: Failed to set log directory.\n");
exit(1);
}
break;
case 'q':
mode = MODE_NFQ;
nfq_id = atoi(optarg); /* strtol? */
@ -960,6 +970,7 @@ int main(int argc, char **argv)
DecodePPPoERegisterTests();
DecodeICMPV4RegisterTests();
AlpDetectRegisterTests();
ConfRegisterTests();
UtRunTests();
UtCleanup();
exit(0);

@ -10,6 +10,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
@ -19,6 +20,7 @@
#include "debug.h"
#include "detect.h"
#include "pkt-var.h"
#include "conf.h"
#include "threadvars.h"
#include "tm-modules.h"
@ -28,6 +30,8 @@
#include "util-print.h"
#include "util-unittest.h"
#define DEFAULT_LOG_FILENAME "http.log"
int LogHttplog (ThreadVars *, Packet *, void *, PacketQueue *);
int LogHttplogIPv4(ThreadVars *, Packet *, void *, PacketQueue *);
int LogHttplogIPv6(ThreadVars *, Packet *, void *, PacketQueue *);
@ -180,11 +184,13 @@ int LogHttplogThreadInit(ThreadVars *t, void *initdata, void **data)
}
memset(aft, 0, sizeof(LogHttplogThread));
/* XXX */
char *path = "/var/log/eidps/http.log";
aft->fp = fopen(path, "w");
char log_path[PATH_MAX], *log_dir;
if (ConfGet("default-log-dir", &log_dir) != 1)
log_dir = DEFAULT_LOG_DIR;
snprintf(log_path, PATH_MAX, "%s/%s", log_dir, DEFAULT_LOG_FILENAME);
aft->fp = fopen(log_path, "w");
if (aft->fp == NULL) {
printf("ERROR: failed to open %s: %s\n", path, strerror(errno));
printf("ERROR: failed to open %s: %s\n", log_path, strerror(errno));
return -1;
}

Loading…
Cancel
Save