mirror of https://github.com/OISF/suricata
Simple configuration API.
Allow the log directory to be changed.remotes/origin/master-1.0.x
parent
c73f4334d0
commit
e3b538c7d7
@ -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
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue