From 59ec05645fa186c4f91150ba464997a37868318e Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 22 Dec 2009 00:40:55 -0800 Subject: [PATCH] Index sequence items - allows us to store sequences of mappings in the configuration database. --- src/conf-yaml-loader.c | 140 ++++++++++++++++++++++++++++++----------- src/conf.c | 20 +++++- 2 files changed, 122 insertions(+), 38 deletions(-) diff --git a/src/conf-yaml-loader.c b/src/conf-yaml-loader.c index acf23614fa..89e02b43fc 100644 --- a/src/conf-yaml-loader.c +++ b/src/conf-yaml-loader.c @@ -27,6 +27,11 @@ * values. */ #define MAX_LEVELS 16 +/* Sometimes we'll have to create a node name on the fly (integer + * conversion, etc), so this is a default length to allocate that will + * work most of the time. */ +#define DEFAULT_NAME_LEN 16 + /* Configuration processing states. */ enum conf_state { CONF_KEY = 0, @@ -77,15 +82,15 @@ GetKeyName(char **key, int level) * * \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) +ConfYamlParse2(yaml_parser_t *parser, ConfNode *parent, int inseq) { ConfNode *node = parent; yaml_event_t event; int done = 0; - int state = init_state; + int state = 0; + int seq_idx = 0; while (!done) { if (!yaml_parser_parse(parser, &event)) { @@ -95,41 +100,44 @@ ConfYamlParse2(yaml_parser_t *parser, ConfNode *parent, int init_state) } 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); + char *value = (char *)event.data.scalar.value; + if (inseq) { + ConfNode *seq_node = ConfNodeNew(); + seq_node->name = calloc(1, DEFAULT_NAME_LEN); + snprintf(seq_node->name, DEFAULT_NAME_LEN, "%d", seq_idx++); + seq_node->val = strdup(value); + TAILQ_INSERT_TAIL(&parent->head, seq_node, next); } else { - node = ConfNodeNew(); - if (node == NULL) { - SCLogError(SC_ERR_MEM_ALLOC, - "Failed to allocate memory for new configuration node."); - exit(EXIT_FAILURE); + if (state == CONF_KEY) { + node = ConfNodeNew(); + node->name = strdup((char *)event.data.scalar.value); + TAILQ_INSERT_TAIL(&parent->head, node, next); + state = CONF_VAL; + } + else { + node->val = strdup((char *)event.data.scalar.value); + state = CONF_KEY; } - 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; + return; } else if (event.type == YAML_MAPPING_START_EVENT) { - ConfYamlParse2(parser, node, 0); + if (inseq) { + ConfNode *seq_node = ConfNodeNew(); + seq_node->name = calloc(1, DEFAULT_NAME_LEN); + snprintf(seq_node->name, DEFAULT_NAME_LEN, "%d", seq_idx++); + TAILQ_INSERT_TAIL(&node->head, seq_node, next); + ConfYamlParse2(parser, seq_node, 0); + } + else { + ConfYamlParse2(parser, node, inseq); + } state ^= CONF_VAL; } else if (event.type == YAML_MAPPING_END_EVENT) { @@ -187,13 +195,8 @@ ConfYamlParse(yaml_parser_t *parser) 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); + ConfYamlParse2(parser, new, 1); ConfSetNode(new); state = CONF_KEY; break; @@ -292,9 +295,6 @@ static int ConfYamlRuleFileTest(void) { char input[] = "\ -some-other-list:\n\ - - one\n\ - - two\n\ rule-files:\n\ - netbios.rules\n\ - x11.rules\n\ @@ -329,6 +329,73 @@ default-log-dir: /tmp\n\ return 1; } +static int +ConfYamlLoggingOutputTest(void) +{ + char input[] = "\ +logging:\n\ + output:\n\ + - interface: console\n\ + log-level: error\n\ + - interface: syslog\n\ + facility: local4\n\ + log-level: info\n\ +"; + + ConfYamlLoadString(input, strlen(input)); + + ConfNode *outputs; + outputs = ConfGetNode("logging.output"); + if (outputs == NULL) + return 0; + + ConfNode *output; + ConfNode *output_param; + + output = TAILQ_FIRST(&outputs->head); + if (output == NULL) + return 0; + if (strcmp(output->name, "0") != 0) + return 0; + output_param = TAILQ_FIRST(&output->head); + if (output_param == NULL) + return 0; + if (strcmp(output_param->name, "interface") != 0) + return 0; + if (strcmp(output_param->val, "console") != 0) + return 0; + output_param = TAILQ_NEXT(output_param, next); + if (strcmp(output_param->name, "log-level") != 0) + return 0; + if (strcmp(output_param->val, "error") != 0) + return 0; + + output = TAILQ_NEXT(output, next); + if (output == NULL) + return 0; + if (strcmp(output->name, "1") != 0) + return 0; + output_param = TAILQ_FIRST(&output->head); + if (output_param == NULL) + return 0; + if (strcmp(output_param->name, "interface") != 0) + return 0; + if (strcmp(output_param->val, "syslog") != 0) + return 0; + output_param = TAILQ_NEXT(output_param, next); + if (strcmp(output_param->name, "facility") != 0) + return 0; + if (strcmp(output_param->val, "local4") != 0) + return 0; + output_param = TAILQ_NEXT(output_param, next); + if (strcmp(output_param->name, "log-level") != 0) + return 0; + if (strcmp(output_param->val, "info") != 0) + return 0; + + return 1; +} + #endif /* UNITTESTS */ void @@ -336,5 +403,6 @@ ConfYamlRegisterTests(void) { #ifdef UNITTESTS UtRegisterTest("ConfYamlRuleFileTest", ConfYamlRuleFileTest, 1); + UtRegisterTest("ConfYamlLoggingOutputTest", ConfYamlLoggingOutputTest, 1); #endif /* UNITTESTS */ } diff --git a/src/conf.c b/src/conf.c index e76838a8d9..a95753c557 100644 --- a/src/conf.c +++ b/src/conf.c @@ -125,8 +125,11 @@ ConfNodeNew(void) ConfNode *new; new = calloc(1, sizeof(*new)); - if (new == NULL) - return NULL; + if (new == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, + "Error allocating memory for new configuration node"); + exit(EXIT_FAILURE); + } TAILQ_INIT(&new->head); return new; @@ -393,6 +396,19 @@ ConfDeInit(void) SCLogDebug("configuration module de-initialized"); } +void +ConfNodeDump(ConfNode *node) +{ + ConfNode *child; + int idx = 0; + + TAILQ_FOREACH(child, &node->head, next) { + printf("%s = %s\n", child->name, child->val); + if (child->val == NULL) + ConfNodeDump(child); + } +} + /** * \brief Dump configuration to stdout. */