mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.5 KiB
C
207 lines
5.5 KiB
C
16 years ago
|
/* Copyright (c) 2009 Open Information Security Foundation */
|
||
|
|
||
|
/**
|
||
|
* \file
|
||
|
*
|
||
|
* \author Endace Technology Limited - Jason Ish <jason.ish@endace.com>
|
||
|
*
|
||
|
* YAML configuration loader.
|
||
|
*/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#include <yaml.h>
|
||
|
|
||
|
#include "conf.h"
|
||
|
|
||
|
#undef YAML_LOADER_DEBUG
|
||
|
#ifdef YAML_LOADER_DEBUG
|
||
|
#define DPRINTF(x) do { printf x ; } while (0)
|
||
|
#else
|
||
|
#define DPRINTF(x)
|
||
|
#endif /* YAML_LOADER_DEBUG */
|
||
|
|
||
|
/* Define to print the current YAML state. */
|
||
|
#undef PRINT_STATES
|
||
|
#ifdef PRINT_STATES
|
||
|
#define DPRINT_STATE(x) do { printf x ; } while (0)
|
||
|
#else
|
||
|
#define DPRINT_STATE(x)
|
||
|
#endif /* PRINT_STATES */
|
||
|
|
||
|
/* Defines the maximum number of levels YAML may nest. This is
|
||
|
* primarily used for construction of lookup-keys for configuration
|
||
|
* values. */
|
||
|
#define MAX_LEVELS 16
|
||
|
|
||
|
/* Configuration processing states. */
|
||
|
enum conf_state {
|
||
|
CONF_KEY = 0,
|
||
|
CONF_VAL,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* \brief Return the name of the current configuration key value.
|
||
|
*
|
||
|
* This function returns the current value of the configuration key.
|
||
|
* This is all the key components joined together with a ".".
|
||
|
*
|
||
|
* NOTE: This function is not re-entrant safe, but we do not expect to
|
||
|
* be loading configuration files concurrently.
|
||
|
*/
|
||
|
static char *
|
||
|
GetKeyName(char **key, int level)
|
||
|
{
|
||
|
/* Statically allocate a string that should be large enough. */
|
||
|
static char print_key[1024];
|
||
|
int i;
|
||
|
|
||
|
print_key[0] = '\0';
|
||
|
|
||
|
for (i = 0; i <= level; i++) {
|
||
|
if (key[i] == NULL)
|
||
|
break;
|
||
|
if (strlen(key[i]) + strlen(print_key) + 2 > sizeof(print_key)) {
|
||
|
/* Overflow. */
|
||
|
return NULL;
|
||
|
}
|
||
|
else {
|
||
|
strncat(print_key, key[i], strlen(key[i]));
|
||
|
if (i < level)
|
||
|
strncat(print_key, ".", 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return print_key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* \brief Load a configuration file.
|
||
|
*
|
||
|
* Loads the IDS configuration file. On failure, the program will
|
||
|
* exist with an error message.
|
||
|
*
|
||
|
* \param filename Name of the filename to load.
|
||
|
*/
|
||
|
void
|
||
|
LoadYamlConf(const char *filename)
|
||
|
{
|
||
|
FILE *conf_file;
|
||
|
yaml_parser_t parser;
|
||
|
yaml_event_t event;
|
||
|
int done;
|
||
|
int level;
|
||
|
int state;
|
||
|
int inseq;
|
||
|
char *key[MAX_LEVELS];
|
||
|
|
||
|
memset(key, 0, sizeof(key));
|
||
|
|
||
|
if (yaml_parser_initialize(&parser) != 1) {
|
||
|
fprintf(stderr, "Failed to initialize yaml parser.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
conf_file = fopen(filename, "r");
|
||
|
if (conf_file == NULL) {
|
||
|
fprintf(stderr, "Failed to open file: %s: %s\n", filename,
|
||
|
strerror(errno));
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
yaml_parser_set_input_file(&parser, conf_file);
|
||
|
|
||
|
state = CONF_KEY;
|
||
|
done = 0;
|
||
|
level = -1;
|
||
|
inseq = 0;
|
||
|
while (!done) {
|
||
|
if (!yaml_parser_parse(&parser, &event)) {
|
||
|
fprintf(stderr, "Failed to parse configuration file: %s\n",
|
||
|
parser.problem);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
if (level > -1) {
|
||
|
DPRINTF(("Current key: %s\n", GetKeyName(key, level)));
|
||
|
}
|
||
|
switch (event.type) {
|
||
|
case YAML_STREAM_START_EVENT:
|
||
|
DPRINT_STATE(("YAML_STREAM_START_EVENT\n"));
|
||
|
break;
|
||
|
case YAML_STREAM_END_EVENT:
|
||
|
DPRINT_STATE(("YAML_STREAM_END_EVENT\n"));
|
||
|
done = 1;
|
||
|
break;
|
||
|
case YAML_DOCUMENT_START_EVENT:
|
||
|
DPRINT_STATE(("YAML_STREAM_END_EVENT\n"));
|
||
|
/* Ignored. */
|
||
|
break;
|
||
|
case YAML_DOCUMENT_END_EVENT:
|
||
|
DPRINT_STATE(("YAML_DOCUMENT_END_EVENT\n"));
|
||
|
/* Ignored. */
|
||
|
break;
|
||
|
case YAML_SEQUENCE_START_EVENT:
|
||
|
DPRINT_STATE(("YAML_SEQUENCE_START_EVENT\n"));
|
||
|
inseq = 1;
|
||
|
break;
|
||
|
case YAML_SEQUENCE_END_EVENT:
|
||
|
DPRINT_STATE(("YAML_SEQUENCE_END_EVENT\n"));
|
||
|
inseq = 0;
|
||
|
break;
|
||
|
case YAML_MAPPING_START_EVENT:
|
||
|
DPRINT_STATE(("YAML_MAPPING_START_EVENT\n"));
|
||
|
level++;
|
||
|
if (level == MAX_LEVELS) {
|
||
|
fprintf(stderr, "Reached maximum configuration nesting level.\n");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
/* Since we are entering a new mapping, state goes back to key. */
|
||
|
state = CONF_KEY;
|
||
|
|
||
|
break;
|
||
|
case YAML_MAPPING_END_EVENT:
|
||
|
DPRINT_STATE(("YAML_MAPPING_END_EVENT\n"));
|
||
|
if (level > -1) {
|
||
|
free(key[level]);
|
||
|
key[level] = NULL;
|
||
|
}
|
||
|
level--;
|
||
|
break;
|
||
|
case YAML_SCALAR_EVENT:
|
||
|
DPRINT_STATE(("YAML_SCALAR_EVENT\n"));
|
||
|
if (inseq) {
|
||
|
printf("Ignoring sequence value for %s\n",
|
||
|
GetKeyName(key, level));
|
||
|
break;
|
||
|
}
|
||
|
if (state == CONF_KEY) {
|
||
|
if (key[level] != NULL)
|
||
|
free(key[level]);
|
||
|
key[level] = strdup((char *)event.data.scalar.value);
|
||
|
|
||
|
/* Move state to expecting a value. */
|
||
|
state = CONF_VAL;
|
||
|
}
|
||
|
else if (state == CONF_VAL) {
|
||
|
ConfSet(GetKeyName(key, level), (char *)event.data.scalar.value,
|
||
|
1);
|
||
|
state = CONF_KEY;
|
||
|
}
|
||
|
break;
|
||
|
case YAML_ALIAS_EVENT:
|
||
|
DPRINT_STATE(("YAML_ALIAS_EVENT\n"));
|
||
|
break;
|
||
|
case YAML_NO_EVENT:
|
||
|
DPRINT_STATE(("YAML_NO_EVENT\n"));
|
||
|
break;
|
||
|
}
|
||
|
yaml_event_delete(&event);
|
||
|
}
|
||
|
|
||
|
yaml_parser_delete(&parser);
|
||
|
fclose(conf_file);
|
||
|
}
|