diff --git a/src/Makefile.am b/src/Makefile.am index a686535e5f..0b7cacd4c6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -156,7 +156,8 @@ app-layer-smb.c app-layer-smb.h \ app-layer-smb2.c app-layer-smb2.h \ app-layer-dcerpc.c app-layer-dcerpc.h \ app-layer-ftp.c app-layer-ftp.h \ -defrag.c defrag.h +defrag.c defrag.h \ +output.c output.h # set the include path found by configure INCLUDES= $(all_includes) diff --git a/src/alert-debuglog.c b/src/alert-debuglog.c index 740238b004..44e58e68e9 100644 --- a/src/alert-debuglog.c +++ b/src/alert-debuglog.c @@ -26,6 +26,9 @@ #include "util-debug.h" +#include "output.h" +#include "alert-debuglog.h" + #define DEFAULT_LOG_FILENAME "alert-debug.log" TmEcode AlertDebuglog (ThreadVars *, Packet *, void *, PacketQueue *); @@ -43,6 +46,8 @@ void TmModuleAlertDebuglogRegister (void) { tmm_modules[TMM_ALERTDEBUGLOG].ThreadExitPrintStats = AlertDebuglogExitPrintStats; tmm_modules[TMM_ALERTDEBUGLOG].ThreadDeinit = AlertDebuglogThreadDeinit; tmm_modules[TMM_ALERTDEBUGLOG].RegisterTests = NULL; + + OutputRegisterModule("AlertDebuglog", "alert-debug", AlertDebuglogInitCtx); } typedef struct AlertDebuglogThread_ { diff --git a/src/alert-fastlog.c b/src/alert-fastlog.c index 32c98d91d1..d91ff9f393 100644 --- a/src/alert-fastlog.c +++ b/src/alert-fastlog.c @@ -30,6 +30,9 @@ #include "detect-engine-mpm.h" #include "util-classification-config.h" +#include "output.h" +#include "alert-fastlog.h" + #define DEFAULT_LOG_FILENAME "fast.log" TmEcode AlertFastlog (ThreadVars *, Packet *, void *, PacketQueue *); @@ -48,6 +51,8 @@ void TmModuleAlertFastlogRegister (void) { tmm_modules[TMM_ALERTFASTLOG].ThreadExitPrintStats = AlertFastlogExitPrintStats; tmm_modules[TMM_ALERTFASTLOG].ThreadDeinit = AlertFastlogThreadDeinit; tmm_modules[TMM_ALERTFASTLOG].RegisterTests = AlertFastLogRegisterTests; + + OutputRegisterModule("AlertFastlog", "fast", AlertFastlogInitCtx); } void TmModuleAlertFastlogIPv4Register (void) { diff --git a/src/alert-unified-alert.c b/src/alert-unified-alert.c index 214647e5fa..f3f40523d5 100644 --- a/src/alert-unified-alert.c +++ b/src/alert-unified-alert.c @@ -27,6 +27,9 @@ #include "util-error.h" #include "util-debug.h" +#include "output.h" +#include "alert-unified-alert.h" + #define DEFAULT_LOG_FILENAME "unified.alert" TmEcode AlertUnifiedAlert (ThreadVars *, Packet *, void *, PacketQueue *); @@ -41,6 +44,9 @@ void TmModuleAlertUnifiedAlertRegister (void) { tmm_modules[TMM_ALERTUNIFIEDALERT].Func = AlertUnifiedAlert; tmm_modules[TMM_ALERTUNIFIEDALERT].ThreadDeinit = AlertUnifiedAlertThreadDeinit; tmm_modules[TMM_ALERTUNIFIEDALERT].RegisterTests = AlertUnifiedAlertRegisterTests; + + OutputRegisterModule("AlertUnifiedAlert", "unified-alert", + AlertUnifiedAlertInitCtx); } typedef struct AlertUnifiedAlertThread_ { diff --git a/src/alert-unified-log.c b/src/alert-unified-log.c index a39bfabec2..ba15e32222 100644 --- a/src/alert-unified-log.c +++ b/src/alert-unified-log.c @@ -29,6 +29,9 @@ #include "util-debug.h" #include "util-error.h" +#include "output.h" +#include "alert-unified-log.h" + #define DEFAULT_LOG_FILENAME "unified.log" TmEcode AlertUnifiedLog (ThreadVars *, Packet *, void *, PacketQueue *); @@ -43,6 +46,9 @@ void TmModuleAlertUnifiedLogRegister (void) { tmm_modules[TMM_ALERTUNIFIEDLOG].Func = AlertUnifiedLog; tmm_modules[TMM_ALERTUNIFIEDLOG].ThreadDeinit = AlertUnifiedLogThreadDeinit; tmm_modules[TMM_ALERTUNIFIEDLOG].RegisterTests = AlertUnifiedLogRegisterTests; + + OutputRegisterModule("AlertUnifiedLog", "unified-log", + AlertUnifiedLogInitCtx); } typedef struct AlertUnifiedLogThread_ { diff --git a/src/alert-unified2-alert.c b/src/alert-unified2-alert.c index 333304fd57..9643aa5aac 100644 --- a/src/alert-unified2-alert.c +++ b/src/alert-unified2-alert.c @@ -21,6 +21,10 @@ #include "util-error.h" #include "util-debug.h" #include "util-time.h" + +#include "output.h" +#include "alert-unified2-alert.h" + #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif @@ -126,6 +130,9 @@ void TmModuleUnified2AlertRegister (void) { tmm_modules[TMM_ALERTUNIFIED2ALERT].Func = Unified2Alert; tmm_modules[TMM_ALERTUNIFIED2ALERT].ThreadDeinit = Unified2AlertThreadDeinit; tmm_modules[TMM_ALERTUNIFIED2ALERT].RegisterTests = Unified2RegisterTests; + + OutputRegisterModule("Unified2Alert", "unified2-alert", + Unified2AlertInitCtx); } /** diff --git a/src/log-httplog.c b/src/log-httplog.c index 8d4e228733..4f34ab7e81 100644 --- a/src/log-httplog.c +++ b/src/log-httplog.c @@ -20,6 +20,9 @@ #include "util-debug.h" +#include "output.h" +#include "log-httplog.h" + #define DEFAULT_LOG_FILENAME "http.log" TmEcode LogHttplog (ThreadVars *, Packet *, void *, PacketQueue *); @@ -37,6 +40,8 @@ void TmModuleLogHttplogRegister (void) { tmm_modules[TMM_LOGHTTPLOG].ThreadExitPrintStats = LogHttplogExitPrintStats; tmm_modules[TMM_LOGHTTPLOG].ThreadDeinit = LogHttplogThreadDeinit; tmm_modules[TMM_LOGHTTPLOG].RegisterTests = NULL; + + OutputRegisterModule("LogHttplog", "http-log", LogHttplogInitCtx); } void TmModuleLogHttplogIPv4Register (void) { diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000000..2643d711de --- /dev/null +++ b/src/output.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2009 Open Information Security Foundation */ + +/** + * \file + * \author Endace Technology Limited, Jason Ish + */ + +#include "suricata-common.h" +#include "flow.h" +#include "conf.h" +#include "tm-modules.h" +#include "util-error.h" +#include "util-debug.h" +#include "output.h" + +static TAILQ_HEAD(, OutputModule_) output_modules = + TAILQ_HEAD_INITIALIZER(output_modules); + +/** + * \brief Register an output module. + * + * This function will register an output module so it can be + * configured with the configuration file. + * + * \retval Returns 0 on success, -1 on failure. + */ +void +OutputRegisterModule(char *name, char *conf_name, LogFileCtx *(*InitFunc)(ConfNode *)) +{ + OutputModule *module = calloc(1, sizeof(*module)); + if (module == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, + "Failed to allocated memory for new output module"); + exit(EXIT_FAILURE); + } + + module->name = strdup(name); + module->conf_name = strdup(conf_name); + module->InitFunc = InitFunc; + TAILQ_INSERT_TAIL(&output_modules, module, entries); + + SCLogInfo("Output module \"%s\" registered.", name); +} + +/** + * \brief Get an output module by name. + * + * \retval The OutputModule with the given name or NULL if no output module + * with the given name is registered. + */ +OutputModule * +OutputGetModuleByConfName(char *conf_name) +{ + OutputModule *module; + + TAILQ_FOREACH(module, &output_modules, entries) { + if (strcmp(module->conf_name, conf_name) == 0) + return module; + } + + return NULL; +} + +/** + * \brief Deregister all modules. Useful for a memory clean exit. + */ +void +OutputDeregisterAll(void) +{ + OutputModule *module; + + while ((module = TAILQ_FIRST(&output_modules))) { + TAILQ_REMOVE(&output_modules, module, entries); + free(module->name); + free(module->conf_name); + free(module); + } +} diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000000..c40eaa1c84 --- /dev/null +++ b/src/output.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2009 Open Information Security Foundation */ + +/** + * \file + * \author Endace Technology Limited, Jason Ish + */ + +#ifndef __OUTPUT_H__ +#define __OUTPUT_H__ + +typedef struct OutputModule_ { + char *name; + char *conf_name; + LogFileCtx *(*InitFunc)(ConfNode *); + + TAILQ_ENTRY(OutputModule_) entries; +} OutputModule; + +void OutputRegisterModule(char *, char *, LogFileCtx *(*)(ConfNode *)); +OutputModule *OutputGetModuleByConfName(char *name); +void OutputDeregisterAll(void); + +#endif /* ! __OUTPUT_H__ */ diff --git a/src/runmodes.c b/src/runmodes.c index 8bfbffdfca..ee0f23288d 100644 --- a/src/runmodes.c +++ b/src/runmodes.c @@ -22,6 +22,8 @@ #include "log-httplog.h" +#include "output.h" + /** * Define a linked list to use as a registry of LogFileCtx shutdown hooks. */ @@ -69,32 +71,6 @@ void RunModeShutDown(void) RunLogFileCtxShutDownHooks(); } -struct AlertOutput { - char *shortname; - char *longname; - LogFileCtx *(*InitFunc)(ConfNode *); -} alert_descriptor[] = { - {"fast", "AlertFastlog", AlertFastlogInitCtx}, - {"http-log", "LogHttplog", LogHttplogInitCtx}, - {"unified-log", "AlertUnifiedLog", AlertUnifiedLogInitCtx}, - {"unified-alert", "AlertUnifiedAlert", AlertUnifiedAlertInitCtx}, - {"unified2-alert", "Unified2Alert", Unified2AlertInitCtx}, - {"alert-debug", "AlertDebuglog", AlertDebuglogInitCtx}, -}; - -struct AlertOutput * -GetAlertOutputByName(char *name) -{ - int i; - - for (i = 0; i < sizeof(alert_descriptor)/sizeof(alert_descriptor[0]); i++) { - if (strcmp(alert_descriptor[i].shortname, name) == 0) - return &alert_descriptor[i]; - } - - return NULL; -} - static void SetupOutputs(ThreadVars *tv_outputs) { ConfNode *outputs = ConfGetNode("outputs"); @@ -105,16 +81,18 @@ static void SetupOutputs(ThreadVars *tv_outputs) ConfNode *output, *output_config; TmModule *tm_module; - struct AlertOutput *output_info; const char *enabled; + TAILQ_FOREACH(output, &outputs->head, next) { - output_info = GetAlertOutputByName(output->val); - if (output_info == NULL) { - printf("Unknown output type: %s\n", output->val); + + OutputModule *module = OutputGetModuleByConfName(output->val); + if (module == NULL) { + SCLogWarning(SC_INVALID_ARGUMENT, + "No output module named %s, ignoring", output->val); continue; } - output_config = ConfNodeLookupChild(output, output_info->shortname); + output_config = ConfNodeLookupChild(output, module->conf_name); if (output_config == NULL) { /* Shouldn't happen. */ SCLogError(SC_INVALID_ARGUMENT, @@ -124,19 +102,16 @@ static void SetupOutputs(ThreadVars *tv_outputs) enabled = ConfNodeLookupChildValue(output_config, "enabled"); if (enabled != NULL && strcasecmp(enabled, "yes") == 0) { - LogFileCtx *logfile_ctx = output_info->InitFunc(output_config); + LogFileCtx *logfile_ctx = module->InitFunc(output_config); if (logfile_ctx == NULL) { /* In most cases the init function will have logged the - * error. */ + * error. Maybe we should exit on init errors? */ continue; } - if (logfile_ctx == NULL) { - printf("* fast_ctx is NULL\n"); - } - tm_module = TmModuleGetByName(output_info->longname); + tm_module = TmModuleGetByName(module->name); if (tm_module == NULL) { SCLogError(SC_INVALID_ARGUMENT, - "TmModuleGetByName for AlertFastlog failed"); + "TmModuleGetByName for %s failed", module->name); exit(EXIT_FAILURE); } TmVarSlotSetFuncAppend(tv_outputs, tm_module, logfile_ctx); diff --git a/src/suricata.c b/src/suricata.c index 987f517c8e..60b3db2bd2 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -88,6 +88,8 @@ #include "detect-engine-siggroup.h" #include "util-daemon.h" +#include "output.h" + /* * we put this here, because we only use it here in main. */ @@ -754,6 +756,7 @@ int main(int argc, char **argv) DetectEngineCtxFree(de_ctx); RunModeShutDown(); + OutputDeregisterAll(); exit(EXIT_SUCCESS); }