/* Copyright (C) 2007-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * version 2 along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ /** \file * * \author Victor Julien * * Pre-cooked threading runmodes. */ #include "suricata-common.h" #include "detect.h" #include "detect-engine.h" #include "detect-engine-mpm.h" #include "app-layer-parser.h" #include "tm-threads.h" #include "util-debug.h" #include "util-time.h" #include "util-cpu.h" #include "util-byte.h" #include "util-affinity.h" #include "conf.h" #include "queue.h" #include "runmodes.h" #include "runmode-af-packet.h" #include "runmode-af-xdp.h" #include "runmode-dpdk.h" #include "runmode-erf-dag.h" #include "runmode-erf-file.h" #include "runmode-ipfw.h" #include "runmode-napatech.h" #include "runmode-netmap.h" #include "runmode-nflog.h" #include "runmode-nfq.h" #include "runmode-pcap.h" #include "runmode-pcap-file.h" #include "runmode-pfring.h" #include "runmode-unix-socket.h" #include "runmode-windivert.h" #include "util-unittest.h" #include "util-misc.h" #include "util-plugin.h" #include "output.h" #include "alert-fastlog.h" #include "alert-debuglog.h" #include "log-httplog.h" #include "source-pfring.h" #include "tmqh-flow.h" #include "flow-manager.h" #include "flow-bypass.h" #include "counters.h" #include "suricata-plugin.h" int debuglog_enabled = 0; int threading_set_cpu_affinity = FALSE; uint64_t threading_set_stack_size = 0; /* Runmode Global Thread Names */ const char *thread_name_autofp = "RX"; const char *thread_name_single = "W"; const char *thread_name_workers = "W"; const char *thread_name_verdict = "TX"; const char *thread_name_flow_mgr = "FM"; const char *thread_name_flow_rec = "FR"; const char *thread_name_flow_bypass = "FB"; const char *thread_name_unix_socket = "US"; const char *thread_name_detect_loader = "DL"; const char *thread_name_counter_stats = "CS"; const char *thread_name_counter_wakeup = "CW"; /** * \brief Holds description for a runmode. */ typedef struct RunMode_ { /* the runmode type */ enum RunModes runmode; const char *name; const char *description; /* runmode function */ int (*RunModeFunc)(void); void (*RunModeIsIPSEnabled)(void); } RunMode; typedef struct RunModes_ { int cnt; RunMode *runmodes; } RunModes; static RunModes runmodes[RUNMODE_USER_MAX]; static char *active_runmode; /* free list for our outputs */ typedef struct OutputFreeList_ { OutputModule *output_module; OutputCtx *output_ctx; TAILQ_ENTRY(OutputFreeList_) entries; } OutputFreeList; static TAILQ_HEAD(, OutputFreeList_) output_free_list = TAILQ_HEAD_INITIALIZER(output_free_list); /** * \internal * \brief Translate a runmode mode to a printable string. * * \param runmode Runmode to be converted into a printable string. * * \retval string Printable string. */ static const char *RunModeTranslateModeToName(int runmode) { switch (runmode) { case RUNMODE_PCAP_DEV: return "PCAP_DEV"; case RUNMODE_PCAP_FILE: return "PCAP_FILE"; case RUNMODE_PFRING: #ifdef HAVE_PFRING return "PFRING"; #else return "PFRING(DISABLED)"; #endif case RUNMODE_PLUGIN: return "PLUGIN"; case RUNMODE_NFQ: return "NFQ"; case RUNMODE_NFLOG: return "NFLOG"; case RUNMODE_IPFW: return "IPFW"; case RUNMODE_ERF_FILE: return "ERF_FILE"; case RUNMODE_DAG: return "ERF_DAG"; case RUNMODE_NAPATECH: return "NAPATECH"; case RUNMODE_UNITTEST: return "UNITTEST"; case RUNMODE_AFP_DEV: return "AF_PACKET_DEV"; case RUNMODE_AFXDP_DEV: return "AF_XDP_DEV"; case RUNMODE_NETMAP: #ifdef HAVE_NETMAP return "NETMAP"; #else return "NETMAP(DISABLED)"; #endif case RUNMODE_UNIX_SOCKET: return "UNIX_SOCKET"; case RUNMODE_WINDIVERT: #ifdef WINDIVERT return "WINDIVERT"; #else return "WINDIVERT(DISABLED)"; #endif case RUNMODE_DPDK: #ifdef HAVE_DPDK return "DPDK"; #else return "DPDK(DISABLED)"; #endif default: FatalError("Unknown runtime mode. Aborting"); } } /** * \internal * \brief Dispatcher function for runmodes. Calls the required runmode function * based on runmode + runmode_custom_id. * * \param runmode The runmode type. * \param runmode_custom_id The runmode custom id. */ static RunMode *RunModeGetCustomMode(enum RunModes runmode, const char *custom_mode) { if (runmode < RUNMODE_USER_MAX) { for (int i = 0; i < runmodes[runmode].cnt; i++) { if (strcmp(runmodes[runmode].runmodes[i].name, custom_mode) == 0) return &runmodes[runmode].runmodes[i]; } } return NULL; } /** * Return the running mode * * The returned string must not be freed. * * \return a string containing the current running mode */ char *RunmodeGetActive(void) { return active_runmode; } /** * Return the running mode * * The returned string must not be freed. * * \return a string containing the current running mode */ const char *RunModeGetMainMode(void) { int mainmode = RunmodeGetCurrent(); return RunModeTranslateModeToName(mainmode); } /** * \brief Register all runmodes in the engine. */ void RunModeRegisterRunModes(void) { memset(runmodes, 0, sizeof(runmodes)); RunModeIdsPcapRegister(); RunModeFilePcapRegister(); RunModeIdsPfringRegister(); RunModeIpsNFQRegister(); RunModeIpsIPFWRegister(); RunModeErfFileRegister(); RunModeErfDagRegister(); RunModeNapatechRegister(); RunModeIdsAFPRegister(); RunModeIdsAFXDPRegister(); RunModeIdsNetmapRegister(); RunModeIdsNflogRegister(); RunModeUnixSocketRegister(); RunModeIpsWinDivertRegister(); RunModeDpdkRegister(); #ifdef UNITTESTS UtRunModeRegister(); #endif return; } /** * \brief Lists all registered runmodes. */ void RunModeListRunmodes(void) { printf("------------------------------------- Runmodes -------------------" "-----------------------\n"); printf("| %-17s | %-17s | %-10s \n", "RunMode Type", "Custom Mode ", "Description"); printf("|-----------------------------------------------------------------" "-----------------------\n"); int i = RUNMODE_UNKNOWN + 1; int j = 0; for ( ; i < RUNMODE_USER_MAX; i++) { int mode_displayed = 0; for (j = 0; j < runmodes[i].cnt; j++) { if (mode_displayed == 1) { printf("| ----------------------------------------------" "-----------------------\n"); RunMode *runmode = &runmodes[i].runmodes[j]; printf("| %-17s | %-17s | %-27s \n", "", runmode->name, runmode->description); } else { RunMode *runmode = &runmodes[i].runmodes[j]; printf("| %-17s | %-17s | %-27s \n", RunModeTranslateModeToName(runmode->runmode), runmode->name, runmode->description); } if (mode_displayed == 0) mode_displayed = 1; } if (mode_displayed == 1) { printf("|-----------------------------------------------------------------" "-----------------------\n"); } } return; } static const char *RunModeGetConfOrDefault(int capture_mode, const char *capture_plugin_name) { const char *custom_mode = NULL; const char *val = NULL; if (ConfGet("runmode", &val) != 1) { custom_mode = NULL; } else { custom_mode = val; } if ((custom_mode == NULL) || (strcmp(custom_mode, "auto") == 0)) { switch (capture_mode) { case RUNMODE_PCAP_DEV: custom_mode = RunModeIdsGetDefaultMode(); break; case RUNMODE_PCAP_FILE: custom_mode = RunModeFilePcapGetDefaultMode(); break; #ifdef HAVE_PFRING case RUNMODE_PFRING: custom_mode = RunModeIdsPfringGetDefaultMode(); break; #endif case RUNMODE_PLUGIN: { #ifdef HAVE_PLUGINS SCCapturePlugin *plugin = SCPluginFindCaptureByName(capture_plugin_name); if (plugin == NULL) { FatalError("No capture plugin found with name %s", capture_plugin_name); } custom_mode = (const char *)plugin->GetDefaultMode(); #endif break; } case RUNMODE_NFQ: custom_mode = RunModeIpsNFQGetDefaultMode(); break; case RUNMODE_IPFW: custom_mode = RunModeIpsIPFWGetDefaultMode(); break; case RUNMODE_ERF_FILE: custom_mode = RunModeErfFileGetDefaultMode(); break; case RUNMODE_DAG: custom_mode = RunModeErfDagGetDefaultMode(); break; case RUNMODE_NAPATECH: custom_mode = RunModeNapatechGetDefaultMode(); break; case RUNMODE_AFP_DEV: custom_mode = RunModeAFPGetDefaultMode(); break; case RUNMODE_AFXDP_DEV: custom_mode = RunModeAFXDPGetDefaultMode(); break; case RUNMODE_NETMAP: custom_mode = RunModeNetmapGetDefaultMode(); break; case RUNMODE_UNIX_SOCKET: custom_mode = RunModeUnixSocketGetDefaultMode(); break; case RUNMODE_NFLOG: custom_mode = RunModeIdsNflogGetDefaultMode(); break; #ifdef WINDIVERT case RUNMODE_WINDIVERT: custom_mode = RunModeIpsWinDivertGetDefaultMode(); break; #endif #ifdef HAVE_DPDK case RUNMODE_DPDK: custom_mode = RunModeDpdkGetDefaultMode(); break; #endif default: return NULL; } } else { /* Add compatibility with old 'worker' name */ if (!strcmp("worker", custom_mode)) { SCLogWarning("'worker' mode have been renamed " "to 'workers', please modify your setup."); custom_mode = "workers"; } } return custom_mode; } void RunModeEngineIsIPS(int capture_mode, const char *runmode, const char *capture_plugin_name) { if (runmode == NULL) { runmode = RunModeGetConfOrDefault(capture_mode, capture_plugin_name); if (runmode == NULL) // non-standard runmode return; } RunMode *mode = RunModeGetCustomMode(capture_mode, runmode); if (mode == NULL) { return; } if (mode->RunModeIsIPSEnabled != NULL) { mode->RunModeIsIPSEnabled(); } } /** */ void RunModeDispatch(int runmode, const char *custom_mode, const char *capture_plugin_name, const char *capture_plugin_args) { char *local_custom_mode = NULL; if (custom_mode == NULL) { custom_mode = RunModeGetConfOrDefault(runmode, capture_plugin_name); if (custom_mode == NULL) FatalError("Unknown runtime mode. Aborting"); } RunMode *mode = RunModeGetCustomMode(runmode, custom_mode); if (mode == NULL) { SCLogError("The custom type \"%s\" doesn't exist " "for this runmode type \"%s\". Please use --list-runmodes to " "see available custom types for this runmode", custom_mode, RunModeTranslateModeToName(runmode)); exit(EXIT_FAILURE); } /* Export the custom mode */ if (active_runmode) { SCFree(active_runmode); } active_runmode = SCStrdup(custom_mode); if (unlikely(active_runmode == NULL)) { FatalError("Unable to dup active mode"); } if (strcasecmp(active_runmode, "autofp") == 0) { TmqhFlowPrintAutofpHandler(); } mode->RunModeFunc(); if (local_custom_mode != NULL) SCFree(local_custom_mode); /* Check if the alloted queues have at least 1 reader and writer */ TmValidateQueueState(); if (runmode != RUNMODE_UNIX_SOCKET) { /* spawn management threads */ FlowManagerThreadSpawn(); FlowRecyclerThreadSpawn(); if (RunModeNeedsBypassManager()) { BypassedFlowManagerThreadSpawn(); } StatsSpawnThreads(); } } static int g_runmode_needs_bypass = 0; void RunModeEnablesBypassManager(void) { g_runmode_needs_bypass = 1; } int RunModeNeedsBypassManager(void) { return g_runmode_needs_bypass; } /** * \brief Registers a new runmode. * * \param runmode Runmode type. * \param name Custom mode for this specific runmode type. Within each * runmode type, each custom name is a primary key. * \param description Description for this runmode. * \param RunModeFunc The function to be run for this runmode. */ void RunModeRegisterNewRunMode(enum RunModes runmode, const char *name, const char *description, int (*RunModeFunc)(void), void (*RunModeIsIPSEnabled)(void)) { if (RunModeGetCustomMode(runmode, name) != NULL) { FatalError("runmode '%s' has already " "been registered. Please use an unique name.", name); } void *ptmp = SCRealloc(runmodes[runmode].runmodes, (runmodes[runmode].cnt + 1) * sizeof(RunMode)); if (ptmp == NULL) { SCFree(runmodes[runmode].runmodes); runmodes[runmode].runmodes = NULL; exit(EXIT_FAILURE); } runmodes[runmode].runmodes = ptmp; RunMode *mode = &runmodes[runmode].runmodes[runmodes[runmode].cnt]; runmodes[runmode].cnt++; memset(mode, 0x00, sizeof(*mode)); mode->runmode = runmode; mode->name = SCStrdup(name); if (unlikely(mode->name == NULL)) { FatalError("Failed to allocate string"); } mode->description = SCStrdup(description); if (unlikely(mode->description == NULL)) { FatalError("Failed to allocate string"); } mode->RunModeFunc = RunModeFunc; mode->RunModeIsIPSEnabled = RunModeIsIPSEnabled; return; } /** * Setup the outputs for this run mode. * * \param tv The ThreadVars for the thread the outputs will be * appended to. */ static void RunOutputFreeList(void) { OutputFreeList *output; while ((output = TAILQ_FIRST(&output_free_list))) { TAILQ_REMOVE(&output_free_list, output, entries); SCLogDebug("output %s %p %p", output->output_module->name, output, output->output_ctx); if (output->output_ctx != NULL && output->output_ctx->DeInit != NULL) output->output_ctx->DeInit(output->output_ctx); SCFree(output); } } static int file_logger_count = 0; static int filedata_logger_count = 0; static LoggerId logger_bits[ALPROTO_MAX]; int RunModeOutputFileEnabled(void) { return file_logger_count > 0; } int RunModeOutputFiledataEnabled(void) { return filedata_logger_count > 0; } bool IsRunModeSystem(enum RunModes run_mode_to_check) { switch (run_mode_to_check) { case RUNMODE_PCAP_FILE: case RUNMODE_ERF_FILE: case RUNMODE_ENGINE_ANALYSIS: return false; break; default: return true; } } bool IsRunModeOffline(enum RunModes run_mode_to_check) { switch(run_mode_to_check) { case RUNMODE_CONF_TEST: case RUNMODE_PCAP_FILE: case RUNMODE_ERF_FILE: case RUNMODE_ENGINE_ANALYSIS: case RUNMODE_UNIX_SOCKET: return true; break; default: return false; } } /** * Cleanup the run mode. */ void RunModeShutDown(void) { RunOutputFreeList(); OutputPacketShutdown(); OutputTxShutdown(); OutputFileShutdown(); OutputFiledataShutdown(); OutputStreamingShutdown(); OutputStatsShutdown(); OutputFlowShutdown(); OutputClearActiveLoggers(); /* Reset logger counts. */ file_logger_count = 0; filedata_logger_count = 0; } /** \internal * \brief add Sub RunModeOutput to list for Submodule so we can free * the output ctx at shutdown and unix socket reload */ static void AddOutputToFreeList(OutputModule *module, OutputCtx *output_ctx) { OutputFreeList *fl_output = SCCalloc(1, sizeof(OutputFreeList)); if (unlikely(fl_output == NULL)) return; fl_output->output_module = module; fl_output->output_ctx = output_ctx; TAILQ_INSERT_TAIL(&output_free_list, fl_output, entries); } /** \brief Turn output into thread module */ static void SetupOutput(const char *name, OutputModule *module, OutputCtx *output_ctx) { /* flow logger doesn't run in the packet path */ if (module->FlowLogFunc) { OutputRegisterFlowLogger(module->name, module->FlowLogFunc, output_ctx, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); return; } /* stats logger doesn't run in the packet path */ if (module->StatsLogFunc) { OutputRegisterStatsLogger(module->name, module->StatsLogFunc, output_ctx,module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); return; } if (module->logger_id == LOGGER_ALERT_DEBUG) { debuglog_enabled = 1; } if (module->PacketLogFunc) { SCLogDebug("%s is a packet logger", module->name); OutputRegisterPacketLogger(module->logger_id, module->name, module->PacketLogFunc, module->PacketConditionFunc, output_ctx, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); } else if (module->TxLogFunc) { SCLogDebug("%s is a tx logger", module->name); OutputRegisterTxLogger(module->logger_id, module->name, module->alproto, module->TxLogFunc, output_ctx, module->tc_log_progress, module->ts_log_progress, module->TxLogCondition, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); /* Not used with wild card loggers */ if (module->alproto != ALPROTO_UNKNOWN) { logger_bits[module->alproto] |= BIT_U32(module->logger_id); } } else if (module->FiledataLogFunc) { SCLogDebug("%s is a filedata logger", module->name); OutputRegisterFiledataLogger(module->logger_id, module->name, module->FiledataLogFunc, output_ctx, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); filedata_logger_count++; } else if (module->FileLogFunc) { SCLogDebug("%s is a file logger", module->name); OutputRegisterFileLogger(module->logger_id, module->name, module->FileLogFunc, output_ctx, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); file_logger_count++; } else if (module->StreamingLogFunc) { SCLogDebug("%s is a streaming logger", module->name); OutputRegisterStreamingLogger(module->logger_id, module->name, module->StreamingLogFunc, output_ctx, module->stream_type, module->ThreadInit, module->ThreadDeinit, module->ThreadExitPrintStats); } else { SCLogError("Unknown logger type: name=%s", module->name); } } static void RunModeInitializeEveOutput(ConfNode *conf, OutputCtx *parent_ctx) { ConfNode *types = ConfNodeLookupChild(conf, "types"); SCLogDebug("types %p", types); if (types == NULL) { return; } ConfNode *type = NULL; TAILQ_FOREACH(type, &types->head, next) { int sub_count = 0; char subname[256]; if (strcmp(type->val, "ikev2") == 0) { SCLogWarning("eve module 'ikev2' has been replaced by 'ike'"); strlcpy(subname, "eve-log.ike", sizeof(subname)); } else { snprintf(subname, sizeof(subname), "eve-log.%s", type->val); } SCLogConfig("enabling 'eve-log' module '%s'", type->val); ConfNode *sub_output_config = ConfNodeLookupChild(type, type->val); if (sub_output_config != NULL) { const char *enabled = ConfNodeLookupChildValue( sub_output_config, "enabled"); if (enabled != NULL && !ConfValIsTrue(enabled)) { continue; } } /* Now setup all registers logger of this name. */ OutputModule *sub_module; TAILQ_FOREACH(sub_module, &output_modules, entries) { if (strcmp(subname, sub_module->conf_name) == 0) { sub_count++; if (sub_module->parent_name == NULL || strcmp(sub_module->parent_name, "eve-log") != 0) { FatalError("bad parent for %s", subname); } if (sub_module->InitSubFunc == NULL) { FatalError("bad sub-module for %s", subname); } /* pass on parent output_ctx */ OutputInitResult result = sub_module->InitSubFunc(sub_output_config, parent_ctx); if (!result.ok || result.ctx == NULL) { FatalError("unable to initialize sub-module %s", subname); } AddOutputToFreeList(sub_module, result.ctx); SetupOutput(sub_module->name, sub_module, result.ctx); } } /* Error is no registered loggers with this name * were found .*/ if (!sub_count) { FatalErrorOnInit("No output module named %s", subname); continue; } } } static void RunModeInitializeLuaOutput(ConfNode *conf, OutputCtx *parent_ctx) { OutputModule *lua_module = OutputGetModuleByConfName("lua"); BUG_ON(lua_module == NULL); ConfNode *scripts = ConfNodeLookupChild(conf, "scripts"); BUG_ON(scripts == NULL); //TODO OutputModule *m; TAILQ_FOREACH(m, &parent_ctx->submodules, entries) { SCLogDebug("m %p %s:%s", m, m->name, m->conf_name); ConfNode *script = NULL; TAILQ_FOREACH(script, &scripts->head, next) { SCLogDebug("script %s", script->val); if (strcmp(script->val, m->conf_name) == 0) { break; } } BUG_ON(script == NULL); /* pass on parent output_ctx */ OutputInitResult result = m->InitSubFunc(script, parent_ctx); if (!result.ok || result.ctx == NULL) { continue; } AddOutputToFreeList(m, result.ctx); SetupOutput(m->name, m, result.ctx); } } extern bool g_file_logger_enabled; extern bool g_filedata_logger_enabled; /** * Initialize the output modules. */ void RunModeInitializeOutputs(void) { ConfNode *outputs = ConfGetNode("outputs"); if (outputs == NULL) { /* No "outputs" section in the configuration. */ return; } ConfNode *output, *output_config; const char *enabled; char tls_log_enabled = 0; char tls_store_present = 0; memset(&logger_bits, 0, sizeof(logger_bits)); TAILQ_FOREACH(output, &outputs->head, next) { output_config = ConfNodeLookupChild(output, output->val); if (output_config == NULL) { /* Shouldn't happen. */ FatalError("Failed to lookup configuration child node: %s", output->val); } if (strcmp(output->val, "tls-store") == 0) { tls_store_present = 1; } enabled = ConfNodeLookupChildValue(output_config, "enabled"); if (enabled == NULL || !ConfValIsTrue(enabled)) { continue; } if (strcmp(output->val, "file-log") == 0) { SCLogWarning("file-log is no longer supported," " use eve.files instead " "(see ticket #2376" " for an explanation)"); continue; } else if (strncmp(output->val, "unified-", sizeof("unified-") - 1) == 0) { SCLogWarning("Unified1 is no longer supported," " use Unified2 instead " "(see ticket #353" " for an explanation)"); continue; } else if (strncmp(output->val, "unified2-", sizeof("unified2-") - 1) == 0) { SCLogWarning("Unified2 is no longer supported."); continue; } else if (strcmp(output->val, "lua") == 0) { #ifndef HAVE_LUA SCLogWarning("lua support not compiled in. Reconfigure/" "recompile with lua(jit) and its development " "files installed to add lua support."); continue; #endif } else if (strcmp(output->val, "dns-log") == 0) { SCLogWarning("dns-log is not longer available as of Suricata 5.0"); continue; } else if (strcmp(output->val, "tls-log") == 0) { tls_log_enabled = 1; } OutputModule *module; int count = 0; TAILQ_FOREACH(module, &output_modules, entries) { if (strcmp(module->conf_name, output->val) != 0) { continue; } count++; OutputCtx *output_ctx = NULL; if (module->InitFunc != NULL) { OutputInitResult r = module->InitFunc(output_config); if (!r.ok) { FatalErrorOnInit("output module \"%s\": setup failed", output->val); continue; } else if (r.ctx == NULL) { continue; } output_ctx = r.ctx; } else if (module->InitSubFunc != NULL) { SCLogInfo("skipping submodule"); continue; } // TODO if module == parent, find it's children if (strcmp(output->val, "eve-log") == 0) { RunModeInitializeEveOutput(output_config, output_ctx); /* add 'eve-log' to free list as it's the owner of the * main output ctx from which the sub-modules share the * LogFileCtx */ AddOutputToFreeList(module, output_ctx); } else if (strcmp(output->val, "lua") == 0) { SCLogDebug("handle lua"); if (output_ctx == NULL) continue; RunModeInitializeLuaOutput(output_config, output_ctx); AddOutputToFreeList(module, output_ctx); } else { AddOutputToFreeList(module, output_ctx); SetupOutput(module->name, module, output_ctx); } } if (count == 0) { FatalErrorOnInit("No output module named %s", output->val); continue; } } /* Backward compatibility code */ if (!tls_store_present && tls_log_enabled) { /* old YAML with no "tls-store" in outputs. "tls-log" value needs * to be started using 'tls-log' config as own config */ SCLogWarning("Please use 'tls-store' in YAML to configure TLS storage"); TAILQ_FOREACH(output, &outputs->head, next) { output_config = ConfNodeLookupChild(output, output->val); if (strcmp(output->val, "tls-log") == 0) { OutputModule *module = OutputGetModuleByConfName("tls-store"); if (module == NULL) { SCLogWarning("No output module named %s, ignoring", "tls-store"); continue; } OutputCtx *output_ctx = NULL; if (module->InitFunc != NULL) { OutputInitResult r = module->InitFunc(output_config); if (!r.ok) { FatalErrorOnInit("output module setup failed"); continue; } else if (r.ctx == NULL) { continue; } output_ctx = r.ctx; } AddOutputToFreeList(module, output_ctx); SetupOutput(module->name, module, output_ctx); } } } /* register the logger bits to the app-layer */ AppProto a; for (a = 0; a < ALPROTO_MAX; a++) { if (AppLayerParserSupportsFiles(IPPROTO_TCP, a)) { if (g_file_logger_enabled) logger_bits[a] |= BIT_U32(LOGGER_FILE); if (g_filedata_logger_enabled) logger_bits[a] |= BIT_U32(LOGGER_FILEDATA); SCLogDebug("IPPROTO_TCP::%s: g_file_logger_enabled %d g_filedata_logger_enabled %d -> " "%08x", AppProtoToString(a), g_file_logger_enabled, g_filedata_logger_enabled, logger_bits[a]); } if (AppLayerParserSupportsFiles(IPPROTO_UDP, a)) { if (g_file_logger_enabled) logger_bits[a] |= BIT_U32(LOGGER_FILE); if (g_filedata_logger_enabled) logger_bits[a] |= BIT_U32(LOGGER_FILEDATA); } if (logger_bits[a] == 0) continue; const int tcp = AppLayerParserProtocolHasLogger(IPPROTO_TCP, a) | (g_file_logger_enabled) | (g_filedata_logger_enabled); const int udp = AppLayerParserProtocolHasLogger(IPPROTO_UDP, a) | (g_file_logger_enabled) | (g_filedata_logger_enabled); SCLogDebug("tcp %d udp %d", tcp, udp); SCLogDebug("logger for %s: %s %s", AppProtoToString(a), tcp ? "true" : "false", udp ? "true" : "false"); SCLogDebug("logger bits for %s: %08x", AppProtoToString(a), logger_bits[a]); if (tcp) AppLayerParserRegisterLoggerBits(IPPROTO_TCP, a, logger_bits[a]); if (udp) AppLayerParserRegisterLoggerBits(IPPROTO_UDP, a, logger_bits[a]); } OutputSetupActiveLoggers(); } float threading_detect_ratio = 1; /** * Initialize multithreading settings. */ void RunModeInitializeThreadSettings(void) { threading_set_cpu_affinity = FALSE; if ((ConfGetBool("threading.set-cpu-affinity", &threading_set_cpu_affinity)) == 0) { threading_set_cpu_affinity = FALSE; } /* try to get custom cpu mask value if needed */ if (threading_set_cpu_affinity == TRUE) { AffinitySetupLoadFromConfig(); } if ((ConfGetFloat("threading.detect-thread-ratio", &threading_detect_ratio)) != 1) { if (ConfGetNode("threading.detect-thread-ratio") != NULL) WarnInvalidConfEntry("threading.detect-thread-ratio", "%s", "1"); threading_detect_ratio = 1; } SCLogDebug("threading.detect-thread-ratio %f", threading_detect_ratio); /* * Check if there's a configuration setting for the per-thread stack size * in case the default per-thread stack size is to be adjusted */ const char *ss = NULL; if ((ConfGet("threading.stack-size", &ss)) == 1) { if (ss != NULL) { if (ParseSizeStringU64(ss, &threading_set_stack_size) < 0) { FatalError("Failed to initialize thread_stack_size output, invalid limit: %s", ss); } } } else { pthread_attr_t attr; pthread_attr_init(&attr); size_t size; if (pthread_attr_getstacksize(&attr, &size) == 0 && size < 512 * 1024) { threading_set_stack_size = 512 * 1024; SCLogNotice("thread stack size of %" PRIuMAX " to too small: setting to 512k", (uintmax_t)size); } } SCLogDebug("threading.stack-size %" PRIu64, threading_set_stack_size); }