#include #include #include #include #include #include #include #include #include #include #include "netconsole.h" #include "netdumpclient.h" #include "configuration.h" #include "server.h" NetdumpConfiguration config; char *netdump_dir_prefix = NETDUMP_DIR_PREFIX; enum ConfigType { CONFIG_NONE, CONFIG_BOOLEAN, CONFIG_INT, CONFIG_UINT32, CONFIG_UINT16, CONFIG_STRING }; struct ConfigData { char *name; enum ConfigType type; int offset; void *default_value; }; /* retrive a structure offset */ #ifdef offsetof #define CONFIG_OFFSET(field) ((int) offsetof (NetdumpConfiguration, field)) #else /* !offsetof */ #define CONFIG_OFFSET(field) ((int) ((char*) &((NetdumpConfiguration *) 0)->field)) #endif /* !offsetof */ struct ConfigData config_data[] = { { "port", CONFIG_UINT16, CONFIG_OFFSET(port), GINT_TO_POINTER (NETDUMP_PORT) }, { "max_concurrent_dumps", CONFIG_INT, CONFIG_OFFSET(max_concurrent_dumps), GINT_TO_POINTER (4) }, { "daemon", CONFIG_BOOLEAN, CONFIG_OFFSET(daemon), GINT_TO_POINTER (0) }, { "pidfile", CONFIG_STRING, CONFIG_OFFSET(pidfile), NULL }, { "dumpdirprefix", CONFIG_STRING, CONFIG_OFFSET(dumpdirprefix), NETDUMP_DIR_PREFIX }, { "secure", CONFIG_INT, CONFIG_OFFSET(secure), GINT_TO_POINTER (1) }, { "space_check", CONFIG_INT, CONFIG_OFFSET(space_check), GINT_TO_POINTER (1) }, }; #define NUM_CONFIG_DATA (sizeof(config_data)/sizeof(struct ConfigData)) static const GScannerConfig netdump_config_scanner_config = { ( " \t\n" ) /* cset_skip_characters */, ( G_CSET_a_2_z "_" G_CSET_A_2_Z ) /* cset_identifier_first */, ( G_CSET_a_2_z "_-0123456789" G_CSET_A_2_Z ) /* cset_identifier_nth */, ( "#\n" ) /* cpair_comment_single */, TRUE /* case_sensitive */, FALSE /* skip_comment_multi */, TRUE /* skip_comment_single */, FALSE /* scan_comment_multi */, TRUE /* scan_identifier */, TRUE /* scan_identifier_1char */, FALSE /* scan_identifier_NULL */, TRUE /* scan_symbols */, FALSE /* scan_binary */, FALSE /* scan_octal */, TRUE /* scan_float */, TRUE /* scan_hex */, FALSE /* scan_hex_dollar */, FALSE /* scan_string_sq */, TRUE /* scan_string_dq */, TRUE /* numbers_2_int */, FALSE /* int_2_float */, FALSE /* identifier_2_string */, TRUE /* char_2_token */, FALSE /* symbol_2_token */, FALSE /* scope_0_fallback */, }; typedef enum { CONFIG_TOKEN_BOOLEAN = G_TOKEN_LAST } PrefsTokenType; static void config_set_defaults(void) { int i; char *ptr; for (i=0;ivalue.v_symbol); token = g_scanner_get_next_token(scanner); if (token != G_TOKEN_EQUAL_SIGN) return G_TOKEN_EQUAL_SIGN; token = g_scanner_get_next_token(scanner); ptr = (unsigned char *)&config + config_data[symbol_nr].offset; switch (config_data[symbol_nr].type) { case CONFIG_BOOLEAN: if (token != G_TOKEN_IDENTIFIER) return G_TOKEN_IDENTIFIER; if (strcasecmp(scanner->value.v_string, "true")==0) *(int *)ptr = 1; else *(int *)ptr = 0; break; case CONFIG_INT: if (token != G_TOKEN_INT) return G_TOKEN_INT; *(int *)ptr = scanner->value.v_int; break; case CONFIG_UINT32: if (token != G_TOKEN_INT) return G_TOKEN_INT; *(guint32 *)ptr = scanner->value.v_int; break; case CONFIG_UINT16: if (token != G_TOKEN_INT) return G_TOKEN_INT; *(guint16 *)ptr = scanner->value.v_int; break; case CONFIG_STRING: if (token != G_TOKEN_STRING) return G_TOKEN_STRING; if (*(char **)ptr != NULL) free(*(char **)ptr); *(char **)ptr = (char *)malloc(strlen(scanner->value.v_string) + 1); if (*(char **)ptr != NULL) { strncpy(*(char **)ptr, scanner->value.v_string, strlen(scanner->value.v_string)); (*(char **)ptr)[strlen(scanner->value.v_string)] = '\0'; } else { syslog(LOG_ERR, "Cannot malloc\n"); exit(1); } break; case CONFIG_NONE: break; } return G_TOKEN_NONE; } static void msg_handler (GScanner *scanner, gchar *message, gint is_error) { char *msg; g_return_if_fail (scanner != NULL); msg = g_strdup_printf ("Error parsing %s at line %d: %s", scanner->input_name, scanner->line, message); if (is_error) syslog (LOG_ERR, "%s", msg); else syslog (LOG_WARNING, "%s", msg); fprintf (stderr, "%s\n", msg); g_free (msg); } static void config_load (const char *filename) { int i; int fd; GScanner *scanner; guint expected_token; fd = open(filename, O_RDONLY); if (fd < 0) { return; } scanner = g_scanner_new ((GScannerConfig *) &netdump_config_scanner_config); g_scanner_input_file (scanner, fd); scanner->input_name = filename; scanner->msg_handler = msg_handler; g_scanner_freeze_symbol_table(scanner); for (i = 0; i < NUM_CONFIG_DATA; i++) if (config_data[i].type != CONFIG_NONE) { g_scanner_add_symbol(scanner, config_data[i].name, GINT_TO_POINTER(i)); } g_scanner_thaw_symbol_table(scanner); while (1) { if (g_scanner_peek_next_token(scanner) == G_TOKEN_EOF) { break; } expected_token = config_parse_line(scanner); if (expected_token != G_TOKEN_NONE) { gchar *symbol_name; gchar *msg; msg = NULL; symbol_name = NULL; g_scanner_unexp_token (scanner, expected_token, NULL, "keyword", symbol_name, msg, TRUE); } } g_scanner_destroy (scanner); close(fd); } static int intarg; static struct poptOption optionsTable[] = { { "port", 'p', POPT_ARG_INT, &intarg, 'p', "ip port to listen on", "6666" }, { "concurrent", 'c', POPT_ARG_INT, &config.max_concurrent_dumps, 0, "max number of concurrent dumps", "4" }, { "daemon", 'd', POPT_ARG_NONE, &config.daemon, 0, "run in background as a daemon", NULL }, { "pidfile", 'P', POPT_ARG_STRING, &config.pidfile, 0, "file in which to store the pid", "path" }, { "dumpdirprefix", 'D', POPT_ARG_STRING, &config.dumpdirprefix, 0, "dir in which to store dumps", "/var/spool/netdump" }, { "secure", 's', POPT_ARG_INT, &config.secure, 0, "use ssh to send client identification", "1" }, { "space_check", 'S', POPT_ARG_INT, &config.space_check, 0, "verify that space is available for the dumpfile", "1" }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0 } }; static void parse_argument (char c) { switch (c) { case 'p': config.port = intarg; break; } } void config_init (int argc, char *argv[]) { signed char c; poptContext optCon; /* context for parsing command-line options */ /* Set the default values */ config_set_defaults(); config_load ("/usr/local/etc/netdump.conf"); optCon = poptGetContext("netdump-server", argc, (const char **)argv, optionsTable, 0); while ((c = poptGetNextOpt(optCon)) >= 0) parse_argument (c); }