Files missed in last commit.

Update Conf API to allow direct access to nodes.

    A configuration node is now a tailq head and a tailq entry.  This allows us to build
    n-ary type trees to build something DOM like.

    Properly process lists so a list of rule files (for example) can be loaded.
remotes/origin/master-1.0.x
Jason Ish 16 years ago committed by Victor Julien
parent d39a291427
commit ec9fa7b0a7

@ -62,3 +62,7 @@ pfring:
# All threads/processes that will participate need to have the same # All threads/processes that will participate need to have the same
# clusterid. # clusterid.
clusterid: 99 clusterid: 99
rule-files:
- netbios.rules
- x11.rules

@ -12,6 +12,7 @@
#include "eidps-common.h" #include "eidps-common.h"
#include "conf.h" #include "conf.h"
#include "util-debug.h" #include "util-debug.h"
#include "util-unittest.h"
/* Define to print the current YAML state. */ /* Define to print the current YAML state. */
#undef PRINT_STATES #undef PRINT_STATES
@ -30,6 +31,7 @@
enum conf_state { enum conf_state {
CONF_KEY = 0, CONF_KEY = 0,
CONF_VAL, CONF_VAL,
CONF_SEQ,
}; };
/** /**
@ -67,6 +69,80 @@ GetKeyName(char **key, int level)
return print_key; return print_key;
} }
/**
* \brief Parse a YAML layer.
*
* This will eventually replace ConfYamlParse but for now its just
* used to load lists.
*
* \param parser A pointer to an active yaml_parser_t.
* \param parent The parent configuration node.
* \param init_state State to start off as.
*/
static void
ConfYamlParse2(yaml_parser_t *parser, ConfNode *parent, int init_state)
{
ConfNode *node = parent;
yaml_event_t event;
int done = 0;
int state = init_state;
while (!done) {
if (!yaml_parser_parse(parser, &event)) {
fprintf(stderr, "Failed to parse configuration file: %s\n",
parser->problem);
exit(EXIT_FAILURE);
}
if (event.type == YAML_SCALAR_EVENT) {
if (state) {
ConfNode *new;
new = ConfNodeNew();
if (new == NULL) {
SCLogError(SC_ERR_MEM_ALLOC,
"Failed to allocate memory for new configuration node.");
exit(EXIT_FAILURE);
}
new->val = strdup((char *)event.data.scalar.value);
TAILQ_INSERT_TAIL(&node->head, new, next);
}
else {
node = ConfNodeNew();
if (node == NULL) {
SCLogError(SC_ERR_MEM_ALLOC,
"Failed to allocate memory for new configuration node.");
exit(EXIT_FAILURE);
}
node->val = strdup((char *)event.data.scalar.value);
TAILQ_INSERT_TAIL(&parent->head, node, next);
}
state ^= CONF_VAL;
}
else if (event.type == YAML_SEQUENCE_START_EVENT) {
state = CONF_SEQ;
}
else if (event.type == YAML_SEQUENCE_END_EVENT) {
state = CONF_KEY;
/* Only b/c we called from the old parser... */
if (init_state != CONF_KEY)
return;
}
else if (event.type == YAML_MAPPING_START_EVENT) {
ConfYamlParse2(parser, node, 0);
state ^= CONF_VAL;
}
else if (event.type == YAML_MAPPING_END_EVENT) {
done = 1;
}
else if (event.type == YAML_STREAM_END_EVENT) {
done = 1;
}
yaml_event_delete(&event);
}
}
/** /**
* \brief Process a YAML parser. * \brief Process a YAML parser.
* *
@ -96,38 +172,39 @@ ConfYamlParse(yaml_parser_t *parser)
parser->problem); parser->problem);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (level > -1) {
SCLogDebug("current key: %s", GetKeyName(key, level));
}
switch (event.type) { switch (event.type) {
case YAML_STREAM_START_EVENT: case YAML_STREAM_START_EVENT:
DPRINT_STATE(("YAML_STREAM_START_EVENT"));
break; break;
case YAML_STREAM_END_EVENT: case YAML_STREAM_END_EVENT:
DPRINT_STATE(("YAML_STREAM_END_EVENT"));
done = 1; done = 1;
break; break;
case YAML_DOCUMENT_START_EVENT: case YAML_DOCUMENT_START_EVENT:
DPRINT_STATE(("YAML_STREAM_END_EVENT"));
/* Ignored. */ /* Ignored. */
break; break;
case YAML_DOCUMENT_END_EVENT: case YAML_DOCUMENT_END_EVENT:
DPRINT_STATE(("YAML_DOCUMENT_END_EVENT"));
/* Ignored. */ /* Ignored. */
break; break;
case YAML_SEQUENCE_START_EVENT: case YAML_SEQUENCE_START_EVENT: {
DPRINT_STATE(("YAML_SEQUENCE_START_EVENT")); ConfNode *new;
inseq = 1; new = ConfNodeNew();
if (new == NULL) {
SCLogError(SC_ERR_MEM_ALLOC,
"Failed to allocate new configuration node.");
exit(EXIT_FAILURE);
}
new->name = strdup(GetKeyName(key, level));
ConfYamlParse2(parser, new, CONF_SEQ);
ConfSetNode(new);
state = CONF_KEY;
break; break;
}
case YAML_SEQUENCE_END_EVENT: case YAML_SEQUENCE_END_EVENT:
DPRINT_STATE(("YAML_SEQUENCE_END_EVENT"));
inseq = 0;
break; break;
case YAML_MAPPING_START_EVENT: case YAML_MAPPING_START_EVENT:
DPRINT_STATE(("YAML_MAPPING_START_EVENT"));
level++; level++;
if (level == MAX_LEVELS) { if (level == MAX_LEVELS) {
fprintf(stderr, "Reached maximum configuration nesting level.\n"); fprintf(stderr,
"Reached maximum configuration nesting level.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -136,7 +213,6 @@ ConfYamlParse(yaml_parser_t *parser)
break; break;
case YAML_MAPPING_END_EVENT: case YAML_MAPPING_END_EVENT:
DPRINT_STATE(("YAML_MAPPING_END_EVENT"));
if (level > -1) { if (level > -1) {
free(key[level]); free(key[level]);
key[level] = NULL; key[level] = NULL;
@ -144,13 +220,6 @@ ConfYamlParse(yaml_parser_t *parser)
level--; level--;
break; break;
case YAML_SCALAR_EVENT: case YAML_SCALAR_EVENT:
DPRINT_STATE(("YAML_SCALAR_EVENT"));
if (inseq) {
if (level > -1) {
SCLogDebug("ignoring sequence value for %s", GetKeyName(key, level));
}
break;
}
if (state == CONF_KEY) { if (state == CONF_KEY) {
if (key[level] != NULL) if (key[level] != NULL)
free(key[level]); free(key[level]);
@ -166,10 +235,8 @@ ConfYamlParse(yaml_parser_t *parser)
} }
break; break;
case YAML_ALIAS_EVENT: case YAML_ALIAS_EVENT:
DPRINT_STATE(("YAML_ALIAS_EVENT"));
break; break;
case YAML_NO_EVENT: case YAML_NO_EVENT:
DPRINT_STATE(("YAML_NO_EVENT"));
break; break;
} }
yaml_event_delete(&event); yaml_event_delete(&event);
@ -218,3 +285,56 @@ ConfYamlLoadString(const u_char *string, size_t len)
ConfYamlParse(&parser); ConfYamlParse(&parser);
yaml_parser_delete(&parser); yaml_parser_delete(&parser);
} }
#ifdef UNITTESTS
static int
ConfYamlRuleFileTest(void)
{
char input[] = "\
some-other-list:\n\
- one\n\
- two\n\
rule-files:\n\
- netbios.rules\n\
- x11.rules\n\
\n\
default-log-dir: /tmp\n\
";
ConfNode *node;
ConfYamlLoadString((u_char *)input, strlen(input));
node = ConfGetNode("rule-files");
if (node == NULL)
return 0;
if (TAILQ_EMPTY(&node->head))
return 0;
int i = 0;
ConfNode *filename;
TAILQ_FOREACH(filename, &node->head, next) {
if (i == 0) {
if (strcmp(filename->val, "netbios.rules") != 0)
return 0;
}
else if (i == 1) {
if (strcmp(filename->val, "x11.rules") != 0)
return 0;
}
else {
return 0;
}
i++;
}
return 1;
}
#endif /* UNITTESTS */
void
ConfYamlRegisterTests(void)
{
#ifdef UNITTESTS
UtRegisterTest("ConfYamlRuleFileTest", ConfYamlRuleFileTest, 1);
#endif /* UNITTESTS */
}

@ -4,5 +4,6 @@
#define __CONF_YAML_LOADER_H__ #define __CONF_YAML_LOADER_H__
void ConfYamlLoadFile(const char *); void ConfYamlLoadFile(const char *);
void ConfYamlRegisterTests(void);
#endif /* !__CONF_YAML_LOADER_H__ */ #endif /* !__CONF_YAML_LOADER_H__ */

@ -9,7 +9,7 @@
* configuration data. Allowing run time changes to the configuration * configuration data. Allowing run time changes to the configuration
* will require some locks. * will require some locks.
* *
* \author Endace Technology Limited * \author Endace Technology Limited - Jason Ish <jason.ish@endace.com>
* *
* \todo Consider using HashListTable to allow easy dumping of all data. * \todo Consider using HashListTable to allow easy dumping of all data.
*/ */
@ -24,16 +24,6 @@
static HashTable *conf_hash = NULL; static HashTable *conf_hash = NULL;
/**
* Structure of a configuration parameter.
*/
typedef struct ConfNode_ {
char *name;
char *val;
int allow_override;
} ConfNode;
/** /**
* \brief Function to generate the hash of a configuration value. * \brief Function to generate the hash of a configuration value.
* *
@ -81,10 +71,7 @@ static void ConfHashFree(void *data)
{ {
ConfNode *cn = (ConfNode *)data; ConfNode *cn = (ConfNode *)data;
SCLogDebug("freeing configuration parameter '%s'", cn->name); ConfNodeFree(cn);
free(cn->name);
free(cn->val);
free(cn);
} }
/** /**
@ -109,6 +96,91 @@ ConfInit(void)
SCLogDebug("configuration module initialized"); SCLogDebug("configuration module initialized");
} }
/**
* \brief Allocate a new configuration node.
*
* \retval An allocated configuration node on success, NULL on failure.
*/
ConfNode *
ConfNodeNew(void)
{
ConfNode *new;
new = calloc(1, sizeof(*new));
if (new == NULL)
return NULL;
TAILQ_INIT(&new->head);
return new;
}
/**
* \brief Free a ConfNode and all of its children.
*
* \param node The configuration node to free.
*/
void
ConfNodeFree(ConfNode *node)
{
ConfNode *tmp;
TAILQ_FOREACH(tmp, &node->head, next)
ConfNodeFree(tmp);
if (node->name != NULL)
free(node->name);
if (node->val != NULL)
free(node->val);
free(node);
}
/**
* \brief Set a configuration node.
*
* \retval 1 on success, 0 on failure.
*/
int
ConfSetNode(ConfNode *node)
{
ConfNode lookup;
ConfNode *pnode;
lookup.name = node->name;
pnode = HashTableLookup(conf_hash, &lookup, sizeof(lookup));
if (pnode != NULL) {
if (!pnode->allow_override) {
return 0;
}
HashTableRemove(conf_hash, pnode, sizeof(*pnode));
}
if (HashTableAdd(conf_hash, node, sizeof(*node)) != 0) {
SCLogError(SC_ERR_MEM_ALLOC, "Failed to add new configuration node.");
exit(EXIT_FAILURE);
}
return 1;
}
/**
* \brief Get a ConfNode by key.
*
* \param key The lookup key of the node to find.
*
* \retval The node matching the key or NULL if not found.
*/
ConfNode *
ConfGetNode(char *key)
{
ConfNode lookup;
ConfNode *node;
lookup.name = key;
node = HashTableLookup(conf_hash, &lookup, sizeof(lookup));
return node;
}
/** /**
* \brief Set a configuration value. * \brief Set a configuration value.
* *
@ -132,7 +204,7 @@ ConfSet(char *name, char *val, int allow_override)
HashTableRemove(conf_hash, conf_node, sizeof(*conf_node)); HashTableRemove(conf_hash, conf_node, sizeof(*conf_node));
} }
conf_node = calloc(1, sizeof(*conf_node)); conf_node = ConfNodeNew();
if (conf_node == NULL) { if (conf_node == NULL) {
return 0; return 0;
} }
@ -280,6 +352,12 @@ ConfDump(void)
while (b != NULL) { while (b != NULL) {
cn = (ConfNode *)b->data; cn = (ConfNode *)b->data;
printf("%s=%s\n", cn->name, cn->val); printf("%s=%s\n", cn->name, cn->val);
if (!TAILQ_EMPTY(&cn->head)) {
ConfNode *n0;
TAILQ_FOREACH(n0, &cn->head, next) {
printf(".%s\n", n0->val);
}
}
b = b->next; b = b->next;
} }
} }
@ -323,6 +401,38 @@ ConfTestSetAndGet(void)
return 1; return 1;
} }
static int
ConfTestSetGetNode(void)
{
ConfNode *set;
ConfNode *get;
const char key[] = "some-key";
const char val[] = "some-val";
set = ConfNodeNew();
if (set == NULL)
return 0;
set->name = strdup(key);
set->val = strdup(val);
if (ConfSetNode(set) != 1)
return 0;
get = ConfGetNode(key);
if (get == NULL)
return 0;
if (strcmp(get->name, key) != 0)
return 0;
if (strcmp(get->val, val) != 0)
return 0;
ConfRemove(key);
get = ConfGetNode(key);
if (get != NULL)
return 0;
return 1;
}
/** /**
* Test that overriding a value is allowed provided allow_override is * Test that overriding a value is allowed provided allow_override is
* true and that the config parameter gets the new value. * true and that the config parameter gets the new value.
@ -465,6 +575,7 @@ void
ConfRegisterTests(void) ConfRegisterTests(void)
{ {
UtRegisterTest("ConfTestGetNonExistant", ConfTestGetNonExistant, 1); UtRegisterTest("ConfTestGetNonExistant", ConfTestGetNonExistant, 1);
UtRegisterTest("ConfTestSetGetNode", ConfTestSetGetNode, 1);
UtRegisterTest("ConfTestSetAndGet", ConfTestSetAndGet, 1); UtRegisterTest("ConfTestSetAndGet", ConfTestSetAndGet, 1);
UtRegisterTest("ConfTestOverrideValue1", ConfTestOverrideValue1, 1); UtRegisterTest("ConfTestOverrideValue1", ConfTestOverrideValue1, 1);
UtRegisterTest("ConfTestOverrideValue2", ConfTestOverrideValue2, 1); UtRegisterTest("ConfTestOverrideValue2", ConfTestOverrideValue2, 1);

@ -7,6 +7,22 @@
#ifndef __CONF_H__ #ifndef __CONF_H__
#define __CONF_H__ #define __CONF_H__
#include "queue.h"
/**
* Structure of a configuration parameter.
*/
typedef struct ConfNode_ {
char *name;
char *val;
int allow_override;
TAILQ_HEAD(, ConfNode_) head;
TAILQ_ENTRY(ConfNode_) next;
} ConfNode;
/** /**
* The default log directory. * The default log directory.
*/ */
@ -16,9 +32,13 @@ void ConfInit(void);
int ConfGet(char *name, char **vptr); int ConfGet(char *name, char **vptr);
int ConfGetInt(char *name, intmax_t *val); int ConfGetInt(char *name, intmax_t *val);
int ConfGetBool(char *name, int *val); int ConfGetBool(char *name, int *val);
int ConfSet(char *name, char *val, int allow_override); int ConfSet(char *name, char *val, int allow_override);
void ConfDump(void); void ConfDump(void);
void ConfNodeDump(ConfNode *node);
ConfNode *ConfNodeNew(void);
void ConfNodeFree(ConfNode *);
int ConfSetNode(ConfNode *node);
ConfNode *ConfGetNode(char *key);
void ConfRegisterTests(); void ConfRegisterTests();
#endif /* ! __CONF_H__ */ #endif /* ! __CONF_H__ */

@ -453,6 +453,7 @@ int main(int argc, char **argv)
DecodeGRERegisterTests(); DecodeGRERegisterTests();
AlpDetectRegisterTests(); AlpDetectRegisterTests();
ConfRegisterTests(); ConfRegisterTests();
ConfYamlRegisterTests();
TmqhFlowRegisterTests(); TmqhFlowRegisterTests();
FlowRegisterTests(); FlowRegisterTests();
SCSigRegisterSignatureOrderingTests(); SCSigRegisterSignatureOrderingTests();

Loading…
Cancel
Save