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 15 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
# clusterid.
clusterid: 99
rule-files:
- netbios.rules
- x11.rules

@ -12,6 +12,7 @@
#include "eidps-common.h"
#include "conf.h"
#include "util-debug.h"
#include "util-unittest.h"
/* Define to print the current YAML state. */
#undef PRINT_STATES
@ -30,6 +31,7 @@
enum conf_state {
CONF_KEY = 0,
CONF_VAL,
CONF_SEQ,
};
/**
@ -67,6 +69,80 @@ GetKeyName(char **key, int level)
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.
*
@ -96,38 +172,39 @@ ConfYamlParse(yaml_parser_t *parser)
parser->problem);
exit(EXIT_FAILURE);
}
if (level > -1) {
SCLogDebug("current key: %s", GetKeyName(key, level));
}
switch (event.type) {
case YAML_STREAM_START_EVENT:
DPRINT_STATE(("YAML_STREAM_START_EVENT"));
break;
case YAML_STREAM_END_EVENT:
DPRINT_STATE(("YAML_STREAM_END_EVENT"));
done = 1;
break;
case YAML_DOCUMENT_START_EVENT:
DPRINT_STATE(("YAML_STREAM_END_EVENT"));
/* Ignored. */
break;
case YAML_DOCUMENT_END_EVENT:
DPRINT_STATE(("YAML_DOCUMENT_END_EVENT"));
/* Ignored. */
break;
case YAML_SEQUENCE_START_EVENT:
DPRINT_STATE(("YAML_SEQUENCE_START_EVENT"));
inseq = 1;
case YAML_SEQUENCE_START_EVENT: {
ConfNode *new;
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;
}
case YAML_SEQUENCE_END_EVENT:
DPRINT_STATE(("YAML_SEQUENCE_END_EVENT"));
inseq = 0;
break;
case YAML_MAPPING_START_EVENT:
DPRINT_STATE(("YAML_MAPPING_START_EVENT"));
level++;
if (level == MAX_LEVELS) {
fprintf(stderr, "Reached maximum configuration nesting level.\n");
fprintf(stderr,
"Reached maximum configuration nesting level.\n");
exit(EXIT_FAILURE);
}
@ -136,7 +213,6 @@ ConfYamlParse(yaml_parser_t *parser)
break;
case YAML_MAPPING_END_EVENT:
DPRINT_STATE(("YAML_MAPPING_END_EVENT"));
if (level > -1) {
free(key[level]);
key[level] = NULL;
@ -144,13 +220,6 @@ ConfYamlParse(yaml_parser_t *parser)
level--;
break;
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 (key[level] != NULL)
free(key[level]);
@ -166,10 +235,8 @@ ConfYamlParse(yaml_parser_t *parser)
}
break;
case YAML_ALIAS_EVENT:
DPRINT_STATE(("YAML_ALIAS_EVENT"));
break;
case YAML_NO_EVENT:
DPRINT_STATE(("YAML_NO_EVENT"));
break;
}
yaml_event_delete(&event);
@ -218,3 +285,56 @@ ConfYamlLoadString(const u_char *string, size_t len)
ConfYamlParse(&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__
void ConfYamlLoadFile(const char *);
void ConfYamlRegisterTests(void);
#endif /* !__CONF_YAML_LOADER_H__ */

@ -9,7 +9,7 @@
* configuration data. Allowing run time changes to the configuration
* 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.
*/
@ -24,16 +24,6 @@
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.
*
@ -81,10 +71,7 @@ static void ConfHashFree(void *data)
{
ConfNode *cn = (ConfNode *)data;
SCLogDebug("freeing configuration parameter '%s'", cn->name);
free(cn->name);
free(cn->val);
free(cn);
ConfNodeFree(cn);
}
/**
@ -109,6 +96,91 @@ ConfInit(void)
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.
*
@ -132,7 +204,7 @@ ConfSet(char *name, char *val, int allow_override)
HashTableRemove(conf_hash, conf_node, sizeof(*conf_node));
}
conf_node = calloc(1, sizeof(*conf_node));
conf_node = ConfNodeNew();
if (conf_node == NULL) {
return 0;
}
@ -280,6 +352,12 @@ ConfDump(void)
while (b != NULL) {
cn = (ConfNode *)b->data;
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;
}
}
@ -323,6 +401,38 @@ ConfTestSetAndGet(void)
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
* true and that the config parameter gets the new value.
@ -465,6 +575,7 @@ void
ConfRegisterTests(void)
{
UtRegisterTest("ConfTestGetNonExistant", ConfTestGetNonExistant, 1);
UtRegisterTest("ConfTestSetGetNode", ConfTestSetGetNode, 1);
UtRegisterTest("ConfTestSetAndGet", ConfTestSetAndGet, 1);
UtRegisterTest("ConfTestOverrideValue1", ConfTestOverrideValue1, 1);
UtRegisterTest("ConfTestOverrideValue2", ConfTestOverrideValue2, 1);

@ -7,6 +7,22 @@
#ifndef __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.
*/
@ -16,9 +32,13 @@ void ConfInit(void);
int ConfGet(char *name, char **vptr);
int ConfGetInt(char *name, intmax_t *val);
int ConfGetBool(char *name, int *val);
int ConfSet(char *name, char *val, int allow_override);
void ConfDump(void);
void ConfNodeDump(ConfNode *node);
ConfNode *ConfNodeNew(void);
void ConfNodeFree(ConfNode *);
int ConfSetNode(ConfNode *node);
ConfNode *ConfGetNode(char *key);
void ConfRegisterTests();
#endif /* ! __CONF_H__ */

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

Loading…
Cancel
Save