"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/snort.c" (16 Oct 2020, 174210 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "snort.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /* $Id$ */
    2 /*
    3 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    4 ** Copyright (C) 2002-2013 Sourcefire, Inc.
    5 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
    6 **
    7 ** This program is free software; you can redistribute it and/or modify
    8 ** it under the terms of the GNU General Public License Version 2 as
    9 ** published by the Free Software Foundation.  You may not use, modify or
   10 ** distribute this program under any other version of the GNU General
   11 ** Public License.
   12 **
   13 ** This program is distributed in the hope that it will be useful,
   14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16 ** GNU General Public License for more details.
   17 **
   18 ** You should have received a copy of the GNU General Public License
   19 ** along with this program; if not, write to the Free Software
   20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   21 */
   22 
   23 /*
   24  *
   25  * Program: Snort
   26  *
   27  * Purpose: Check out the README file for info on what you can do
   28  *          with Snort.
   29  *
   30  * Author: Martin Roesch (roesch@clark.net)
   31  *
   32  * Comments: Ideas and code stolen liberally from Mike Borella's IP Grab
   33  *           program. Check out his stuff at http://www.borella.net.  I
   34  *           also have ripped some util functions from TCPdump, plus Mike's
   35  *           prog is derived from it as well.  All hail TCPdump....
   36  *
   37  */
   38 
   39 #ifdef HAVE_CONFIG_H
   40 # include "config.h"
   41 #endif
   42 
   43 #ifdef HAVE_GETTID
   44 #define _GNU_SOURCE
   45 #endif
   46 
   47 #include <assert.h>
   48 #include <sys/types.h>
   49 #include <sys/stat.h>
   50 #include <fcntl.h>
   51 #include <errno.h>
   52 #include <sys/types.h>
   53 #include <stdlib.h>
   54 #include <stdio.h>
   55 #include <unistd.h>
   56 #include <string.h>
   57 #include <setjmp.h>
   58 #include <signal.h>
   59 #include <time.h>
   60 #include <pcap.h>
   61 #ifdef HAVE_MALLOC_TRIM
   62 #include <malloc.h>
   63 #endif
   64 
   65 #ifndef WIN32
   66 #include <netdb.h>
   67 #else
   68 #include <Iphlpapi.h>
   69 #endif
   70 
   71 #ifdef HAVE_GETOPT_LONG
   72 //#define _GNU_SOURCE
   73 /* A GPL copy of getopt & getopt_long src code is now in sfutil */
   74 # undef HAVE_GETOPT_LONG
   75 #endif
   76 #include <getopt.h>
   77 
   78 #ifdef HAVE_STRINGS_H
   79 # include <strings.h>
   80 #endif
   81 
   82 #ifndef WIN32
   83 # include <grp.h>
   84 # include <pwd.h>
   85 # include <sys/socket.h>
   86 # include <netinet/in.h>
   87 # include <arpa/inet.h>
   88 #endif  /* !WIN32 */
   89 
   90 #if !defined(CATCH_SEGV) && !defined(WIN32)
   91 # include <sys/resource.h>
   92 #endif
   93 
   94 #include "decode.h"
   95 #include "encode.h"
   96 #include "sfdaq.h"
   97 #include "active.h"
   98 #include "snort.h"
   99 #include "rules.h"
  100 #include "treenodes.h"
  101 #include "plugbase.h"
  102 #include "snort_debug.h"
  103 #include "util.h"
  104 #include "parser.h"
  105 #include "tag.h"
  106 #include "log.h"
  107 #include "detect.h"
  108 #include "mstring.h"
  109 #include "fpcreate.h"
  110 #include "fpdetect.h"
  111 #include "sfthreshold.h"
  112 #include "rate_filter.h"
  113 #include "packet_time.h"
  114 #include "detection-plugins/sp_flowbits.h"
  115 #include "preprocessors/spp_perfmonitor.h"
  116 #include "preprocessors/perf-base.h"
  117 #include "preprocessors/perf.h"
  118 #include "mempool.h"
  119 #include "strlcpyu.h"
  120 #include "sflsq.h"
  121 #include "sp_replace.h"
  122 #include "output-plugins/spo_log_tcpdump.h"
  123 #include "event_queue.h"
  124 #include "asn1.h"
  125 #include "mpse.h"
  126 #include "generators.h"
  127 #include "ppm.h"
  128 #include "profiler.h"
  129 #include "dynamic-plugins/sp_dynamic.h"
  130 #include "dynamic-plugins/sf_dynamic_define.h"
  131 #include "dynamic-output/plugins/output.h"
  132 #include "sfutil/strvec.h"
  133 #include "detection_util.h"
  134 #include "sfcontrol_funcs.h"
  135 #include "idle_processing_funcs.h"
  136 #include "file_service.h"
  137 #include "pkt_tracer.h"
  138 #include "session_expect.h"
  139 #include "reload.h"
  140 #include "reg_test.h"
  141 #include "memory_stats.h"
  142 #include "pthread.h"
  143 #ifdef SIDE_CHANNEL
  144 # include "sidechannel.h"
  145 #endif
  146 
  147 #include "dynamic-plugins/sf_dynamic_engine.h"
  148 #include "dynamic-plugins/sf_dynamic_detection.h"
  149 #define PROFILE_PREPROCS_NOREDEF
  150 #include "dynamic-plugins/sf_dynamic_preprocessor.h"
  151 #include "dynamic-plugins/sp_preprocopt.h"
  152 #ifdef SIDE_CHANNEL
  153 # include "dynamic-plugins/sf_dynamic_side_channel.h"
  154 #endif
  155 
  156 #ifdef TARGET_BASED
  157 # include "target-based/sftarget_reader.h"
  158 #endif
  159 
  160 #ifdef EXIT_CHECK
  161 # include "cpuclock.h"
  162 #endif
  163 #include "sfActionQueue.h"
  164 
  165 #ifdef INTEL_SOFT_CPM
  166 #include "sfutil/intel-soft-cpm.h"
  167 #endif
  168 
  169 #include "session_api.h"
  170 
  171 #include "stream_common.h"
  172 #include "stream5_ha.h"
  173 
  174 #ifdef CONTROL_SOCKET
  175 #include "dump.h"
  176 #endif
  177 
  178 #ifdef PERF_PROFILING
  179 #include "perf_indicators.h"
  180 #endif
  181 
  182 /* Macros *********************************************************************/
  183 #ifndef DLT_LANE8023
  184 /*
  185  * Old OPEN BSD Log format is 17.
  186  * Define DLT_OLDPFLOG unless DLT_LANE8023 (Suse 6.3) is already
  187  * defined in bpf.h.
  188  */
  189 # define DLT_OLDPFLOG 17
  190 #endif
  191 
  192 #define ALERT_MODE_OPT__NONE       "none"
  193 #define ALERT_MODE_OPT__PKT_CNT    "packet-count"
  194 #define ALERT_MODE_OPT__FULL       "full"
  195 #define ALERT_MODE_OPT__FAST       "fast"
  196 #define ALERT_MODE_OPT__CONSOLE    "console"
  197 #define ALERT_MODE_OPT__CMG        "cmg"
  198 #define ALERT_MODE_OPT__JH         "jh"
  199 #define ALERT_MODE_OPT__DJR        "djr"
  200 #define ALERT_MODE_OPT__AJK        "ajk"
  201 #define ALERT_MODE_OPT__UNIX_SOCK  "unsock"
  202 #define ALERT_MODE_OPT__TEST       "test"
  203 
  204 #define LOG_MODE_OPT__NONE    "none"
  205 #define LOG_MODE_OPT__PCAP    "pcap"
  206 #define LOG_MODE_OPT__ASCII   "ascii"
  207 
  208 #ifdef MPLS
  209 # define MPLS_PAYLOAD_OPT__IPV4      "ipv4"
  210 # define MPLS_PAYLOAD_OPT__IPV6      "ipv6"
  211 # define MPLS_PAYLOAD_OPT__ETHERNET  "ethernet"
  212 #endif
  213 
  214 #define DEFAULT_PAF_MAX  16384
  215 
  216 /* Instead of 16k as Flowcount, We should use a smaller number for idle pruning in SnortIdle() to avoid AAB.
  217  * Now in snort Idle case, we will prune the sessions with in AAB timeout (Miminum configurable AAB value).
  218  * Tested and found out, on an average 0.2 ms is taking to prune one session.
  219  * FlowCount = (AAB timeout / time to prune onesession ) / 3  (tcp+udp+ip)
  220  */
  221 
  222 #define AAB_THRESHOLD 250
  223 #define TIME_TO_PRUNE_ONE_SESSION 0.2
  224 const uint32_t FLOW_COUNT = (AAB_THRESHOLD/TIME_TO_PRUNE_ONE_SESSION) / 3;
  225 volatile int detection_lib_changed = 0;
  226 #ifdef SNORT_RELOAD
  227 extern volatile bool reloadInProgress;
  228 #endif
  229 
  230 
  231 /* Data types *****************************************************************/
  232 
  233 typedef enum _GetOptArgType
  234 {
  235     LONGOPT_ARG_NONE = 0,
  236     LONGOPT_ARG_REQUIRED,
  237     LONGOPT_ARG_OPTIONAL
  238 
  239 } GetOptArgType;
  240 
  241 /* Externs *******************************************************************/
  242 /* Undefine the one from sf_dynamic_preprocessor.h */
  243 #ifdef PERF_PROFILING
  244 extern PreprocStats detectPerfStats, decodePerfStats, metaPerfStats,
  245        totalPerfStats, eventqPerfStats, rulePerfStats, mpsePerfStats;
  246 extern PreprocStats ruleCheckBitPerfStats, ruleSetBitPerfStats, ruleFailedFlowbitsPerfStats;
  247 extern PreprocStats ruleRTNEvalPerfStats, ruleOTNEvalPerfStats, ruleHeaderNoMatchPerfStats;
  248 extern PreprocStats ruleAddEventQPerfStats, ruleNQEventQPerfStats;
  249 extern PreprocStats preprocRuleOptionPerfStats;
  250 #endif
  251 
  252 /* for getopt */
  253 extern char *optarg;
  254 extern int optind;
  255 extern int opterr;
  256 extern int optopt;
  257 
  258 extern ListHead *head_tmp;
  259 
  260 
  261 /* Globals/Public *************************************************************/
  262 PacketCount pc;  /* packet count information */
  263 uint32_t *netmasks = NULL;   /* precalculated netmask array */
  264 char **protocol_names = NULL;
  265 char *snort_conf_file = NULL;   /* -c */
  266 char *snort_conf_dir = NULL;
  267 
  268 SnortConfig *snort_cmd_line_conf = NULL;
  269 SnortConfig *snort_conf = NULL;
  270 
  271 int internal_log_level = INTERNAL_LOG_LEVEL__MESSAGE;
  272 
  273 tSfActionQueueId decoderActionQ = NULL;
  274 MemPool decoderAlertMemPool;
  275 
  276 VarNode *cmd_line_var_list = NULL;
  277 
  278 static pthread_mutex_t cleanup_mutex = PTHREAD_MUTEX_INITIALIZER;
  279 
  280 #ifdef TARGET_BASED
  281 pthread_t attribute_reload_thread_id;
  282 pid_t attribute_reload_thread_pid;
  283 volatile int attribute_reload_thread_running = 0;
  284 volatile int attribute_reload_thread_stop = 0;
  285 int reload_attribute_table_flags = 0;
  286 #endif
  287 
  288 volatile bool snort_initializing = true;
  289 volatile int snort_exiting = 0;
  290 volatile int already_exiting = 0;
  291 static pid_t snort_main_thread_pid = 0;
  292 #ifndef WIN32
  293 static pthread_t snort_main_thread_id = 0;
  294 #endif
  295 
  296 #if defined(SNORT_RELOAD) && !defined(WIN32)
  297 volatile int snort_reload = 0;
  298 static pthread_t snort_reload_thread_id;
  299 volatile int snort_reload_thread_created = 0;
  300 pid_t snort_reload_thread_pid;
  301 #endif
  302 
  303 const struct timespec thread_sleep = { 0, 100 };
  304 #ifdef OPENBSD
  305 const struct timespec packet_sleep = { 0, 1 };
  306 #endif
  307 
  308 #ifdef HAVE_PCAP_LEX_DESTROY
  309 extern void pcap_lex_destroy(void);
  310 #endif
  311 
  312 PreprocConfigFuncNode *preproc_config_funcs = NULL;
  313 OutputConfigFuncNode *output_config_funcs = NULL;
  314 RuleOptConfigFuncNode *rule_opt_config_funcs = NULL;
  315 RuleOptOverrideInitFuncNode *rule_opt_override_init_funcs = NULL;
  316 RuleOptParseCleanupNode *rule_opt_parse_cleanup_list = NULL;
  317 RuleOptByteOrderFuncNode *rule_opt_byte_order_funcs = NULL;
  318 
  319 PreprocSignalFuncNode *preproc_clean_exit_funcs = NULL;
  320 PreprocSignalFuncNode *preproc_shutdown_funcs = NULL;
  321 PreprocSignalFuncNode *preproc_reset_funcs = NULL;
  322 PreprocSignalFuncNode *preproc_reset_stats_funcs = NULL;
  323 PreprocStatsFuncNode *preproc_stats_funcs = NULL;
  324 
  325 PluginSignalFuncNode *plugin_shutdown_funcs = NULL;
  326 PluginSignalFuncNode *plugin_clean_exit_funcs = NULL;
  327 #ifdef SNORT_RELOAD
  328 PostConfigFuncNode *plugin_reload_funcs = NULL;
  329 #endif
  330 
  331 OutputFuncNode *AlertList = NULL;   /* Alert function list */
  332 OutputFuncNode *LogList = NULL;     /* Log function list */
  333 
  334 PeriodicCheckFuncNode *periodic_check_funcs = NULL;
  335 grinder_t grinder;
  336 
  337 pthread_mutex_t dynamic_rules_lock;
  338 #ifdef SIDE_CHANNEL
  339 pthread_mutex_t snort_process_lock;
  340 static bool snort_process_lock_held = false;
  341 #endif
  342 uint8_t iprep_current_update_counter;
  343 
  344 /* Locals/Private ************************************************************/
  345 static long int pcap_loop_count = 0;
  346 static SF_QUEUE *pcap_save_queue = NULL;
  347 
  348 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
  349 static pthread_t inline_failopen_thread_id;
  350 static pid_t inline_failopen_thread_pid;
  351 static volatile int inline_failopen_thread_running = 0;
  352 static volatile int inline_failopen_initialized = 0;
  353 static int inline_failopen_pass_pkt_cnt = 0;
  354 static void * SnortPostInitThread(void *);
  355 static DAQ_Verdict IgnoreCallback (void*, const DAQ_PktHdr_t*, const uint8_t*);
  356 #endif
  357 
  358 static char signal_error_msg[STD_BUF];
  359 static int exit_signal = 0;
  360 static bool dump_stats_signal = false;
  361 static bool rotate_stats_signal = false;
  362 #ifdef TARGET_BASED
  363 static bool no_attr_table_signal = false;
  364 #endif
  365 
  366 #ifndef SNORT_RELOAD
  367 static volatile bool reload_signal = false;
  368 #else
  369 /* reload_signal is incremented in the signal handler for SIGNAL_SNORT_RELOAD
  370  * which is handled in the main thread.  The reload thread compares the
  371  * reload_signal count to reload_total which it increments after an equality
  372  * test between reload_signal and reload_total fails (which means we got a new
  373  *  SIGNAL_SNORT_RELOAD).  They need to be the same type and size to do this
  374  *  comparison.  See ReloadConfigThread() */
  375 volatile snort_reload_t reload_signal = 0;
  376 snort_reload_t reload_total = 0;
  377 #endif
  378 
  379 static int done_processing = 0;
  380 static int exit_logged = 0;
  381 
  382 static SF_LIST *pcap_object_list = NULL;
  383 static SF_QUEUE *pcap_queue = NULL;
  384 static char* pcap_filter = NULL;
  385 
  386 static int snort_argc = 0;
  387 static char **snort_argv = NULL;
  388 
  389 /* command line options for getopt */
  390 static const char *valid_options =
  391     "?A:bB:c:CdDeEfF:"
  392 #ifndef WIN32
  393     "g:"
  394 #endif
  395     "G:h:Hi:Ik:K:l:L:"
  396 #ifndef WIN32
  397     "m:"
  398 #endif
  399     "Mn:NOpP:q"
  400 #ifndef WIN32
  401     "Q"
  402 #endif
  403     "r:R:sS:"
  404 #ifndef WIN32
  405     "t:"
  406 #endif
  407     "T"
  408 #ifndef WIN32
  409     "u:"
  410 #endif
  411     "UvVw:"
  412 #ifdef WIN32
  413     "W"
  414 #endif
  415     "XxyZ:"
  416 ;
  417 
  418 static struct option long_options[] =
  419 {
  420    {"logid", LONGOPT_ARG_REQUIRED, NULL, 'G'},
  421    {"perfmon-file", LONGOPT_ARG_REQUIRED, NULL, 'Z'},
  422    {"snaplen", LONGOPT_ARG_REQUIRED, NULL, 'P'},
  423    {"version", LONGOPT_ARG_NONE, NULL, 'V'},
  424    {"help", LONGOPT_ARG_NONE, NULL, '?'},
  425    {"conf-error-out", LONGOPT_ARG_NONE, NULL,'x'},
  426    {"dynamic-engine-lib", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_ENGINE_FILE},
  427    {"dynamic-engine-lib-dir", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_ENGINE_DIRECTORY},
  428    {"dynamic-detection-lib", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_LIBRARY_FILE},
  429    {"dynamic-detection-lib-dir", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_LIBRARY_DIRECTORY},
  430    {"dump-dynamic-rules", LONGOPT_ARG_REQUIRED, NULL, DUMP_DYNAMIC_RULES},
  431    {"dynamic-preprocessor-lib", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_PREPROC_FILE},
  432    {"dynamic-preprocessor-lib-dir", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_PREPROC_DIRECTORY},
  433    {"dynamic-output-lib", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_OUTPUT_FILE},
  434    {"dynamic-output-lib-dir", LONGOPT_ARG_REQUIRED, NULL, DYNAMIC_OUTPUT_DIRECTORY},
  435    {"alert-before-pass", LONGOPT_ARG_NONE, NULL, ALERT_BEFORE_PASS},
  436    {"treat-drop-as-alert", LONGOPT_ARG_NONE, NULL, TREAT_DROP_AS_ALERT},
  437    {"treat-drop-as-ignore", LONGOPT_ARG_NONE, NULL, TREAT_DROP_AS_IGNORE},
  438    {"process-all-events", LONGOPT_ARG_NONE, NULL, PROCESS_ALL_EVENTS},
  439    {"pid-path", LONGOPT_ARG_REQUIRED, NULL, PID_PATH},
  440    {"create-pidfile", LONGOPT_ARG_NONE, NULL, CREATE_PID_FILE},
  441    {"nolock-pidfile", LONGOPT_ARG_NONE, NULL, NOLOCK_PID_FILE},
  442    {"no-interface-pidfile", LONGOPT_ARG_NONE, NULL, NO_IFACE_PID_FILE},
  443 
  444 #ifdef INLINE_FAILOPEN
  445    {"disable-inline-init-failopen", LONGOPT_ARG_NONE, NULL, DISABLE_INLINE_FAILOPEN},
  446 #endif
  447 
  448    {"nostamps", LONGOPT_ARG_NONE, NULL, NO_LOGGING_TIMESTAMPS},
  449 
  450 #ifdef TARGET_BASED
  451    {"disable-attribute-reload-thread", LONGOPT_ARG_NONE, NULL, DISABLE_ATTRIBUTE_RELOAD},
  452 #endif
  453 
  454    {"pcap-single", LONGOPT_ARG_REQUIRED, NULL, PCAP_SINGLE},
  455    {"pcap-file", LONGOPT_ARG_REQUIRED, NULL, PCAP_FILE_LIST},
  456    {"pcap-list", LONGOPT_ARG_REQUIRED, NULL, PCAP_LIST},
  457 
  458 #ifndef WIN32
  459    {"pcap-dir", LONGOPT_ARG_REQUIRED, NULL, PCAP_DIR},
  460    {"pcap-filter", LONGOPT_ARG_REQUIRED, NULL, PCAP_FILTER},
  461    {"pcap-no-filter", LONGOPT_ARG_NONE, NULL, PCAP_NO_FILTER},
  462 #endif
  463 
  464    {"pcap-loop", LONGOPT_ARG_REQUIRED, NULL, PCAP_LOOP},
  465    {"pcap-reload", LONGOPT_ARG_NONE, NULL, PCAP_RELOAD},
  466    {"pcap-reset", LONGOPT_ARG_NONE, NULL, PCAP_RESET},
  467    {"pcap-show", LONGOPT_ARG_NONE, NULL, PCAP_SHOW},
  468 
  469 #ifdef EXIT_CHECK
  470    {"exit-check", LONGOPT_ARG_REQUIRED, NULL, ARG_EXIT_CHECK},
  471 #endif
  472 
  473    {"search-method", LONGOPT_ARG_REQUIRED, NULL, DETECTION_SEARCH_METHOD},
  474    {"man", LONGOPT_ARG_REQUIRED, NULL, DETECTION_SEARCH_METHOD},
  475 
  476 #ifdef MPLS
  477    {"enable-mpls-multicast", LONGOPT_ARG_NONE, NULL, ENABLE_MPLS_MULTICAST},
  478    {"enable-mpls-overlapping-ip", LONGOPT_ARG_NONE, NULL, ENABLE_OVERLAPPING_IP},
  479    {"max-mpls-labelchain-len", LONGOPT_ARG_REQUIRED, NULL, MAX_MPLS_LABELCHAIN_LEN},
  480    {"mpls-payload-type", LONGOPT_ARG_REQUIRED, NULL, MPLS_PAYLOAD_TYPE},
  481 #endif
  482 
  483    {"require-rule-sid", LONGOPT_ARG_NONE, NULL, REQUIRE_RULE_SID},
  484 
  485    {"daq", LONGOPT_ARG_REQUIRED, NULL, ARG_DAQ_TYPE},
  486    {"daq-mode", LONGOPT_ARG_REQUIRED, NULL, ARG_DAQ_MODE},
  487    {"daq-var", LONGOPT_ARG_REQUIRED, NULL, ARG_DAQ_VAR},
  488    {"daq-dir", LONGOPT_ARG_REQUIRED, NULL, ARG_DAQ_DIR},
  489    {"daq-list", LONGOPT_ARG_OPTIONAL, NULL, ARG_DAQ_LIST},
  490    {"dirty-pig", LONGOPT_ARG_NONE, NULL, ARG_DIRTY_PIG},
  491 
  492    {"enable-inline-test", LONGOPT_ARG_NONE, NULL, ENABLE_INLINE_TEST},
  493 
  494    {"cs-dir", LONGOPT_ARG_REQUIRED, NULL, ARG_CS_DIR},
  495    {"ha-peer", LONGOPT_ARG_NONE, NULL, ARG_HA_PEER},
  496    {"ha-out", LONGOPT_ARG_REQUIRED, NULL, ARG_HA_OUT},
  497    {"ha-in", LONGOPT_ARG_REQUIRED, NULL, ARG_HA_IN},
  498    {"ha-pdts-in", LONGOPT_ARG_REQUIRED, NULL, ARG_HA_PDTS_IN},
  499 
  500    {"suppress-config-log", LONGOPT_ARG_NONE, NULL, SUPPRESS_CONFIG_LOG},
  501 
  502 #ifdef DUMP_BUFFER
  503    {"buffer-dump", LONGOPT_ARG_OPTIONAL, NULL, BUFFER_DUMP},
  504    {"buffer-dump-alert", LONGOPT_ARG_OPTIONAL, NULL, BUFFER_DUMP_ALERT},
  505 #endif
  506 
  507    {0, 0, 0, 0}
  508 };
  509 
  510 #ifdef DUMP_BUFFER
  511 bool dump_alert_only;
  512 bool dumped_state;
  513 bool dump_enabled;
  514 TraceBuffer *(*getBuffers[MAX_BUFFER_DUMP_FUNC])(void);
  515 BufferDumpEnableMask bdmask;
  516 #endif
  517 
  518 typedef void (*log_func_t)(Packet*);
  519 static void LogPacket (Packet* p)
  520 {
  521     pc.log_pkts++;
  522     CallLogPlugins(p, NULL, NULL);
  523 }
  524 static void IgnorePacket (Packet* p) { }
  525 static log_func_t log_func = IgnorePacket;
  526 
  527 /* Private function prototypes ************************************************/
  528 static void InitNetmasks(void);
  529 static void InitProtoNames(void);
  530 static const char* GetPacketSource(char**);
  531 
  532 static void SnortInit(int, char **);
  533 static void InitPidChrootAndPrivs(pid_t);
  534 static void ParseCmdLine(int, char **);
  535 static int ShowUsage(char *);
  536 static void PrintVersion(SnortConfig *);
  537 static void SetSnortConfDir(void);
  538 static void InitGlobals(void);
  539 static void InitSignals(void);
  540 #if defined(NOCOREFILE) && !defined(WIN32)
  541 static void SetNoCores(void);
  542 #endif
  543 static void SnortCleanup(int);
  544 
  545 static void ParseCmdLineDynamicLibInfo(SnortConfig *, int, char *);
  546 static DynamicLibInfo * DupDynamicLibInfo(DynamicLibInfo *);
  547 static void FreeDynamicLibInfo(DynamicLibInfo *);
  548 static void FreeDynamicLibInfos(SnortConfig *);
  549 
  550 static void FreeOutputConfigs(OutputConfig *);
  551 #ifdef SIDE_CHANNEL
  552 static void FreeSideChannelModuleConfigs(SideChannelModuleConfig *);
  553 #endif
  554 static void FreePreprocConfigs(SnortConfig *);
  555 static void FreeRuleStateList(RuleState *);
  556 static void FreeClassifications(ClassType *);
  557 static void FreeReferences(ReferenceSystemNode *);
  558 static void FreePlugins(SnortConfig *);
  559 static void FreePreprocessors(SnortConfig *);
  560 
  561 static void SnortUnprivilegedInit(void);
  562 static int SetPktProcessor(void);
  563 static void PacketLoop(void);
  564 #if 0
  565 static char * ConfigFileSearch(void);
  566 #endif
  567 static void SnortReset(void);
  568 
  569 static void LoadDynamicPlugins(SnortConfig *);
  570 
  571 static void SnortIdle(void);
  572 #ifndef WIN32
  573 static void SnortStartThreads(void);
  574 #endif
  575 
  576 /* Signal handler declarations ************************************************/
  577 static void SigDumpStatsHandler(int);
  578 static void SigExitHandler(int);
  579 static void SigReloadHandler(int);
  580 static void SigRotateStatsHandler(int);
  581 #ifdef CONTROL_SOCKET
  582 static void SigPipeHandler(int);
  583 #endif
  584 static void SigOopsHandler(int);
  585 
  586 
  587 int InMainThread ()
  588 {
  589     return (
  590 #ifndef WIN32
  591         pthread_equal(snort_main_thread_id, pthread_self())
  592 #else
  593         1
  594 #endif
  595         );
  596 }
  597 
  598 bool SnortIsInitializing( )
  599 {
  600 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
  601     return snort_initializing && !inline_failopen_initialized;
  602 #else
  603     return snort_initializing;
  604 #endif
  605 }
  606 
  607 static int IsProcessingPackets(uint16_t type, const uint8_t *data, uint32_t length, void **new_config,
  608                                char *statusBuf, int statusBuf_len)
  609 {
  610     return (!snort_initializing && !snort_exiting && !exit_signal) ? 0 : -1;
  611 }
  612 
  613 /*  F U N C T I O N   D E F I N I T I O N S  **********************************/
  614 
  615 #define INLINE_FAIL_OPEN_NOT_USED 0
  616 #define INLINE_FAIL_OPEN_COMPLETE 1
  617 #define INLINE_FAIL_OPEN_ERROR    2
  618 
  619 static int InlineFailOpen (void)
  620 {
  621 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
  622     int error = 0;
  623 
  624     if (ScAdapterInlineMode() &&
  625         !ScReadMode() && !ScDisableInlineFailopen())
  626     {
  627         /* If in inline mode, start a thread to handle the rest of snort
  628          * initialization, then dispatch packets until that initialization
  629          * is complete. */
  630         LogMessage("Fail Open Thread starting..\n");
  631 
  632         if (pthread_create(&inline_failopen_thread_id, NULL, SnortPostInitThread, NULL))
  633         {
  634             ErrorMessage("Failed to start Fail Open Thread.  "
  635                          "Starting normally\n");
  636         }
  637         else
  638         {
  639             while (!inline_failopen_thread_running)
  640                 nanosleep(&thread_sleep, NULL);
  641 
  642             LogMessage("Fail Open Thread started tid=%p (pid=%u)\n",
  643                     (void*)inline_failopen_thread_id, inline_failopen_thread_pid);
  644 
  645 # ifdef DEBUG
  646             {
  647                 FILE *tmp = fopen("/var/tmp/fo_threadid", "w");
  648                 if ( tmp )
  649                 {
  650                     fprintf(tmp, "Fail Open Thread PID: %u\n", inline_failopen_thread_pid);
  651                     fclose(tmp);
  652                 }
  653             }
  654 # endif
  655             DAQ_Start();
  656             SetPktProcessor();
  657             inline_failopen_initialized = 1;
  658 
  659             /* Passing packets is in the main thread because some systems
  660              * may have to refer to packet passing thread via process id
  661              * (linuxthreads) */
  662             while (snort_initializing)
  663             {
  664                 error = DAQ_Acquire(1, IgnoreCallback, NULL);
  665 
  666                 if (error)
  667                     break;
  668             }
  669 
  670             pthread_join(inline_failopen_thread_id, NULL);
  671             inline_failopen_thread_running = 0;
  672 
  673             LogMessage("Fail Open Thread terminated, passed %d packets.\n",
  674                        inline_failopen_pass_pkt_cnt);
  675 
  676             if(error)
  677                 return INLINE_FAIL_OPEN_ERROR;
  678             else
  679                 return INLINE_FAIL_OPEN_COMPLETE;
  680         }
  681     }
  682 #endif
  683     return INLINE_FAIL_OPEN_NOT_USED;
  684 }
  685 
  686 /*
  687  *
  688  * Function: main(int, char *)
  689  *
  690  * Purpose:  Handle program entry and exit, call main prog sections
  691  *           This can handle both regular (command-line) style
  692  *           startup, as well as Win32 Service style startup.
  693  *
  694  * Arguments: See command line args in README file
  695  *
  696  * Returns: 0 => normal exit, 1 => exit on error
  697  *
  698  */
  699 int main(int argc, char *argv[])
  700 {
  701 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
  702     /* Do some sanity checking, because some people seem to forget to
  703      * put spaces between their parameters
  704      */
  705     if ((argc > 1) &&
  706         ((_stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_INSTALL_CMDLINE_PARAM)) == 0) ||
  707          (_stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_UNINSTALL_CMDLINE_PARAM)) == 0) ||
  708          (_stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_SHOW_CMDLINE_PARAM)) == 0)))
  709     {
  710         FatalError("You must have a space after the '%s' command-line parameter\n",
  711                    SERVICE_CMDLINE_PARAM);
  712     }
  713 
  714     /* If the first parameter is "/SERVICE", then start Snort as a Win32 service */
  715     if((argc > 1) && (_stricmp(argv[1],SERVICE_CMDLINE_PARAM) == 0))
  716     {
  717         return SnortServiceMain(argc, argv);
  718     }
  719 #endif /* WIN32 && ENABLE_WIN32_SERVICE */
  720 
  721     snort_argc = argc;
  722     snort_argv = argv;
  723 
  724     return SnortMain(argc, argv);
  725 }
  726 
  727 /*
  728  *
  729  * Function: SnortMain(int, char *)
  730  *
  731  * Purpose:  The real place that the program handles entry and exit.  Called
  732  *           called by main(), or by SnortServiceMain().
  733  *
  734  * Arguments: See command line args in README file
  735  *
  736  * Returns: 0 => normal exit, 1 => exit on error
  737  *
  738  */
  739 int SnortMain(int argc, char *argv[])
  740 {
  741     char* tmp_ptr = NULL;
  742     const char* intf;
  743     int daqInit;
  744 
  745 #ifndef WIN32
  746     // must be done now in case of fatal error
  747     // and again after daemonization
  748     snort_main_thread_id = pthread_self();
  749 #endif
  750 
  751     SnortInit(argc, argv);
  752     intf = GetPacketSource(&tmp_ptr);
  753     daqInit = intf || snort_conf->daq_type;
  754 
  755     if ( daqInit )
  756     {
  757         DAQ_Init(snort_conf);
  758         DAQ_New(snort_conf, intf);
  759         DAQ_UpdateTunnelBypass(snort_conf);
  760     }
  761     if ( tmp_ptr )
  762         free(tmp_ptr);
  763 
  764     if ( ScDaemonMode() )
  765     {
  766         GoDaemon();
  767     }
  768 
  769     // this must follow daemonization
  770     snort_main_thread_pid = gettid();
  771 #ifndef WIN32
  772     snort_main_thread_id = pthread_self();
  773 #endif
  774 
  775 #ifndef WIN32
  776     /* Change groups */
  777     InitGroups(ScUid(), ScGid());
  778 #endif
  779 
  780 #if !defined(HAVE_LINUXTHREADS) && !defined(WIN32)
  781     // this could be moved to linux threads location
  782     // and only done there
  783     SnortStartThreads();
  784 #endif
  785 
  786     ReloadControlSocketRegister();
  787     /* For SFR CLI*/
  788     ControlSocketRegisterHandler(CS_TYPE_ACTION_STATS, NULL, NULL, &DisplayActionStats);
  789 
  790     if (ControlSocketRegisterHandler(CS_TYPE_IS_PROCESSING, &IsProcessingPackets, NULL, NULL))
  791     {
  792         LogMessage("Failed to register the is processing control handler.\n");
  793     }
  794     if (ControlSocketRegisterHandler(CS_TYPE_PKT_TRACER, &DebugPktTracer, NULL, NULL))
  795     {
  796         LogMessage("Failed to register the packet tracer control handler.\n");
  797     }
  798 #ifdef CONTROL_SOCKET
  799     if (ControlSocketRegisterHandler(CS_TYPE_DUMP_PACKETS, &PacketDumpCommand, NULL, NULL))
  800     {
  801         LogMessage("Failed to register the packet dump control handler.\n");
  802     }
  803 #endif
  804     if (ControlSocketRegisterHandler(CS_TYPE_MEM_USAGE, &MemoryPreFunction, &MemoryControlFunction, &MemoryPostFunction))
  805     {
  806         LogMessage("Failed to register the memory stats display handler.\n");
  807     }
  808 
  809     if ( ScTestMode() )
  810     {
  811         if ( daqInit && DAQ_UnprivilegedStart() )
  812             SetPktProcessor();
  813         SnortUnprivilegedInit();
  814     }
  815     else if ( DAQ_UnprivilegedStart() )
  816     {
  817         SnortUnprivilegedInit();
  818         SetPktProcessor();
  819         DAQ_Start();
  820     }
  821     else
  822     {
  823         switch(InlineFailOpen())
  824         {
  825             case INLINE_FAIL_OPEN_COMPLETE:
  826                 break;
  827             case INLINE_FAIL_OPEN_NOT_USED:
  828                 DAQ_Start();
  829                 SetPktProcessor();
  830                 SnortUnprivilegedInit();
  831                 break;
  832             case INLINE_FAIL_OPEN_ERROR:
  833             default:
  834                 CleanExit(1);
  835                 return 0;
  836         }
  837     }
  838 #if defined(DAQ_CAPA_CST_TIMEOUT)
  839     Daq_Capa_Timeout = DAQ_CanGetTimeout();
  840     if(getDaqCapaTimeoutFnPtr)
  841     {
  842         getDaqCapaTimeoutFnPtr(Daq_Capa_Timeout);
  843     }
  844 #endif
  845 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
  846     Daq_Capa_Vrf = DAQ_CanGetVrf();
  847 #endif
  848 
  849     if(!exit_signal)
  850         PacketLoop();
  851 
  852     // DAQ is shutdown in CleanExit() since we don't always return here
  853     CleanExit(0);
  854 
  855     return 0;
  856 }
  857 
  858 #ifndef WIN32
  859 /* All threads need to be created after daemonizing.  If created in
  860  * the parent thread, when it goes away, so will all of the threads.
  861  * The child does not "inherit" threads created in the parent. */
  862 static void SnortStartThreads(void)
  863 {
  864 
  865     ControlSocketInit();
  866 
  867 #ifdef SIDE_CHANNEL
  868     SideChannelStartTXThread();
  869 #endif
  870 
  871 # ifdef SNORT_RELOAD
  872     if (ScIdsMode())
  873     {
  874         LogMessage("Reload thread starting...\n");
  875         if (pthread_create(&snort_reload_thread_id, NULL, ReloadConfigThread, NULL) != 0)
  876         {
  877             ErrorMessage("Could not create configuration reload thread.\n");
  878             CleanExit(1);
  879         }
  880 
  881         while (!snort_reload_thread_created)
  882             nanosleep(&thread_sleep, NULL);
  883 
  884         LogMessage("Reload thread started, thread %p (%u)\n",
  885                 (void*)snort_reload_thread_id, snort_reload_thread_pid);
  886     }
  887 # endif
  888 
  889 # ifdef TARGET_BASED
  890     if(IsAdaptiveConfigured() && !ScDisableAttrReload(snort_conf))
  891     SFAT_StartReloadThread();
  892 # endif
  893 }
  894 #else   /* WIN32 */
  895 //------------------------------------------------------------------------------
  896 // interface stuff
  897 //------------------------------------------------------------------------------
  898 
  899 static void PrintAllInterfaces (void)
  900 {
  901     char errorbuf[PCAP_ERRBUF_SIZE];
  902     pcap_if_t *alldevs;
  903     pcap_if_t *dev;
  904     int j = 1;
  905     MIB_IFTABLE *iftable = NULL;
  906     unsigned int len = 0;
  907     unsigned int ret, i;
  908 
  909     if (pcap_findalldevs(&alldevs, errorbuf) == -1)
  910         FatalError("Could not get device list: %s.", errorbuf);
  911 
  912     /* max of two iterations here -- first to get the
  913      * correct length if not big enough. Second to
  914      * get the data. */
  915     for (len = sizeof(iftable[0]); ; ) {
  916         if (iftable)
  917             free(iftable);
  918         iftable = SnortAlloc(len);
  919         ret = GetIfTable(iftable, &len, TRUE);
  920         if (ret == NO_ERROR)
  921             break;
  922         else if (ret != ERROR_INSUFFICIENT_BUFFER)
  923             FatalError("Could not get device list: %s.", errorbuf);;
  924     }
  925 
  926     printf("Index\tPhysical Address\tIP Address\tDevice Name\tDescription\n");
  927     printf("-----\t----------------\t----------\t-----------\t-----------\n");
  928 
  929     for (dev = alldevs; dev != NULL; dev = dev->next, j++)
  930     {
  931         uint8_t *mac_addr = NULL;
  932         for (i = 0; i<iftable->dwNumEntries; i++)
  933         {
  934             if (strncmp(dev->description, iftable->table[i].bDescr, iftable->table[i].dwDescrLen) == 0)
  935             {
  936                 mac_addr = iftable->table[i].bPhysAddr;
  937                 break;
  938             }
  939         }
  940         printf("%5d\t", j);
  941         if (mac_addr)
  942         {
  943             printf("%02X:%02X:%02X:%02X:%02X:%02X\t",
  944                 mac_addr[0], mac_addr[1], mac_addr[2],
  945                 mac_addr[3], mac_addr[4], mac_addr[5]);
  946         }
  947         else
  948         {
  949             printf("00:00:00:00:00:00\t");
  950         }
  951         if (dev->addresses)
  952         {
  953             struct sockaddr_in* saddr = (struct sockaddr_in*)dev->addresses->addr;
  954             sfcidr_t dev_ip;
  955             if ((saddr->sin_family == AF_INET) || (saddr->sin_family == AF_INET6))
  956             {
  957                 sfip_set_raw(&dev_ip, &saddr->sin_addr, saddr->sin_family);
  958                 printf("%s\t", inet_ntoa(&dev_ip));
  959             }
  960             else
  961             {
  962                 printf("disabled\t");
  963             }
  964             printf("%s\t%s\n", dev->name, dev->description);
  965         }
  966         else
  967         {
  968             printf("disabled\t%s\t%s\n", dev->name, dev->description);
  969         }
  970 
  971     }
  972     pcap_freealldevs(alldevs);
  973     free(iftable);
  974 }
  975 #endif  /* WIN32 */
  976 
  977 // pcap list stuff ...
  978 
  979 static void PQ_SetFilter (const char* f)
  980 {
  981     if (pcap_filter != NULL)
  982         free(pcap_filter);
  983 
  984     pcap_filter = f ? SnortStrdup(f) : NULL;
  985 }
  986 
  987 static void PQ_Single (const char* pcap)
  988 {
  989     PcapReadObject* pro;
  990 
  991     if (pcap_object_list == NULL)
  992     {
  993         pcap_object_list = sflist_new();
  994         if (pcap_object_list == NULL)
  995             FatalError("Could not allocate list to store pcap\n");
  996     }
  997 
  998     pro = (PcapReadObject *)SnortAlloc(sizeof(PcapReadObject));
  999     pro->type = PCAP_SINGLE;
 1000     pro->arg = SnortStrdup(pcap);
 1001     pro->filter = NULL;
 1002 
 1003     if (sflist_add_tail(pcap_object_list, (NODE_DATA)pro) == -1)
 1004         FatalError("Could not add pcap object to list: %s\n", pcap);
 1005 }
 1006 
 1007 static void PQ_Multi (char type, const char* list)
 1008 {
 1009     PcapReadObject* pro;
 1010 
 1011     if (pcap_object_list == NULL)
 1012     {
 1013         pcap_object_list = sflist_new();
 1014         if (pcap_object_list == NULL)
 1015             FatalError("Could not allocate list to store pcaps\n");
 1016     }
 1017 
 1018     pro = (PcapReadObject *)SnortAlloc(sizeof(PcapReadObject));
 1019     pro->type = type;
 1020     pro->arg = SnortStrdup(list);
 1021     if (pcap_filter != NULL)
 1022         pro->filter = SnortStrdup(pcap_filter);
 1023     else
 1024         pro->filter = NULL;
 1025 
 1026     if (sflist_add_tail(pcap_object_list, (NODE_DATA)pro) == -1)
 1027         FatalError("Could not add pcap object to list: %s\n", list);
 1028 }
 1029 
 1030 static void PQ_SetUp (void)
 1031 {
 1032     if (pcap_object_list != NULL)
 1033     {
 1034         if (sflist_count(pcap_object_list) == 0)
 1035         {
 1036             sflist_free_all(pcap_object_list, NULL);
 1037             FatalError("No pcaps specified.\n");
 1038         }
 1039 
 1040         pcap_queue = sfqueue_new();
 1041         pcap_save_queue = sfqueue_new();
 1042         if ((pcap_queue == NULL) || (pcap_save_queue == NULL))
 1043             FatalError("Could not allocate pcap queues.\n");
 1044 
 1045         if (GetPcaps(pcap_object_list, pcap_queue) == -1)
 1046             FatalError("Error getting pcaps.\n");
 1047 
 1048         if (sfqueue_count(pcap_queue) == 0)
 1049             FatalError("No pcaps found.\n");
 1050 
 1051         /* free pcap list used to get params */
 1052         while (sflist_count(pcap_object_list) > 0)
 1053         {
 1054             PcapReadObject *pro = (PcapReadObject *)sflist_remove_head(pcap_object_list);
 1055             if (pro == NULL)
 1056                 FatalError("Failed to remove pcap item from list.\n");
 1057 
 1058             if (pro->arg != NULL)
 1059                 free(pro->arg);
 1060 
 1061             if (pro->filter != NULL)
 1062                 free(pro->filter);
 1063 
 1064             free(pro);
 1065         }
 1066 
 1067         sflist_free_all(pcap_object_list, NULL);
 1068         pcap_object_list = NULL;
 1069     }
 1070     if (pcap_filter != NULL)
 1071     {
 1072         free(pcap_filter);
 1073         pcap_filter = NULL;
 1074     }
 1075 }
 1076 
 1077 static int PQ_CleanUp (void)
 1078 {
 1079     /* clean up pcap queues */
 1080     if (pcap_queue != NULL)
 1081         sfqueue_free_all(pcap_queue, free);
 1082 
 1083     if (pcap_save_queue != NULL)
 1084         sfqueue_free_all(pcap_save_queue, free);
 1085 
 1086     return 0;
 1087 }
 1088 
 1089 static void PQ_Show (const char* pcap)
 1090 {
 1091     if ( !ScPcapShow() )
 1092         return;
 1093 
 1094     if ( !strcmp(pcap, "-") ) pcap = "stdin";
 1095 
 1096     fprintf(stdout,
 1097         "Reading network traffic from \"%s\" with snaplen = %d\n",
 1098         pcap, DAQ_GetSnapLen());
 1099 }
 1100 
 1101 static const char* PQ_First (void)
 1102 {
 1103     const char* pcap = (char*)sfqueue_remove(pcap_queue);
 1104 
 1105     if ( !pcap )
 1106         return pcap;
 1107 
 1108     if ( sfqueue_add(pcap_save_queue, (NODE_DATA)pcap) == -1 )
 1109         FatalError("Could not add pcap to saved list\n");
 1110 
 1111     return pcap;
 1112 }
 1113 
 1114 // this must follow 2nd or later start and not stop because we force a
 1115 // reset when the dlt changes even if not enabled with --pcap-reset to
 1116 // avoid eventually flushing stream packets through a different grinder
 1117 // than the one they were queued with.
 1118 static void PQ_Reset ()
 1119 {
 1120     static int dlt = -1;
 1121     int new_dlt = DAQ_GetBaseProtocol();
 1122 
 1123     if ( ScPcapReset() || ((dlt != new_dlt) && (dlt != -1)) )
 1124         SnortReset();
 1125 
 1126     dlt = new_dlt;
 1127 
 1128     /* open a new tcpdump file - necessary because the snaplen and
 1129      * datalink could be different between pcaps */
 1130     if (snort_conf->log_tcpdump)
 1131     {
 1132         /* this sleep is to ensure we get a new log file since it has a
 1133          * time stamp with resolution to the second */
 1134 #ifdef WIN32
 1135         Sleep(1000);
 1136 #else
 1137         sleep(1);
 1138 #endif
 1139         LogTcpdumpReset();
 1140     }
 1141 }
 1142 
 1143 static int PQ_Next (void)
 1144 {
 1145     char reopen_pcap = 0;
 1146 
 1147     if (sfqueue_count(pcap_queue) > 0)
 1148     {
 1149         reopen_pcap = 1;
 1150     }
 1151     else if (pcap_loop_count)
 1152     {
 1153         if (pcap_loop_count > 0)
 1154             pcap_loop_count--;
 1155 
 1156         if (pcap_loop_count != 0)
 1157         {
 1158             SF_QUEUE *tmp;
 1159 
 1160             /* switch pcap lists */
 1161             tmp = pcap_queue;
 1162             pcap_queue = pcap_save_queue;
 1163             pcap_save_queue = tmp;
 1164 
 1165             reopen_pcap = 1;
 1166         }
 1167     }
 1168 
 1169     if (reopen_pcap)
 1170     {
 1171         /* reinitialize pcap */
 1172         const char* pcap = PQ_First();
 1173 
 1174         if ( !pcap )
 1175             FatalError("Could not get pcap from list\n");
 1176 
 1177         DAQ_Stop();
 1178         DAQ_Delete();
 1179 
 1180         DAQ_New(snort_conf, pcap);
 1181         DAQ_Start();
 1182 
 1183         PQ_Reset();
 1184         PQ_Show(pcap);
 1185         SetPktProcessor();
 1186 
 1187 #if defined(SNORT_RELOAD) && !defined(WIN32)
 1188         if ( snort_conf->run_flags & RUN_FLAG__PCAP_RELOAD && ScIdsMode())
 1189         {
 1190             /* Awaiting user confirmation */
 1191             printf("Hit return to continue.\n");
 1192             fflush(stdout);
 1193             while(getc(stdin) != '\n');
 1194 
 1195             SigReloadHandler(SIGNAL_SNORT_RELOAD);
 1196 
 1197             while (!snort_reload)
 1198                 sleep(1);
 1199         }
 1200 #endif
 1201 
 1202         return 1;
 1203     }
 1204     return 0;
 1205 }
 1206 
 1207 static char* GetFirstInterface (void)
 1208 {
 1209     char *iface = NULL;
 1210     char errorbuf[PCAP_ERRBUF_SIZE];
 1211 #ifdef WIN32
 1212     pcap_if_t *alldevs;
 1213 
 1214     if ( (pcap_findalldevs(&alldevs, errorbuf) == -1) || !alldevs )
 1215     {
 1216         FatalError( "Failed to lookup interface: %s. "
 1217             "Please specify one with -i switch\n", errorbuf);
 1218     }
 1219 
 1220     /* Pick first interface */
 1221     iface = SnortStrdup(alldevs->name);
 1222     pcap_freealldevs(alldevs);
 1223 #else
 1224     DEBUG_WRAP(DebugMessage(
 1225         DEBUG_INIT, "interface is NULL, looking up interface...."););
 1226 
 1227     /* look up the device and get the handle */
 1228     iface = pcap_lookupdev(errorbuf);
 1229 
 1230     if ( !iface )
 1231     {
 1232         FatalError( "Failed to lookup interface: %s. "
 1233             "Please specify one with -i switch\n", errorbuf);
 1234     }
 1235 
 1236     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "found interface %s\n",
 1237                             PRINT_INTERFACE(iface)););
 1238 
 1239     iface = SnortStrdup(iface);
 1240 #endif
 1241     return iface;
 1242 }
 1243 
 1244 static const char* GetPacketSource (char** sptr)
 1245 {
 1246     const char* intf = "other";
 1247 
 1248     if ( ScReadMode() )
 1249     {
 1250         intf = PQ_First();
 1251         PQ_Show(intf);
 1252     }
 1253     else if ( !ScVersionMode() && !ScRuleDumpMode() )
 1254     {
 1255         intf = snort_conf->interface;
 1256 
 1257         // don't get interface if daq is explicitly configured
 1258         // since we can't assume that an interface is compatible
 1259         if ( !intf && !ScTestMode() &&
 1260             (!snort_conf->daq_type ||
 1261             // but we make execptions for these:
 1262             // TBD make selection based on DAQ_TYPE_XXX
 1263             !strcasecmp(snort_conf->daq_type, "afpacket") ||
 1264             !strcasecmp(snort_conf->daq_type, "pcap") ||
 1265             !strcasecmp(snort_conf->daq_type, "dump")) )
 1266         {
 1267             intf = GetFirstInterface();
 1268             *sptr = (char*)intf;
 1269         }
 1270     }
 1271     return intf;
 1272 }
 1273 
 1274 static void InitPidChrootAndPrivs(pid_t pid)
 1275 {
 1276 
 1277 #ifndef WIN32
 1278     /* Drop the Chrooted Settings */
 1279     if (snort_conf->chroot_dir)
 1280         SetChroot(snort_conf->chroot_dir, &snort_conf->log_dir);
 1281 
 1282     /* Drop privileges if requested, when initialization is done */
 1283     SetUidGid(ScUid(), ScGid());
 1284 #endif
 1285     /* create the PID file */
 1286     if ( !ScReadMode() &&
 1287        (ScDaemonMode() || *snort_conf->pidfile_suffix || ScCreatePidFile()))
 1288     {
 1289        CreatePidFile(DAQ_GetInterfaceSpec(), pid);
 1290     }
 1291 }
 1292 
 1293 static void LoadDynamicPlugins(SnortConfig *sc)
 1294 {
 1295     unsigned i;
 1296 
 1297     if (sc == NULL)
 1298         return;
 1299 
 1300     if (sc->dyn_engines != NULL)
 1301     {
 1302         /* Load the dynamic engines */
 1303         for (i = 0; i < sc->dyn_engines->count; i++)
 1304         {
 1305             switch (sc->dyn_engines->lib_paths[i]->ptype)
 1306             {
 1307                 case PATH_TYPE__FILE:
 1308                     LoadDynamicEngineLib(sc, sc->dyn_engines->lib_paths[i]->path, 0);
 1309                     break;
 1310 
 1311                 case PATH_TYPE__DIRECTORY:
 1312                     LoadAllDynamicEngineLibs(sc, sc->dyn_engines->lib_paths[i]->path);
 1313                     break;
 1314             }
 1315         }
 1316     }
 1317 
 1318     if (sc->dyn_rules != NULL)
 1319     {
 1320         /* Load the dynamic detection libs */
 1321         for (i = 0; i < sc->dyn_rules->count; i++)
 1322         {
 1323             switch (sc->dyn_rules->lib_paths[i]->ptype)
 1324             {
 1325                 case PATH_TYPE__FILE:
 1326                     LoadDynamicDetectionLib(sc, sc->dyn_rules->lib_paths[i]->path, 0);
 1327                     break;
 1328 
 1329                 case PATH_TYPE__DIRECTORY:
 1330                     LoadAllDynamicDetectionLibs(sc, sc->dyn_rules->lib_paths[i]->path);
 1331                     break;
 1332             }
 1333         }
 1334     }
 1335 
 1336     if (sc->dyn_preprocs != NULL)
 1337     {
 1338         /* Load the dynamic preprocessors */
 1339         for (i = 0; i < sc->dyn_preprocs->count; i++)
 1340         {
 1341             switch (sc->dyn_preprocs->lib_paths[i]->ptype)
 1342             {
 1343                 case PATH_TYPE__FILE:
 1344                     LoadDynamicPreprocessor(sc, sc->dyn_preprocs->lib_paths[i]->path, 0);
 1345                     break;
 1346 
 1347                 case PATH_TYPE__DIRECTORY:
 1348                     LoadAllDynamicPreprocessors(sc, sc->dyn_preprocs->lib_paths[i]->path);
 1349                     break;
 1350             }
 1351         }
 1352     }
 1353 
 1354 # ifdef SIDE_CHANNEL
 1355     if (sc->dyn_side_channels != NULL)
 1356     {
 1357         /* Load the dynamic side channels */
 1358         for (i = 0; i < sc->dyn_side_channels->count; i++)
 1359         {
 1360             switch (sc->dyn_side_channels->lib_paths[i]->ptype)
 1361             {
 1362                 case PATH_TYPE__FILE:
 1363                     LoadDynamicSideChannelLib(sc, sc->dyn_side_channels->lib_paths[i]->path, 0);
 1364                     break;
 1365 
 1366                 case PATH_TYPE__DIRECTORY:
 1367                     LoadAllDynamicSideChannelLibs(sc, sc->dyn_side_channels->lib_paths[i]->path);
 1368                     break;
 1369             }
 1370         }
 1371     }
 1372 # endif /* SIDE_CHANNEL */
 1373 
 1374     ValidateDynamicEngines(sc);
 1375 }
 1376 
 1377 static void DisplayDynamicPluginVersions(SnortConfig *sc)
 1378 {
 1379     void *lib = NULL;
 1380     DynamicPluginMeta *meta;
 1381 
 1382     RemoveDuplicateEngines();
 1383     RemoveDuplicateDetectionPlugins(sc);
 1384     RemoveDuplicatePreprocessorPlugins();
 1385 #ifdef SIDE_CHANNEL
 1386     RemoveDuplicateSideChannelPlugins();
 1387 #endif /* SIDE_CHANNEL */
 1388 
 1389     lib = GetNextEnginePluginVersion(NULL);
 1390     while ( lib != NULL )
 1391     {
 1392         meta = GetDetectionPluginMetaData(lib);
 1393 
 1394         LogMessage("           Rules Engine: %s  Version %d.%d  <Build %d>\n",
 1395                    meta->uniqueName, meta->major, meta->minor, meta->build);
 1396         lib = GetNextEnginePluginVersion(lib);
 1397     }
 1398 
 1399     lib = GetNextDetectionPluginVersion(sc, NULL);
 1400     while ( lib != NULL )
 1401     {
 1402         meta = GetEnginePluginMetaData(lib);
 1403 
 1404         LogMessage("           Rules Object: %s  Version %d.%d  <Build %d>\n",
 1405                    meta->uniqueName, meta->major, meta->minor, meta->build);
 1406         lib = GetNextDetectionPluginVersion(sc, lib);
 1407     }
 1408 
 1409     lib = GetNextPreprocessorPluginVersion(NULL);
 1410     while ( lib != NULL )
 1411     {
 1412         meta = GetPreprocessorPluginMetaData(lib);
 1413 
 1414         LogMessage("           Preprocessor Object: %s  Version %d.%d  <Build %d>\n",
 1415                    meta->uniqueName, meta->major, meta->minor, meta->build);
 1416         lib = GetNextPreprocessorPluginVersion(lib);
 1417     }
 1418 
 1419 #ifdef SIDE_CHANNEL
 1420     lib = GetNextSideChannelPluginVersion(NULL);
 1421     while ( lib != NULL )
 1422     {
 1423         meta = GetSideChannelPluginMetaData(lib);
 1424 
 1425         LogMessage("           Side Channel Object: %s  Version %d.%d  <Build %d>\n",
 1426                    meta->uniqueName, meta->major, meta->minor, meta->build);
 1427         lib = GetNextSideChannelPluginVersion(lib);
 1428     }
 1429 #endif /* SIDE_CHANNEL */
 1430 
 1431     lib = GetNextOutputModule(NULL);
 1432     while ( lib != NULL )
 1433     {
 1434         LogMessage("           Output Module: %s  Version %u\n",
 1435             GetOutputModuleName(lib), GetOutputModuleVersion(lib));
 1436         lib = GetNextOutputModule(lib);
 1437     }
 1438 }
 1439 
 1440 /*
 1441  * This function will print versioning information regardless of whether or
 1442  * not the quiet flag is set.  If the quiet flag has been set and we want
 1443  * to honor it, check it before calling this function.
 1444  */
 1445 static void PrintVersion(SnortConfig *sc)
 1446 {
 1447     DisplayBanner();
 1448 
 1449 /*  Get and print out library versions.
 1450  *  This information would be printed only for one Snort instance which doesn't
 1451  *  have --suppress-config-log option. For Snort instances with --supress-config-log,
 1452  *  we print only banner to provide some info about Snort process being started/reloaded.
 1453  *  This change is done to avoid duplicate logging of plugin information.
 1454  */
 1455     if (ScSuppressConfigLog())
 1456         ScSetInternalLogLevel(INTERNAL_LOG_LEVEL__ERROR);
 1457 
 1458     DisplayDynamicPluginVersions(sc);
 1459 
 1460     ScRestoreInternalLogLevel();
 1461 }
 1462 
 1463 static void PrintDaqModules (SnortConfig* sc, char* dir)
 1464 {
 1465     if ( dir )
 1466         ConfigDaqDir(sc, dir);
 1467 
 1468     DAQ_Load(snort_conf);
 1469     DAQ_PrintTypes(stdout);
 1470     DAQ_Unload();
 1471 }
 1472 
 1473 #ifdef EXIT_CHECK
 1474 static uint64_t exitTime = 0;
 1475 
 1476 static void ExitCheckStart (void)
 1477 {
 1478     if ( exitTime )
 1479     {
 1480         return;
 1481     }
 1482     LogMessage("Exit Check: signaling at " STDu64 "callback\n", pc.total_from_daq);
 1483     get_clockticks(exitTime);
 1484 #ifndef WIN32
 1485     kill(0, SIGINT);  // send to all processes in my process group
 1486 #else
 1487     raise(SIGINT);
 1488 #endif
 1489 }
 1490 
 1491 static void ExitCheckEnd (void)
 1492 {
 1493     uint64_t now = 0;
 1494     double usecs = 0.0;
 1495 
 1496     if ( !exitTime )
 1497     {
 1498         LogMessage(
 1499             "Exit Check: callbacks = " STDu64 "(limit not reached)\n",
 1500             pc.total_from_daq
 1501         );
 1502         return;
 1503     }
 1504     get_clockticks(now);
 1505     exitTime = now - exitTime;
 1506     usecs = exitTime / get_ticks_per_usec();
 1507 
 1508     LogMessage("Exit Check: usecs = %f\n", usecs);
 1509 }
 1510 #endif
 1511 
 1512 #ifdef HAVE_DAQ_ACQUIRE_WITH_META
 1513 static int MetaCallback(
 1514     void* user, const DAQ_MetaHdr_t *metahdr, const uint8_t* data)
 1515 {
 1516     tSfPolicyId policy_id = getDefaultPolicy();
 1517     SnortPolicy *policy;
 1518     PreprocMetaEvalFuncNode *idx;
 1519     PROFILE_VARS;
 1520 
 1521 #ifdef SIDE_CHANNEL
 1522     if (ScSideChannelEnabled() && !snort_process_lock_held)
 1523     {
 1524         pthread_mutex_lock(&snort_process_lock);
 1525         snort_process_lock_held = true;
 1526     }
 1527 #endif
 1528 
 1529     /* First thing we do is process a Usr signal that we caught */
 1530     if (SignalCheck())
 1531     {
 1532 #ifndef SNORT_RELOAD
 1533         /* Got SIGNAL_SNORT_RELOAD */
 1534         Restart();
 1535 #endif
 1536     }
 1537 
 1538     CheckForReload();
 1539 
 1540     PREPROC_PROFILE_START(metaPerfStats);
 1541 
 1542     policy = snort_conf->targeted_policies[policy_id];
 1543     idx = policy->preproc_meta_eval_funcs;
 1544     while (idx != NULL)
 1545     {
 1546         idx->func(metahdr->type, data);
 1547         idx = idx->next;
 1548     }
 1549 
 1550     PREPROC_PROFILE_END(metaPerfStats);
 1551 
 1552 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
 1553     if (ScTerminateService() || ScPauseService())
 1554     {
 1555         return 0;  // time to go
 1556     }
 1557 #endif
 1558 
 1559 #ifdef SNORT_RELOAD
 1560     ReloadAdjust(false, 0);
 1561 #endif
 1562     ControlSocketDoWork(0);
 1563 #ifdef SIDE_CHANNEL
 1564     SideChannelDrainRX(0);
 1565 #endif
 1566 
 1567     return 0;
 1568 }
 1569 #endif
 1570 
 1571 void SetupMetadataCallback(void)
 1572 {
 1573 #ifdef HAVE_DAQ_ACQUIRE_WITH_META
 1574     DAQ_Set_MetaCallback(&MetaCallback);
 1575 #endif
 1576 }
 1577 
 1578 // non-local for easy access from core
 1579 static Packet s_packet;
 1580 static DAQ_PktHdr_t s_pkth;
 1581 static uint8_t s_data[65536];
 1582 
 1583 static DAQ_Verdict PacketCallback(
 1584     void* user, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
 1585 {
 1586     int inject = 0;
 1587     DAQ_Verdict verdict = DAQ_VERDICT_PASS;
 1588     verdict_reason = VERDICT_REASON_NO_BLOCK;
 1589     PROFILE_VARS;
 1590 
 1591     PREPROC_PROFILE_START_PI(totalPerfStats);
 1592 
 1593 #ifdef SIDE_CHANNEL
 1594     if (ScSideChannelEnabled() && !snort_process_lock_held)
 1595     {
 1596         pthread_mutex_lock(&snort_process_lock);
 1597         snort_process_lock_held = true;
 1598     }
 1599 #endif
 1600 
 1601 #ifdef EXIT_CHECK
 1602     if (snort_conf->exit_check && (pc.total_from_daq >= snort_conf->exit_check))
 1603         ExitCheckStart();
 1604 #endif
 1605 
 1606     /* First thing we do is process a Usr signal that we caught */
 1607     if (SignalCheck())
 1608     {
 1609 #ifndef SNORT_RELOAD
 1610         /* Got SIGNAL_SNORT_RELOAD */
 1611         PREPROC_PROFILE_END_PI(totalPerfStats);
 1612         Restart();
 1613 #endif
 1614     }
 1615 
 1616     pc.total_from_daq++;
 1617 
 1618     /* Increment counter that we're evaling rules for caching results */
 1619     rule_eval_pkt_count++;
 1620 
 1621 #ifdef TARGET_BASED
 1622     /* Load in a new attribute table if we need to... */
 1623     AttributeTableReloadCheck();
 1624 #endif
 1625 
 1626     CheckForReload();
 1627 
 1628     /* Save off the time of each and every packet */
 1629     packet_time_update(&pkthdr->ts);
 1630 
 1631 #ifdef REG_TEST
 1632     if ( snort_conf->pkt_skip && pc.total_from_daq <= snort_conf->pkt_skip )
 1633     {
 1634         PREPROC_PROFILE_END_PI(totalPerfStats);
 1635         return verdict;
 1636     }
 1637 #endif
 1638 
 1639 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
 1640     if (ScTerminateService() || ScPauseService())
 1641     {
 1642         PREPROC_PROFILE_END_PI(totalPerfStats);
 1643         return verdict;  // time to go
 1644     }
 1645 #endif
 1646 
 1647     /* reset the thresholding subsystem checks for this packet */
 1648     sfthreshold_reset();
 1649 
 1650     PREPROC_PROFILE_START(eventqPerfStats);
 1651     SnortEventqReset();
 1652     Replace_ResetQueue();
 1653 #ifdef ACTIVE_RESPONSE
 1654     Active_ResetQueue();
 1655 #endif
 1656     PREPROC_PROFILE_END(eventqPerfStats);
 1657 
 1658     verdict = ProcessPacket(&s_packet, pkthdr, pkt, NULL);
 1659 
 1660 #ifdef ACTIVE_RESPONSE
 1661     if ( Active_ResponseQueued() )
 1662     {
 1663         Active_SendResponses(&s_packet);
 1664     }
 1665 #endif
 1666 
 1667     if ( Active_PacketWasDropped() )
 1668     {
 1669         if ( verdict == DAQ_VERDICT_PASS )
 1670         {
 1671 #ifdef HAVE_DAQ_VERDICT_RETRY
 1672             if ( Active_RetryIsPending() && !(s_packet.packet_flags & PKT_RETRANSMIT) )
 1673                 verdict = DAQ_VERDICT_RETRY;
 1674             else
 1675                 verdict = DAQ_VERDICT_BLOCK;
 1676 #else
 1677             verdict = DAQ_VERDICT_BLOCK;
 1678 #endif
 1679         }
 1680     }
 1681     else
 1682     {
 1683         Replace_ModifyPacket(&s_packet);
 1684 
 1685         if ( s_packet.packet_flags & PKT_MODIFIED )
 1686         {
 1687             // this packet was normalized and/or has replacements
 1688             Encode_Update(&s_packet);
 1689             verdict = DAQ_VERDICT_REPLACE;
 1690         }
 1691 #ifdef NORMALIZER
 1692         else if ( s_packet.packet_flags & PKT_RESIZED )
 1693         {
 1694             // we never increase, only trim, but
 1695             // daq doesn't support resizing wire packet
 1696             if ( !DAQ_Inject(s_packet.pkth, 0, s_packet.pkt, s_packet.pkth->pktlen) )
 1697             {
 1698                 verdict = DAQ_VERDICT_BLOCK;
 1699                 inject = 1;
 1700             }
 1701         }
 1702 #endif
 1703         else
 1704         {
 1705             if ((s_packet.packet_flags & PKT_IGNORE) ||
 1706                 (session_api && (session_api->get_ignore_direction(s_packet.ssnptr) == SSN_DIR_BOTH)))
 1707             {
 1708                 if ( !Active_GetTunnelBypass() )
 1709                 {
 1710                     verdict = DAQ_VERDICT_WHITELIST;
 1711                 }
 1712                 else
 1713                 {
 1714                     verdict = DAQ_VERDICT_PASS;
 1715                     pc.internal_whitelist++;
 1716                 }
 1717             }
 1718             else if ( s_packet.packet_flags & PKT_TRUST )
 1719             {
 1720                 if (session_api)
 1721                     session_api->set_ignore_direction(s_packet.ssnptr, SSN_DIR_BOTH);
 1722 
 1723                 verdict = DAQ_VERDICT_WHITELIST;
 1724             }
 1725             else
 1726             {
 1727                 verdict = DAQ_VERDICT_PASS;
 1728             }
 1729         }
 1730     }
 1731 
 1732 #if defined(HAVE_DAQ_LOCALLY_ORIGINATED) && defined(HAVE_DAQ_LOCALLY_DESTINED)
 1733     /* Don't whitelist packets to/from internal endpoints */
 1734     if (verdict == DAQ_VERDICT_WHITELIST && (pkthdr->flags & (DAQ_PKT_FLAG_LOCALLY_DESTINED | DAQ_PKT_FLAG_LOCALLY_ORIGINATED)))
 1735     {
 1736         verdict = DAQ_VERDICT_PASS;
 1737     }
 1738 #endif
 1739 
 1740 #ifdef ENABLE_HA
 1741     /* This needs to be called here since the session could have been updated anywhere up to this point. :( */
 1742     if (session_api)
 1743         session_api->process_ha(s_packet.ssnptr, pkthdr);
 1744 #endif
 1745 
 1746     /* Collect some "on the wire" stats about packet size, etc */
 1747     UpdateWireStats(&sfBase, pkthdr->caplen, Active_PacketWasDropped(), inject);
 1748     Active_Reset();
 1749     Encode_Reset();
 1750 
 1751     if( session_api )
 1752         session_api->check_session_timeout(4, pkthdr->ts.tv_sec);
 1753 #ifdef SNORT_RELOAD
 1754     ReloadAdjust(false, pkthdr->ts.tv_sec);
 1755 #endif
 1756     ControlSocketDoWork(0);
 1757 #ifdef SIDE_CHANNEL
 1758     SideChannelDrainRX(0);
 1759 #endif
 1760 
 1761     if ((verdict == DAQ_VERDICT_BLOCK || verdict == DAQ_VERDICT_BLACKLIST) && (verdict_reason == VERDICT_REASON_NO_BLOCK))
 1762         verdict_reason = VERDICT_REASON_UNKNOWN;
 1763 #ifdef HAVE_DAQ_VERDICT_RETRY
 1764     if (verdict == DAQ_VERDICT_RETRY && verdict_reason == VERDICT_REASON_NO_BLOCK)
 1765         verdict_reason = VERDICT_REASON_DAQRETRY;
 1766 #endif
 1767     if (pkt_trace_enabled)
 1768         writePktTraceData(verdict, getNapRuntimePolicy(), getIpsRuntimePolicy(), &s_packet);
 1769 #if defined(HAVE_DAQ_EXT_MODFLOW) && defined(HAVE_DAQ_VERDICT_REASON)
 1770     if (verdict_reason != VERDICT_REASON_NO_BLOCK)
 1771         sendReason(&s_packet);
 1772 #endif
 1773 
 1774 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
 1775     if (pkthdr->flags  & DAQ_PKT_FLAG_DEBUG_ON)
 1776     {
 1777         print_pktverdict(&s_packet,verdict);
 1778     }
 1779 #endif
 1780 
 1781     s_packet.pkth = NULL;  // no longer avail on segv
 1782 
 1783     PREPROC_PROFILE_END_PI(totalPerfStats);
 1784     return verdict;
 1785 }
 1786 
 1787 static void PrintPacket(Packet *p)
 1788 {
 1789     if (p->iph != NULL)
 1790     {
 1791         PrintIPPkt(stdout, GET_IPH_PROTO((p)), p);
 1792     }
 1793 #ifndef NO_NON_ETHER_DECODER
 1794     else if (p->ah != NULL)
 1795     {
 1796         PrintArpHeader(stdout, p);
 1797     }
 1798     else if (p->eplh != NULL)
 1799     {
 1800         PrintEapolPkt(stdout, p);
 1801     }
 1802     else if (p->wifih && ScOutputWifiMgmt())
 1803     {
 1804         PrintWifiPkt(stdout, p);
 1805     }
 1806 #endif  // NO_NON_ETHER_DECODER
 1807 }
 1808 
 1809 DAQ_Verdict ProcessPacket(
 1810     Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, void* ft)
 1811 {
 1812     DAQ_Verdict verdict = DAQ_VERDICT_PASS;
 1813 
 1814     // set runtime policy to default...idx is same for both nap & ips
 1815     setNapRuntimePolicy(getDefaultPolicy());
 1816     setIpsRuntimePolicy(getDefaultPolicy());
 1817 
 1818     /* call the packet decoder */
 1819     (*grinder) (p, pkthdr, pkt);
 1820     assert(p->pkth && p->pkt);
 1821 
 1822     if (ft)
 1823     {
 1824         p->packet_flags |= (PKT_PSEUDO | PKT_REBUILT_FRAG);
 1825         p->pseudo_type = PSEUDO_PKT_IP;
 1826         p->fragtracker = ft;
 1827         Encode_SetPkt(p);
 1828     }
 1829     if ( !p->proto_bits )
 1830         p->proto_bits = PROTO_BIT__OTHER;
 1831 
 1832     // required until decoders are fixed
 1833     else if ( !p->family && (p->proto_bits & PROTO_BIT__IP) )
 1834         p->proto_bits &= ~PROTO_BIT__IP;
 1835 
 1836     /***** Policy specific decoding should into this function *****/
 1837     p->configPolicyId = snort_conf->targeted_policies[ getNapRuntimePolicy() ]->configPolicyId;
 1838 
 1839 #if defined(HAVE_DAQ_EXT_MODFLOW) && defined(HAVE_DAQ_PKT_TRACE)
 1840     if (pkt_trace_cli_flag || (pkthdr->flags & DAQ_PKT_FLAG_TRACE_ENABLED))
 1841 #else
 1842     if (pkt_trace_cli_flag)
 1843 #endif
 1844     {
 1845         pkt_trace_enabled = pktTracerDebugCheck(p);
 1846         if (pkt_trace_enabled)
 1847         {
 1848             addPktTraceInfo(p);
 1849             if (p->packet_flags & PKT_IGNORE)
 1850                 addPktTraceData(VERDICT_REASON_SNORT, snprintf(trace_line, MAX_TRACE_LINE, "Snort: packet ignored\n"));
 1851         }
 1852     }
 1853     else
 1854         pkt_trace_enabled = false;
 1855 
 1856     /* just throw away the packet if we are configured to ignore this port */
 1857     if ( !(p->packet_flags & PKT_IGNORE) )
 1858     {
 1859         /* start calling the detection processes */
 1860         Preprocess(p);
 1861         log_func(p);
 1862     }
 1863     else if (!pkt_trace_enabled) // ignored packet
 1864         addPktTraceData(VERDICT_REASON_SNORT, 0);
 1865 
 1866     if ( Active_SessionWasDropped() )
 1867     {
 1868         if ( !Active_PacketForceDropped() )
 1869             Active_DropAction(p);
 1870         else
 1871             Active_ForceDropAction(p);
 1872 
 1873         if ( Active_GetTunnelBypass() )
 1874             pc.internal_blacklist++;
 1875         else if ( ScIpsInlineMode() || Active_PacketForceDropped() )
 1876     {
 1877             verdict = DAQ_VERDICT_BLACKLIST;
 1878     }
 1879         else
 1880             verdict = DAQ_VERDICT_IGNORE;
 1881     }
 1882 
 1883 #ifdef CONTROL_SOCKET
 1884     if (packet_dump_stop)
 1885         PacketDumpClose();
 1886     else if (packet_dump_file &&
 1887 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
 1888 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
 1889              ((pkthdr->address_space_id_src == packet_dump_address_space_id) || 
 1890              (pkthdr->address_space_id_dst == packet_dump_address_space_id)) && 
 1891 #else
 1892              pkthdr->address_space_id == packet_dump_address_space_id &&
 1893 #endif
 1894 #endif
 1895              (!packet_dump_fcode.bf_insns || sfbpf_filter(packet_dump_fcode.bf_insns, (uint8_t *)pkt,
 1896                                                           pkthdr->caplen, pkthdr->pktlen)))
 1897     {
 1898         pcap_dump((uint8_t*)packet_dump_file, (const struct pcap_pkthdr*)pkthdr, pkt);
 1899         pcap_dump_flush((pcap_dumper_t*)packet_dump_file);
 1900     }
 1901 #endif
 1902 
 1903     return verdict;
 1904 }
 1905 
 1906 Packet *NewGrinderPkt(Packet *p, DAQ_PktHdr_t* phdr, uint8_t *pkt)
 1907 {
 1908     if( !p )
 1909     {
 1910         IP6Option* ip6_extensions;
 1911         p = SnortAlloc(sizeof(*p));
 1912         ip6_extensions = SnortAlloc(sizeof(IP6Option) * ScMaxIP6Extensions());
 1913 
 1914         if ( !p || !ip6_extensions )
 1915             FatalError("Encode_New() => Failed to allocate packet\n");
 1916 
 1917         p->ip6_extensions = ip6_extensions;
 1918     }
 1919 
 1920     if ( phdr && pkt )
 1921     {
 1922         (*grinder)(p, phdr, pkt);
 1923     }
 1924 
 1925 
 1926     return p;
 1927 }
 1928 
 1929 void DeleteGrinderPkt( Packet *p)
 1930 {
 1931     if(!p)
 1932         return;
 1933 
 1934     if(p->ip6_extensions)
 1935         free(p->ip6_extensions);
 1936 
 1937     free(p);
 1938 }
 1939 
 1940 
 1941 /*
 1942  * Function: ShowUsage(char *)
 1943  *
 1944  * Purpose:  Display the program options and exit
 1945  *
 1946  * Arguments: argv[0] => name of the program (argv[0])
 1947  *
 1948  * Returns: 0 => success
 1949  */
 1950 static int ShowUsage(char *program_name)
 1951 {
 1952     fprintf(stdout, "USAGE: %s [-options] <filter options>\n", program_name);
 1953 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
 1954     fprintf(stdout, "       %s %s %s [-options] <filter options>\n", program_name
 1955                                                                    , SERVICE_CMDLINE_PARAM
 1956                                                                    , SERVICE_INSTALL_CMDLINE_PARAM);
 1957     fprintf(stdout, "       %s %s %s\n", program_name
 1958                                        , SERVICE_CMDLINE_PARAM
 1959                                        , SERVICE_UNINSTALL_CMDLINE_PARAM);
 1960     fprintf(stdout, "       %s %s %s\n", program_name
 1961                                        , SERVICE_CMDLINE_PARAM
 1962                                        , SERVICE_SHOW_CMDLINE_PARAM);
 1963 #endif
 1964 
 1965 #ifdef WIN32
 1966 # define FPUTS_WIN32(msg) fputs(msg,stdout)
 1967 # define FPUTS_UNIX(msg)  NULL
 1968 # define FPUTS_BOTH(msg)  fputs(msg,stdout)
 1969 #else
 1970 # define FPUTS_WIN32(msg)
 1971 # define FPUTS_UNIX(msg)  fputs(msg,stdout)
 1972 # define FPUTS_BOTH(msg)  fputs(msg,stdout)
 1973 #endif
 1974 
 1975     FPUTS_BOTH ("Options:\n");
 1976     FPUTS_BOTH ("        -A         Set alert mode: fast, full, console, test or none "
 1977                                   " (alert file alerts only)\n");
 1978     FPUTS_UNIX ("                   \"unsock\" enables UNIX socket logging (experimental).\n");
 1979     FPUTS_BOTH ("        -b         Log packets in tcpdump format (much faster!)\n");
 1980     FPUTS_BOTH ("        -B <mask>  Obfuscated IP addresses in alerts and packet dumps using CIDR mask\n");
 1981     FPUTS_BOTH ("        -c <rules> Use Rules File <rules>\n");
 1982     FPUTS_BOTH ("        -C         Print out payloads with character data only (no hex)\n");
 1983     FPUTS_BOTH ("        -d         Dump the Application Layer\n");
 1984     FPUTS_UNIX ("        -D         Run Snort in background (daemon) mode\n");
 1985     FPUTS_BOTH ("        -e         Display the second layer header info\n");
 1986     FPUTS_WIN32("        -E         Log alert messages to NT Eventlog. (Win32 only)\n");
 1987     FPUTS_BOTH ("        -f         Turn off fflush() calls after binary log writes\n");
 1988     FPUTS_BOTH ("        -F <bpf>   Read BPF filters from file <bpf>\n");
 1989     FPUTS_UNIX ("        -g <gname> Run snort gid as <gname> group (or gid) after initialization\n");
 1990     FPUTS_BOTH ("        -G <0xid>  Log Identifier (to uniquely id events for multiple snorts)\n");
 1991     FPUTS_BOTH ("        -h <hn>    Set home network = <hn>\n"
 1992                 "                   (for use with -l or -B, does NOT change $HOME_NET in IDS mode)\n");
 1993     FPUTS_BOTH ("        -H         Make hash tables deterministic.\n");
 1994     FPUTS_BOTH ("        -i <if>    Listen on interface <if>\n");
 1995     FPUTS_BOTH ("        -I         Add Interface name to alert output\n");
 1996     FPUTS_BOTH ("        -k <mode>  Checksum mode (all,noip,notcp,noudp,noicmp,none)\n");
 1997     FPUTS_BOTH ("        -K <mode>  Logging mode (pcap[default],ascii,none)\n");
 1998     FPUTS_BOTH ("        -l <ld>    Log to directory <ld>\n");
 1999     FPUTS_BOTH ("        -L <file>  Log to this tcpdump file\n");
 2000     FPUTS_UNIX ("        -M         Log messages to syslog (not alerts)\n");
 2001     FPUTS_UNIX ("        -m <umask> Set umask = <umask>\n");
 2002     FPUTS_BOTH ("        -n <cnt>   Exit after receiving <cnt> packets\n");
 2003     FPUTS_BOTH ("        -N         Turn off logging (alerts still work)\n");
 2004     FPUTS_BOTH ("        -O         Obfuscate the logged IP addresses\n");
 2005     FPUTS_BOTH ("        -p         Disable promiscuous mode sniffing\n");
 2006     printf     ("        -P <snap>  Set explicit snaplen of packet (default: %d)\n",
 2007                                     DAQ_GetSnapLen());
 2008     FPUTS_BOTH ("        -q         Quiet. Don't show banner and status report\n");
 2009 #ifndef WIN32
 2010     FPUTS_BOTH ("        -Q         Enable inline mode operation.\n");
 2011 #endif
 2012     FPUTS_BOTH ("        -r <tf>    Read and process tcpdump file <tf>\n");
 2013     FPUTS_BOTH ("        -R <id>    Include 'id' in snort_intf<id>.pid file name\n");
 2014     FPUTS_BOTH ("        -s         Log alert messages to syslog\n");
 2015     FPUTS_BOTH ("        -S <n=v>   Set rules file variable n equal to value v\n");
 2016     FPUTS_UNIX ("        -t <dir>   Chroots process to <dir> after initialization\n");
 2017     FPUTS_BOTH ("        -T         Test and report on the current Snort configuration\n");
 2018     FPUTS_UNIX ("        -u <uname> Run snort uid as <uname> user (or uid) after initialization\n");
 2019     FPUTS_BOTH ("        -U         Use UTC for timestamps\n");
 2020     FPUTS_BOTH ("        -v         Be verbose\n");
 2021     FPUTS_BOTH ("        -V         Show version number\n");
 2022     FPUTS_WIN32("        -W         Lists available interfaces. (Win32 only)\n");
 2023 #if defined(NON_ETHER_DECODER) && defined(DLT_IEEE802_11)
 2024     FPUTS_BOTH ("        -w         Dump 802.11 management and control frames\n");
 2025 #endif
 2026     FPUTS_BOTH ("        -X         Dump the raw packet data starting at the link layer\n");
 2027     FPUTS_BOTH ("        -x         Exit if Snort configuration problems occur\n");
 2028     FPUTS_BOTH ("        -y         Include year in timestamp in the alert and log files\n");
 2029     FPUTS_BOTH ("        -Z <file>  Set the performonitor preprocessor file path and name\n");
 2030     FPUTS_BOTH ("        -?         Show this information\n");
 2031     FPUTS_BOTH ("<Filter Options> are standard BPF options, as seen in TCPDump\n");
 2032 
 2033     FPUTS_BOTH ("Longname options and their corresponding single char version\n");
 2034     FPUTS_BOTH ("   --logid <0xid>                  Same as -G\n");
 2035     FPUTS_BOTH ("   --perfmon-file <file>           Same as -Z\n");
 2036     FPUTS_BOTH ("   --pid-path <dir>                Specify the directory for the Snort PID file\n");
 2037     FPUTS_BOTH ("   --snaplen <snap>                Same as -P\n");
 2038     FPUTS_BOTH ("   --help                          Same as -?\n");
 2039     FPUTS_BOTH ("   --version                       Same as -V\n");
 2040     FPUTS_BOTH ("   --alert-before-pass             Process alert, drop, sdrop, or reject before pass, default is pass before alert, drop,...\n");
 2041     FPUTS_BOTH ("   --treat-drop-as-alert           Converts drop, sdrop, and reject rules into alert rules during startup\n");
 2042     FPUTS_BOTH ("   --treat-drop-as-ignore          Use drop, sdrop, and reject rules to ignore session traffic when not inline.\n");
 2043     FPUTS_BOTH ("   --process-all-events            Process all queued events (drop, alert,...), default stops after 1st action group\n");
 2044     FPUTS_BOTH ("   --enable-inline-test            Enable Inline-Test Mode Operation\n");
 2045     FPUTS_BOTH ("   --dynamic-engine-lib <file>     Load a dynamic detection engine\n");
 2046     FPUTS_BOTH ("   --dynamic-engine-lib-dir <path> Load all dynamic engines from directory\n");
 2047     FPUTS_BOTH ("   --dynamic-detection-lib <file>  Load a dynamic rules library\n");
 2048     FPUTS_BOTH ("   --dynamic-detection-lib-dir <path> Load all dynamic rules libraries from directory\n");
 2049     FPUTS_BOTH ("   --dump-dynamic-rules <path>     Creates stub rule files of all loaded rules libraries\n");
 2050     FPUTS_BOTH ("   --dynamic-preprocessor-lib <file>  Load a dynamic preprocessor library\n");
 2051     FPUTS_BOTH ("   --dynamic-preprocessor-lib-dir <path> Load all dynamic preprocessor libraries from directory\n");
 2052     FPUTS_BOTH ("   --dynamic-output-lib <file>  Load a dynamic output library\n");
 2053     FPUTS_BOTH ("   --dynamic-output-lib-dir <path> Load all dynamic output libraries from directory\n");
 2054     FPUTS_UNIX ("   --create-pidfile                Create PID file, even when not in Daemon mode\n");
 2055     FPUTS_UNIX ("   --nolock-pidfile                Do not try to lock Snort PID file\n");
 2056     FPUTS_UNIX ("   --no-interface-pidfile          Do not include the interface name in Snort PID file\n");
 2057 #ifdef INLINE_FAILOPEN
 2058     FPUTS_UNIX ("   --disable-inline-init-failopen  Do not fail open and pass packets while initializing with inline mode.\n");
 2059 #endif
 2060 #ifdef TARGET_BASED
 2061     FPUTS_UNIX ("   --disable-attribute-reload-thread Do not create a thread to reload the attribute table\n");
 2062 #endif
 2063     FPUTS_BOTH ("   --pcap-single <tf>              Same as -r.\n");
 2064     FPUTS_BOTH ("   --pcap-file <file>              file that contains a list of pcaps to read - read mode is implied.\n");
 2065     FPUTS_BOTH ("   --pcap-list \"<list>\"            a space separated list of pcaps to read - read mode is implied.\n");
 2066     FPUTS_UNIX ("   --pcap-dir <dir>                a directory to recurse to look for pcaps - read mode is implied.\n");
 2067     FPUTS_UNIX ("   --pcap-filter <filter>          filter to apply when getting pcaps from file or directory.\n");
 2068     FPUTS_UNIX ("   --pcap-no-filter                reset to use no filter when getting pcaps from file or directory.\n");
 2069     FPUTS_BOTH ("   --pcap-loop <count>             this option will read the pcaps specified on command line continuously.\n"
 2070                 "                                   for <count> times.  A value of 0 will read until Snort is terminated.\n");
 2071     FPUTS_BOTH ("   --pcap-reset                    if reading multiple pcaps, reset snort to post-configuration state before reading next pcap.\n");
 2072 #if defined(SNORT_RELOAD) && !defined(WIN32)
 2073     FPUTS_BOTH ("   --pcap-reload                   if reading multiple pcaps, reload snort config between pcaps.\n");
 2074 #endif
 2075     FPUTS_BOTH ("   --pcap-show                     print a line saying what pcap is currently being read.\n");
 2076     FPUTS_BOTH ("   --exit-check <count>            Signal termination after <count> callbacks from DAQ_Acquire(), showing the time it\n"
 2077                 "                                   takes from signaling until DAQ_Stop() is called.\n");
 2078     FPUTS_BOTH ("   --conf-error-out                Same as -x\n");
 2079 #ifdef MPLS
 2080     FPUTS_BOTH ("   --enable-mpls-multicast         Allow multicast MPLS\n");
 2081     FPUTS_BOTH ("   --enable-mpls-overlapping-ip    Handle overlapping IPs within MPLS clouds\n");
 2082     FPUTS_BOTH ("   --max-mpls-labelchain-len       Specify the max MPLS label chain\n");
 2083     FPUTS_BOTH ("   --mpls-payload-type             Specify the protocol (ipv4, ipv6, ethernet) that is encapsulated by MPLS\n");
 2084 #endif
 2085     FPUTS_BOTH ("   --require-rule-sid              Require that all snort rules have SID specified.\n");
 2086     FPUTS_BOTH ("   --daq <type>                    Select packet acquisition module (default is pcap).\n");
 2087     FPUTS_BOTH ("   --daq-mode <mode>               Select the DAQ operating mode.\n");
 2088     FPUTS_BOTH ("   --daq-var <name=value>          Specify extra DAQ configuration variable.\n");
 2089     FPUTS_BOTH ("   --daq-dir <dir>                 Tell snort where to find desired DAQ.\n");
 2090     FPUTS_BOTH ("   --daq-list[=<dir>]              List packet acquisition modules available in dir.  Default is static modules only.\n");
 2091     FPUTS_BOTH ("   --dirty-pig                     Don't flush packets and release memory on shutdown.\n");
 2092     FPUTS_BOTH ("   --cs-dir <dir>                  Directory to use for control socket.\n");
 2093     FPUTS_BOTH ("   --ha-peer                       Activate live high-availability state sharing with peer.\n");
 2094     FPUTS_BOTH ("   --ha-out <file>                 Write high-availability events to this file.\n");
 2095     FPUTS_BOTH ("   --ha-in <file>                  Read high-availability events from this file on startup (warm-start).\n");
 2096     FPUTS_BOTH ("   --suppress-config-log           Suppress configuration information output.\n");
 2097 #ifdef DUMP_BUFFER
 2098     FPUTS_BOTH ("   --buffer-dump=<file>            Dump buffers for all packets\n");
 2099     FPUTS_BOTH ("   --buffer-dump-alert=<file>            Dump buffers when a rule triggers\n");
 2100 #endif
 2101 #undef FPUTS_WIN32
 2102 #undef FPUTS_UNIX
 2103 #undef FPUTS_BOTH
 2104     return 0;
 2105 }
 2106 
 2107 static void ParseCmdLineDynamicLibInfo(SnortConfig *sc, int type, char *path)
 2108 {
 2109     DynamicLibInfo *dli = NULL;
 2110     DynamicLibPath *dlp = NULL;
 2111 
 2112     if ((sc == NULL) || (path == NULL))
 2113         FatalError("%s(%d) NULL arguments.\n", __FILE__, __LINE__);
 2114 
 2115     switch (type)
 2116     {
 2117         case DYNAMIC_PREPROC_FILE:
 2118         case DYNAMIC_PREPROC_DIRECTORY:
 2119             DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Dynamic preprocessor specifier\n"););
 2120             if (sc->dyn_preprocs == NULL)
 2121             {
 2122                 sc->dyn_preprocs = (DynamicLibInfo *)SnortAlloc(sizeof(DynamicLibInfo));
 2123                 sc->dyn_preprocs->type = DYNAMIC_TYPE__PREPROCESSOR;
 2124             }
 2125             else if (sc->dyn_preprocs->count >= MAX_DYNAMIC_LIBS)
 2126             {
 2127                 FatalError("Maximum number of loaded Dynamic Preprocessor Libs "
 2128                            "(%d) exceeded.\n", MAX_DYNAMIC_LIBS);
 2129             }
 2130 
 2131             dli = sc->dyn_preprocs;
 2132             break;
 2133 
 2134         case DYNAMIC_LIBRARY_FILE:
 2135         case DYNAMIC_LIBRARY_DIRECTORY:
 2136             DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Dynamic detection specifier\n"););
 2137             if (sc->dyn_rules == NULL)
 2138             {
 2139                 sc->dyn_rules = (DynamicLibInfo *)SnortAlloc(sizeof(DynamicLibInfo));
 2140                 sc->dyn_rules->type = DYNAMIC_TYPE__DETECTION;
 2141             }
 2142             else if (sc->dyn_rules->count >= MAX_DYNAMIC_LIBS)
 2143             {
 2144                 FatalError("Maximum number of loaded Dynamic Detection Libs "
 2145                            "(%d) exceeded.\n", MAX_DYNAMIC_LIBS);
 2146             }
 2147 
 2148             dli = sc->dyn_rules;
 2149             break;
 2150 
 2151         case DYNAMIC_ENGINE_FILE:
 2152         case DYNAMIC_ENGINE_DIRECTORY:
 2153             DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Dynamic engine specifier\n"););
 2154             if (sc->dyn_engines == NULL)
 2155             {
 2156                 sc->dyn_engines = (DynamicLibInfo *)SnortAlloc(sizeof(DynamicLibInfo));
 2157                 sc->dyn_engines->type = DYNAMIC_TYPE__ENGINE;
 2158             }
 2159             else if (sc->dyn_engines->count >= MAX_DYNAMIC_LIBS)
 2160             {
 2161                 FatalError("Maximum number of loaded Dynamic Engine Libs "
 2162                            "(%d) exceeded.\n", MAX_DYNAMIC_LIBS);
 2163             }
 2164 
 2165             dli = sc->dyn_engines;
 2166             break;
 2167         case DYNAMIC_OUTPUT_FILE:
 2168             output_load_module(path);
 2169             return;
 2170             break;
 2171         case DYNAMIC_OUTPUT_DIRECTORY:
 2172             output_load(path);
 2173             return;
 2174             break;
 2175 
 2176 
 2177         default:
 2178             FatalError("%s(%d) Invalid dynamic type: %d\n", __FILE__, __LINE__, type);
 2179             break;
 2180     }
 2181 
 2182     dlp = (DynamicLibPath *)SnortAlloc(sizeof(DynamicLibPath));
 2183     switch (type)
 2184     {
 2185         case DYNAMIC_PREPROC_FILE:
 2186         case DYNAMIC_LIBRARY_FILE:
 2187         case DYNAMIC_ENGINE_FILE:
 2188         case DYNAMIC_OUTPUT_FILE:
 2189             dlp->ptype = PATH_TYPE__FILE;
 2190             break;
 2191 
 2192         case DYNAMIC_PREPROC_DIRECTORY:
 2193         case DYNAMIC_LIBRARY_DIRECTORY:
 2194         case DYNAMIC_ENGINE_DIRECTORY:
 2195         case DYNAMIC_OUTPUT_DIRECTORY:
 2196             dlp->ptype = PATH_TYPE__DIRECTORY;
 2197             break;
 2198 
 2199         default:
 2200             FatalError("%s(%d) Invalid dynamic type: %d\n", __FILE__, __LINE__, type);
 2201             break;
 2202     }
 2203 
 2204     dlp->path = SnortStrdup(path);
 2205     dli->lib_paths[dli->count] = dlp;
 2206     dli->count++;
 2207 }
 2208 
 2209 /*
 2210  * Function: ParseCmdLine(int, char **)
 2211  *
 2212  * Parses command line arguments
 2213  *
 2214  * Arguments:
 2215  *  int
 2216  *      count of arguments passed to the routine
 2217  *  char **
 2218  *      2-D character array, contains list of command line args
 2219  *
 2220  * Returns: None
 2221  *
 2222  */
 2223 
 2224 static void ParseCmdLine(int argc, char **argv)
 2225 {
 2226     int ch;
 2227     int option_index = -1;
 2228     char *endptr;   /* for SnortStrtol calls */
 2229     SnortConfig *sc;
 2230     int output_logging = 0;
 2231     int output_alerting = 0;
 2232     int syslog_configured = 0;
 2233 #ifndef WIN32
 2234     int daemon_configured = 0;
 2235 #endif
 2236 
 2237     int version_flag_parsed = 0;
 2238     int quiet_flag_parsed = 0;
 2239 
 2240     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Parsing command line...\n"););
 2241 
 2242     if (snort_cmd_line_conf != NULL)
 2243     {
 2244         FatalError("%s(%d) Trying to parse the command line again.\n",
 2245                    __FILE__, __LINE__);
 2246     }
 2247 
 2248     snort_cmd_line_conf = SnortConfNew();
 2249     snort_conf = snort_cmd_line_conf;     /* Set the global for log messages */
 2250     sc = snort_cmd_line_conf;
 2251 
 2252     optind = 1;
 2253 
 2254     /* Look for a -D and/or -M switch so we can start logging to syslog
 2255      * with "snort" tag right away */
 2256     while ((ch = getopt_long(argc, argv, valid_options, long_options, &option_index)) != -1)
 2257     {
 2258         switch (ch)
 2259         {
 2260             case 'M':
 2261                 if (syslog_configured)
 2262                     break;
 2263 
 2264                 /* If daemon or logging to syslog use "snort" as identifier and
 2265                  * start logging there now */
 2266                 openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON);
 2267 
 2268                 sc->logging_flags |= LOGGING_FLAG__SYSLOG;
 2269                 syslog_configured = 1;
 2270                 break;
 2271 
 2272 #ifndef WIN32
 2273             case 'E':
 2274                 sc->run_flags |= RUN_FLAG__DAEMON_RESTART;
 2275                 /* Fall through */
 2276             case 'D':
 2277                 if (daemon_configured)
 2278                     break;
 2279 
 2280                 /* If daemon or logging to syslog use "snort" as identifier and
 2281                  * start logging there now */
 2282                 openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON);
 2283 
 2284                 ConfigDaemon(sc, optarg);
 2285                 daemon_configured = 1;
 2286                 break;
 2287 #endif
 2288 
 2289             case 'V':
 2290                 version_flag_parsed = 1;
 2291                 break;
 2292 
 2293             case 'q':
 2294                 quiet_flag_parsed = 1;
 2295                 break;
 2296 
 2297             case '?':  /* show help and exit with 1 */
 2298                 PrintVersion(sc);
 2299                 ShowUsage(argv[0]);
 2300                 exit(1);
 2301                 break;
 2302 
 2303             default:
 2304                 break;
 2305         }
 2306     }
 2307 
 2308     if (version_flag_parsed)
 2309     {
 2310         sc->run_mode_flags |= RUN_MODE_FLAG__VERSION;
 2311     }
 2312     else if (quiet_flag_parsed)
 2313     {
 2314         ConfigQuiet(sc, NULL);
 2315         internal_log_level = INTERNAL_LOG_LEVEL__ERROR;
 2316     }
 2317 
 2318     /*
 2319     **  Set this so we know whether to return 1 on invalid input.
 2320     **  Snort uses '?' for help and getopt uses '?' for telling us there
 2321     **  was an invalid option, so we can't use that to tell invalid input.
 2322     **  Instead, we check optopt and it will tell us.
 2323     */
 2324     optopt = 0;
 2325     optind = 1;
 2326 
 2327     /* loop through each command line var and process it */
 2328     while ((ch = getopt_long(argc, argv, valid_options, long_options, &option_index)) != -1)
 2329     {
 2330         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Processing cmd line switch: %c\n", ch););
 2331 
 2332         switch (ch)
 2333         {
 2334             case DYNAMIC_ENGINE_FILE:       /* Load dynamic engine specified */
 2335             case DYNAMIC_ENGINE_DIRECTORY:  /* Load dynamic engine specified */
 2336             case DYNAMIC_PREPROC_FILE:      /* Load dynamic preprocessor lib specified */
 2337             case DYNAMIC_PREPROC_DIRECTORY:
 2338             case DYNAMIC_LIBRARY_FILE:      /* Load dynamic detection lib specified */
 2339             case DYNAMIC_LIBRARY_DIRECTORY:
 2340             case DYNAMIC_OUTPUT_FILE:      /* Load dynamic output lib specified */
 2341             case DYNAMIC_OUTPUT_DIRECTORY:
 2342                 ParseCmdLineDynamicLibInfo(sc, ch, optarg);
 2343                 break;
 2344 
 2345             case DUMP_DYNAMIC_RULES:
 2346                 ConfigDumpDynamicRulesPath(sc, optarg);
 2347                 break;
 2348 
 2349             case ALERT_BEFORE_PASS:
 2350                 ConfigAlertBeforePass(sc, NULL);
 2351                 break;
 2352 
 2353             case PROCESS_ALL_EVENTS:
 2354                 ConfigProcessAllEvents(sc, NULL);
 2355                 break;
 2356 
 2357             case TREAT_DROP_AS_ALERT:
 2358                 ConfigTreatDropAsAlert(sc, NULL);
 2359                 break;
 2360 
 2361             case TREAT_DROP_AS_IGNORE:
 2362                 ConfigTreatDropAsIgnore(sc, NULL);
 2363                 break;
 2364 
 2365             case PID_PATH:
 2366                 ConfigPidPath(sc, optarg);
 2367                 break;
 2368 
 2369             case CREATE_PID_FILE:
 2370                 ConfigCreatePidFile(sc, NULL);
 2371                 break;
 2372 
 2373             case NOLOCK_PID_FILE:
 2374                 sc->run_flags |= RUN_FLAG__NO_LOCK_PID_FILE;
 2375                 break;
 2376 
 2377             case NO_IFACE_PID_FILE:
 2378                 sc->run_flags |= RUN_FLAG__NO_IFACE_PID_FILE;
 2379                 break;
 2380 
 2381 #ifdef INLINE_FAILOPEN
 2382             case DISABLE_INLINE_FAILOPEN:
 2383                 ConfigDisableInlineFailopen(sc, NULL);
 2384                 break;
 2385 #endif
 2386             case NO_LOGGING_TIMESTAMPS:
 2387                 ConfigNoLoggingTimestamps(sc, NULL);
 2388                 break;
 2389 
 2390 #ifdef EXIT_CHECK
 2391             case ARG_EXIT_CHECK:
 2392                 {
 2393                     char* endPtr;
 2394 
 2395                     sc->exit_check = SnortStrtoul(optarg, &endPtr, 0);
 2396                     if ((errno == ERANGE) || (*endPtr != '\0'))
 2397                         FatalError("--exit-check value must be non-negative integer\n");
 2398 
 2399                     LogMessage("Exit Check: limit = "STDu64" callbacks\n", sc->exit_check);
 2400                 }
 2401 
 2402                 break;
 2403 #endif
 2404 
 2405 #ifdef TARGET_BASED
 2406             case DISABLE_ATTRIBUTE_RELOAD:
 2407                 ConfigDisableAttributeReload(sc, NULL);
 2408                 break;
 2409 #endif
 2410             case DETECTION_SEARCH_METHOD:
 2411                 if (sc->fast_pattern_config != NULL)
 2412                     FatalError("Can only configure search method once.\n");
 2413 
 2414                 sc->fast_pattern_config = FastPatternConfigNew();
 2415 
 2416                 if (fpSetDetectSearchMethod(sc->fast_pattern_config, optarg) == -1)
 2417                     FatalError("Invalid search method: %s.\n", optarg);
 2418 
 2419                 break;
 2420 
 2421             case ARG_DAQ_TYPE:
 2422                 ConfigDaqType(sc, optarg);
 2423                 break;
 2424 
 2425             case ARG_DAQ_MODE:
 2426                 ConfigDaqMode(sc, optarg);
 2427                 break;
 2428 
 2429             case ARG_DAQ_VAR:
 2430                 ConfigDaqVar(sc, optarg);
 2431                 break;
 2432 
 2433             case ARG_DAQ_DIR:
 2434                 ConfigDaqDir(sc, optarg);
 2435                 break;
 2436 
 2437             case ARG_DAQ_LIST:
 2438                 PrintDaqModules(sc, optarg);
 2439                 exit(0);
 2440                 break;
 2441 
 2442             case ARG_DIRTY_PIG:
 2443                 ConfigDirtyPig(sc, optarg);
 2444                 break;
 2445 
 2446             case 'A':  /* alert mode */
 2447                 output_alerting = 1;
 2448 
 2449                 if (strcasecmp(optarg, ALERT_MODE_OPT__NONE) == 0)
 2450                 {
 2451                     sc->no_alert = 1;
 2452                 }
 2453                 else if (strcasecmp(optarg, ALERT_MODE_OPT__PKT_CNT) == 0)
 2454                 {
 2455                     /* print packet count at start of alert */
 2456                     sc->output_flags |= OUTPUT_FLAG__ALERT_PKT_CNT;
 2457                 }
 2458                 else if (strcasecmp(optarg, ALERT_MODE_OPT__FULL) == 0)
 2459                 {
 2460                     ParseOutput(sc, NULL, "alert_full");
 2461                 }
 2462                 else if (strcasecmp(optarg, "console:" ALERT_MODE_OPT__FULL) == 0)
 2463                 {
 2464                     ParseOutput(sc, NULL, "alert_full: stdout");
 2465                 }
 2466                 else if (strcasecmp(optarg, ALERT_MODE_OPT__FAST) == 0)
 2467                 {
 2468                     ParseOutput(sc, NULL, "alert_fast");
 2469                 }
 2470                 else if (
 2471                     strcasecmp(optarg, "console:" ALERT_MODE_OPT__FAST) == 0 ||
 2472                     strcasecmp(optarg, ALERT_MODE_OPT__CONSOLE) == 0 )
 2473                 {
 2474                     ParseOutput(sc, NULL, "alert_fast: stdout");
 2475                 }
 2476                 else if ((strcasecmp(optarg, ALERT_MODE_OPT__CMG) == 0) ||
 2477                          (strcasecmp(optarg, ALERT_MODE_OPT__JH) == 0) ||
 2478                          (strcasecmp(optarg, ALERT_MODE_OPT__DJR) == 0))
 2479                 {
 2480                     ParseOutput(sc, NULL, "alert_fast: stdout packet");
 2481                     sc->no_log = 1;
 2482                     /* turn on layer2 headers */
 2483                     sc->output_flags |= OUTPUT_FLAG__SHOW_DATA_LINK;
 2484                     /* turn on data dump */
 2485                     sc->output_flags |= OUTPUT_FLAG__APP_DATA;
 2486                 }
 2487                 else if (strcasecmp(optarg, ALERT_MODE_OPT__AJK) == 0)
 2488                 {
 2489                     ParseOutput(sc, NULL, "unified2");
 2490                 }
 2491                 else if (strcasecmp(optarg, ALERT_MODE_OPT__UNIX_SOCK) == 0)
 2492                 {
 2493                     ParseOutput(sc, NULL, "alert_unixsock");
 2494                 }
 2495                 else if (strcasecmp(optarg, ALERT_MODE_OPT__TEST) == 0)
 2496                 {
 2497                     ParseOutput(sc, NULL, "alert_test");
 2498                     sc->no_log = 1;
 2499                 }
 2500                 else if (strcasecmp(optarg, "console:" ALERT_MODE_OPT__TEST) == 0)
 2501                 {
 2502                     ParseOutput(sc, NULL, "alert_test: stdout");
 2503                     sc->no_log = 1;
 2504                 }
 2505                 else
 2506                 {
 2507                     FatalError("Unknown command line alert option: %s\n", optarg);
 2508                 }
 2509 
 2510                 break;
 2511 
 2512             case 'b':  /* log packets in binary format for post-processing */
 2513                 ParseOutput(sc, NULL, "log_tcpdump");
 2514                 output_logging = 1;
 2515                 break;
 2516 
 2517             case 'B':  /* obfuscate with a substitution mask */
 2518                 ConfigObfuscationMask(sc, optarg);
 2519                 break;
 2520 
 2521             case 'c':  /* use configuration file x */
 2522                 sc->run_mode_flags |= RUN_MODE_FLAG__IDS;
 2523                 snort_conf_file = SnortStrdup(optarg);
 2524                 break;
 2525 
 2526             case 'C':  /* dump the application layer as text only */
 2527                 ConfigDumpCharsOnly(sc, NULL);
 2528                 break;
 2529 
 2530             case 'd':  /* dump the application layer data */
 2531                 ConfigDumpPayload(sc, NULL);
 2532                 break;
 2533 
 2534 #ifndef WIN32
 2535             case 'E':  /* Restarting from daemon mode */
 2536             case 'D':  /* daemon mode */
 2537                 /* These are parsed at the beginning so as to start logging
 2538                  * to syslog right away */
 2539                 break;
 2540 #endif
 2541 
 2542             case 'e':  /* show second level header info */
 2543                 ConfigDecodeDataLink(sc, NULL);
 2544                 break;
 2545 #ifdef WIN32
 2546             case 'E':  /* log alerts to Event Log */
 2547                 ParseOutput(sc, NULL, "alert_syslog");
 2548                 sc->logging_flags &= ~LOGGING_FLAG__SYSLOG_REMOTE;
 2549                 output_alerting = 1;
 2550                 break;
 2551 #endif
 2552             case 'f':
 2553                 sc->output_flags |= OUTPUT_FLAG__LINE_BUFFER;
 2554                 break;
 2555 
 2556             case 'F':   /* read BPF filter in from a file */
 2557                 ConfigBpfFile(sc, optarg);
 2558                 break;
 2559 
 2560 #ifndef WIN32
 2561             case 'g':   /* setgid */
 2562                 ConfigSetGid(sc, optarg);
 2563                 break;
 2564 #endif
 2565 
 2566             case 'G':  /* snort loG identifier */
 2567                 sc->event_log_id = SnortStrtoul(optarg, &endptr, 0);
 2568                 if ((errno == ERANGE) || (*endptr != '\0') ||
 2569                     (sc->event_log_id > UINT16_MAX))
 2570                 {
 2571                     FatalError("Snort log identifier invalid: %s.  It must "
 2572                                "be between 0 and %u.\n", optarg, UINT16_MAX);
 2573                 }
 2574 
 2575                 /* Forms upper 2 bytes.  Lower two bytes are the event id */
 2576                 sc->event_log_id <<= 16;
 2577 
 2578                 break;
 2579 
 2580             case 'h':
 2581                 /* set home network to x, this will help determine what to set
 2582                  * logging diectories to */
 2583                 ConfigReferenceNet(sc, optarg);
 2584                 break;
 2585 
 2586             case 'H':
 2587                 sc->run_flags |= RUN_FLAG__STATIC_HASH;
 2588                 break;
 2589 
 2590             case 'i':
 2591                 ConfigInterface(sc, optarg);
 2592                 break;
 2593 
 2594             case 'I':  /* add interface name to alert string */
 2595                 ConfigAlertWithInterfaceName(sc, NULL);
 2596                 break;
 2597 
 2598             case 'k':  /* set checksum mode */
 2599                 ConfigChecksumMode(sc, optarg);
 2600                 break;
 2601 
 2602             case 'K':  /* log mode */
 2603                 if (strcasecmp(optarg, LOG_MODE_OPT__NONE) == 0)
 2604                 {
 2605                     sc->no_log = 1;
 2606                 }
 2607                 else if (strcasecmp(optarg, LOG_MODE_OPT__PCAP) == 0)
 2608                 {
 2609                     ParseOutput(sc, NULL, "log_tcpdump");
 2610                 }
 2611                 else if (strcasecmp(optarg, LOG_MODE_OPT__ASCII) == 0)
 2612                 {
 2613                     ParseOutput(sc, NULL, "log_ascii");
 2614                 }
 2615                 else
 2616                 {
 2617                     FatalError("Unknown command line log option: %s\n", optarg);
 2618                 }
 2619 
 2620                 output_logging = 1;
 2621                 break;
 2622 
 2623             case 'l':  /* use log dir <X> */
 2624                 ConfigLogDir(sc, optarg);
 2625                 break;
 2626 
 2627             case 'L':  /* set BinLogFile name */
 2628                 /* implies tcpdump format logging
 2629                  * 256 is kind of arbitrary but should be more than enough */
 2630                 if (strlen(optarg) < 256)
 2631                 {
 2632                     ParseOutput(sc, NULL, "log_tcpdump");
 2633                     sc->pcap_log_file = SnortStrdup(optarg);
 2634                 }
 2635                 else
 2636                 {
 2637                     FatalError("log_tcpdump file name \"%s\" has to be less "
 2638                                "than or equal to 256 characters.\n", optarg);
 2639                 }
 2640 
 2641                 output_logging = 1;
 2642                 break;
 2643 
 2644             case 'M':
 2645                 /* This is parsed at the beginning so as to start logging
 2646                  * to syslog right away */
 2647                 break;
 2648 
 2649 #ifndef WIN32
 2650             case 'm':  /* set the umask for the output files */
 2651                 ConfigUmask(sc, optarg);
 2652                 break;
 2653 #endif
 2654 
 2655             case 'n':  /* grab x packets and exit */
 2656                 ConfigPacketCount(sc, optarg);
 2657                 break;
 2658 
 2659             case 'N':  /* no logging mode */
 2660                 ConfigNoLog(sc, NULL);
 2661                 break;
 2662 
 2663             case 'O':  /* obfuscate the logged IP addresses for privacy */
 2664                 ConfigObfuscate(sc, NULL);
 2665                 break;
 2666 
 2667             case 'p':  /* disable explicit promiscuous mode */
 2668                 ConfigNoPromiscuous(sc, NULL);
 2669                 break;
 2670 
 2671             case 'P':  /* explicitly define snaplength of packets */
 2672                 ConfigPacketSnaplen(sc, optarg);
 2673                 break;
 2674 
 2675             case 'q':  /* no stdout output mode */
 2676                 /* This is parsed at the beginning so as to start logging
 2677                  * in quiet mode right away */
 2678                 break;
 2679 
 2680 #ifndef WIN32
 2681             case 'Q':
 2682                 LogMessage("Enabling inline operation\n");
 2683                 sc->run_flags |= RUN_FLAG__INLINE;
 2684                 break;
 2685 #endif
 2686             case ENABLE_INLINE_TEST:
 2687                 LogMessage("Enable Inline Test Mode\n");
 2688                 sc->run_flags |= RUN_FLAG__INLINE_TEST;
 2689                 break;
 2690 
 2691 
 2692             case 'r':  /* read packets from a TCPdump file instead of the net */
 2693             case PCAP_SINGLE:
 2694                 PQ_Single(optarg);
 2695                 sc->run_flags |= RUN_FLAG__READ;
 2696                 break;
 2697 
 2698             case 'R': /* augment pid file name suffix */
 2699                 if ((strlen(optarg) >= MAX_PIDFILE_SUFFIX) || (strlen(optarg) <= 0) ||
 2700                     (strstr(optarg, "..") != NULL) || (strstr(optarg, "/") != NULL))
 2701                 {
 2702                         FatalError("Invalid pidfile suffix: %s.  Suffix must "
 2703                                    "less than %u characters and not have "
 2704                                    "\"..\" or \"/\" in the name.\n", optarg,
 2705                                    MAX_PIDFILE_SUFFIX);
 2706                 }
 2707 
 2708                 SnortStrncpy(sc->pidfile_suffix, optarg, sizeof(sc->pidfile_suffix));
 2709                 break;
 2710 
 2711             case 's':  /* log alerts to syslog */
 2712 #ifndef WIN32
 2713                 ParseOutput(sc, NULL, "alert_syslog");
 2714 #else
 2715                 sc->logging_flags |= LOGGING_FLAG__SYSLOG_REMOTE;
 2716 #endif
 2717                 output_alerting = 1;
 2718                 break;
 2719 
 2720             case 'S':  /* set a rules file variable */
 2721                 {
 2722                     char *equal_ptr = strchr(optarg, '=');
 2723                     VarNode *node;
 2724 
 2725                     if (equal_ptr == NULL)
 2726                     {
 2727                         FatalError("Format for command line variable definitions "
 2728                                    "is:\n -S var=value\n");
 2729                     }
 2730 
 2731                     /* Save these and parse when snort conf is parsed so
 2732                      * they can be added to the snort conf configuration */
 2733                     node = (VarNode *)SnortAlloc(sizeof(VarNode));
 2734                     node->name = SnortStrndup(optarg, equal_ptr - optarg);
 2735 
 2736                     /* Make sure it's not already in the list */
 2737                     if (cmd_line_var_list != NULL)
 2738                     {
 2739                         VarNode *tmp = cmd_line_var_list;
 2740 
 2741                         while (tmp != NULL)
 2742                         {
 2743                             if (strcasecmp(tmp->name, node->name) == 0)
 2744                             {
 2745                                 FreeVarList(cmd_line_var_list);
 2746                                 FatalError("Duplicate variable name: %s.\n",
 2747                                            tmp->name);
 2748                             }
 2749 
 2750                             tmp = tmp->next;
 2751                         }
 2752                     }
 2753 
 2754                     node->value = SnortStrdup(equal_ptr + 1);
 2755                     node->line = SnortStrdup(optarg);
 2756                     node->next = cmd_line_var_list;
 2757                     cmd_line_var_list = node;
 2758 
 2759                     /* Put line in a parser parsable form - we know the
 2760                      * equals is already there */
 2761                     equal_ptr = strchr(node->line, '=');
 2762                     *equal_ptr = ' ';
 2763                 }
 2764 
 2765                 break;
 2766 
 2767 #ifndef WIN32
 2768             case 't':  /* chroot to the user specified directory */
 2769                 ConfigChrootDir(sc, optarg);
 2770                 break;
 2771 #endif
 2772 
 2773             case 'T':  /* test mode, verify that the rules load properly */
 2774                 sc->run_mode_flags |= RUN_MODE_FLAG__TEST;
 2775                 break;
 2776 
 2777 #ifndef WIN32
 2778             case 'u':  /* setuid */
 2779                 ConfigSetUid(sc, optarg);
 2780                 break;
 2781 #endif
 2782 
 2783             case 'U':  /* use UTC */
 2784                 ConfigUtc(sc, NULL);
 2785                 break;
 2786 
 2787             case 'v':  /* be verbose */
 2788                 ConfigVerbose(sc, NULL);
 2789                 break;
 2790 
 2791             case 'V':  /* prog ver already gets printed out, so we just exit */
 2792                 break;
 2793 
 2794 #ifdef WIN32
 2795             case 'W':
 2796                 PrintVersion(sc);
 2797                 PrintAllInterfaces();
 2798                 exit(0);  /* XXX Should maybe use CleanExit here? */
 2799                 break;
 2800 #endif
 2801 
 2802 #if !defined(NO_NON_ETHER_DECODER) && defined(DLT_IEEE802_11)
 2803             case 'w':  /* show 802.11 all frames info */
 2804                 sc->output_flags |= OUTPUT_FLAG__SHOW_WIFI_MGMT;
 2805                 break;
 2806 #endif
 2807             case 'X':  /* display verbose packet bytecode dumps */
 2808                 ConfigDumpPayloadVerbose(sc, NULL);
 2809                 break;
 2810 
 2811             case 'x':
 2812                 sc->run_flags |= RUN_FLAG__CONF_ERROR_OUT;
 2813                 break;
 2814 
 2815             case 'y':  /* Add year to timestamp in alert and log files */
 2816                 ConfigShowYear(sc, NULL);
 2817                 break;
 2818 
 2819             case 'Z':  /* Set preprocessor perfmon file path/filename */
 2820                 ConfigPerfFile(sc, optarg);
 2821                 break;
 2822 
 2823             case PCAP_FILE_LIST:
 2824             case PCAP_LIST:
 2825 #ifndef WIN32
 2826             case PCAP_DIR:
 2827 #endif
 2828                 PQ_Multi((char)ch, optarg);
 2829                 sc->run_flags |= RUN_FLAG__READ;
 2830                 break;
 2831 
 2832             case PCAP_LOOP:
 2833                 {
 2834                     long int loop_count = SnortStrtol(optarg, &endptr, 0);
 2835 
 2836                     if ((errno == ERANGE) || (*endptr != '\0') ||
 2837                         (loop_count < 0) || (loop_count > 2147483647))
 2838                     {
 2839                         FatalError("Valid values for --pcap-loop are between 0 and 2147483647\n");
 2840                     }
 2841 
 2842                     if (loop_count == 0)
 2843                         pcap_loop_count = -1;
 2844                     else
 2845                         pcap_loop_count = loop_count;
 2846                 }
 2847 
 2848                 break;
 2849 
 2850             case PCAP_RESET:
 2851                 sc->run_flags |= RUN_FLAG__PCAP_RESET;
 2852                 break;
 2853 
 2854 #if defined(SNORT_RELOAD) && !defined(WIN32)
 2855             case PCAP_RELOAD:
 2856                 sc->run_flags |= RUN_FLAG__PCAP_RELOAD;
 2857                 break;
 2858 #endif
 2859 
 2860 #ifndef WIN32
 2861             case PCAP_FILTER:
 2862                 PQ_SetFilter(optarg);
 2863                 break;
 2864 
 2865             case PCAP_NO_FILTER:
 2866                 PQ_SetFilter(NULL);
 2867                 break;
 2868 #endif
 2869 
 2870             case PCAP_SHOW:
 2871                 sc->run_flags |= RUN_FLAG__PCAP_SHOW;
 2872                 break;
 2873 #ifdef MPLS
 2874             case ENABLE_MPLS_MULTICAST:
 2875                 ConfigEnableMplsMulticast(sc, NULL);
 2876                 break;
 2877 
 2878             case ENABLE_OVERLAPPING_IP:
 2879                 ConfigEnableMplsOverlappingIp(sc, NULL);
 2880                 break;
 2881 
 2882             case MAX_MPLS_LABELCHAIN_LEN:
 2883                 ConfigMaxMplsLabelChain(sc, optarg);
 2884                 break;
 2885 
 2886             case MPLS_PAYLOAD_TYPE:
 2887                 ConfigMplsPayloadType(sc, optarg);
 2888                 break;
 2889 #endif
 2890             case REQUIRE_RULE_SID:
 2891                 sc->run_flags |= RUN_FLAG__REQUIRE_RULE_SID;
 2892                 break;
 2893 
 2894             case ARG_CS_DIR:
 2895                 if ( optarg != NULL )
 2896                     sc->cs_dir = SnortStrdup(optarg);
 2897                 break;
 2898 #ifdef REG_TEST
 2899             case ARG_HA_PEER:
 2900                 sc->ha_peer = true;
 2901                 break;
 2902 
 2903             case ARG_HA_OUT:
 2904                 sc->ha_out = SnortStrdup(optarg);
 2905                 break;
 2906 
 2907             case ARG_HA_IN:
 2908                 sc->ha_in = SnortStrdup(optarg);
 2909                 break;
 2910             case ARG_HA_PDTS_IN:
 2911                 sc->ha_pdts_in = SnortStrdup(optarg);
 2912                 break;
 2913 #endif
 2914 
 2915             case SUPPRESS_CONFIG_LOG:
 2916                 sc->suppress_config_log = 1;
 2917                 break;
 2918 
 2919 #ifdef DUMP_BUFFER
 2920             case BUFFER_DUMP:
 2921                 dump_alert_only = false;
 2922                 dump_enabled = true;
 2923                 ConfigBufferDump(sc, optarg);
 2924         ParseOutput(sc, NULL, "log_buffer_dump");
 2925                 break;
 2926 
 2927             case BUFFER_DUMP_ALERT:
 2928                 dump_alert_only = true;
 2929                 dump_enabled = true;
 2930                 ConfigBufferDump(sc, optarg);
 2931                 ParseOutput(sc, NULL, "log_buffer_dump");
 2932                 break;
 2933 #endif
 2934 
 2935             case '?':  /* show help and exit with 1 */
 2936                 PrintVersion(sc);
 2937                 ShowUsage(argv[0]);
 2938                 /* XXX Should do a clean exit */
 2939                 exit(1);
 2940                 break;
 2941 
 2942             default:
 2943                 FatalError("Invalid option: %c.\n", ch);
 2944                 break;
 2945         }
 2946     }
 2947 
 2948     sc->bpf_filter = copy_argv(&argv[optind]);
 2949 
 2950     if ((sc->run_mode_flags & RUN_MODE_FLAG__TEST) &&
 2951         (sc->run_flags & RUN_FLAG__DAEMON))
 2952     {
 2953         FatalError("Cannot use test mode and daemon mode together.\n"
 2954                    "To verify configuration, run first in test "
 2955                    "mode and then restart in daemon mode.\n");
 2956     }
 2957 
 2958     if ((sc->run_flags & RUN_FLAG__INLINE) &&
 2959             (sc->run_flags & RUN_FLAG__INLINE_TEST))
 2960     {
 2961         FatalError("Cannot use inline adapter mode and inline test "
 2962                 "mode together. \n");
 2963     }
 2964 
 2965     // TBD no reason why command line args only can't be checked
 2966     // marginally useful, perhaps, but why do we go out of our way
 2967     // to make things hard on the user?
 2968     if ((sc->run_mode_flags & RUN_MODE_FLAG__TEST) &&
 2969         (snort_conf_file == NULL))
 2970     {
 2971         FatalError("Test mode must be run with a snort configuration "
 2972                    "file.  Use the '-c' option on the command line to "
 2973                    "specify a configuration file.\n");
 2974     }
 2975     if (pcap_loop_count && !(sc->run_flags & RUN_FLAG__READ))
 2976     {
 2977         FatalError("--pcap-loop can only be used in combination with pcaps "
 2978                    "on the command line.\n");
 2979     }
 2980 
 2981 #if defined(SNORT_RELOAD) && !defined(WIN32)
 2982     if ((sc->run_flags & RUN_FLAG__PCAP_RELOAD) &&
 2983         !(sc->run_flags & RUN_FLAG__READ))
 2984     {
 2985         FatalError("--pcap-reload can only be used in combination with pcaps "
 2986                    "on the command line.\n");
 2987     }
 2988 #endif
 2989 
 2990     /* Set the run mode based on what we've got from command line */
 2991 
 2992     /* Version overrides all */
 2993     if (sc->run_mode_flags & RUN_MODE_FLAG__VERSION)
 2994     {
 2995         sc->run_mode = RUN_MODE__VERSION;
 2996     }
 2997     /* Next dumping so rule stubs */
 2998     else if (sc->run_mode_flags & RUN_MODE_FLAG__RULE_DUMP)
 2999     {
 3000         sc->run_mode = RUN_MODE__RULE_DUMP;
 3001     }
 3002     /* Next if we want to test a snort conf */
 3003     else if (sc->run_mode_flags & RUN_MODE_FLAG__TEST)
 3004     {
 3005         sc->run_mode = RUN_MODE__TEST;
 3006     }
 3007     /* Now if there is a snort conf.  If a snort conf wasn't given on the
 3008      * command line, we'll look in a default place if the next ones
 3009      * don't match */
 3010     else if ((sc->run_mode_flags & RUN_MODE_FLAG__IDS) && (snort_conf_file != NULL))
 3011     {
 3012         sc->run_mode = RUN_MODE__IDS;
 3013     }
 3014     /* If logging but not alerting or log directory is set */
 3015     else if ((output_logging && !output_alerting) || (sc->log_dir != NULL))
 3016     {
 3017         sc->no_alert = 1;
 3018         sc->run_mode = RUN_MODE__PACKET_LOG;
 3019     }
 3020     /* If none of the above and not logging or alerting and verbose */
 3021     else if ((!output_logging && !output_alerting) &&
 3022              (sc->logging_flags & LOGGING_FLAG__VERBOSE))
 3023     {
 3024         sc->no_alert = 1;
 3025         sc->no_log = 1;
 3026         sc->run_mode = RUN_MODE__PACKET_DUMP;
 3027     }
 3028 
 3029 #if 1
 3030     if (!sc->run_mode)
 3031     {
 3032         sc->no_alert = 1;
 3033         sc->no_log = 1;
 3034         sc->run_mode = RUN_MODE__PACKET_DUMP;
 3035     }
 3036 #else
 3037     if (!sc->run_mode)
 3038         sc->run_mode = RUN_MODE__IDS;
 3039 
 3040     /* If mode mandates a conf and we don't have one,  check for default. */
 3041     if (((sc->run_mode == RUN_MODE__IDS) || (sc->run_mode == RUN_MODE__TEST)) &&
 3042         (snort_conf_file == NULL))
 3043     {
 3044         snort_conf_file = ConfigFileSearch();
 3045         if (snort_conf_file == NULL)
 3046         {
 3047             DisplayBanner();
 3048             ShowUsage(argv[0]);
 3049             FatalError("\n\nUh, you need to tell me to do something...");
 3050         }
 3051     }
 3052 #endif
 3053 
 3054     if ((sc->run_mode == RUN_MODE__PACKET_LOG) &&
 3055         (sc->output_configs == NULL))
 3056     {
 3057         ParseOutput(sc, NULL, "log_tcpdump");
 3058     }
 3059 
 3060     switch ( snort_conf->run_mode )
 3061     {
 3062         case RUN_MODE__IDS:
 3063             if (ScLogVerbose())
 3064                 log_func = PrintPacket;
 3065             break;
 3066 
 3067         case RUN_MODE__PACKET_LOG:
 3068             log_func = LogPacket;
 3069             break;
 3070 
 3071         case RUN_MODE__PACKET_DUMP:
 3072             log_func = PrintPacket;
 3073             break;
 3074 
 3075         default:
 3076             break;
 3077     }
 3078     SetSnortConfDir();
 3079 }
 3080 
 3081 /*
 3082  * Function: SetPktProcessor()
 3083  *
 3084  * Purpose:  Set root decoder based on datalink
 3085  */
 3086 // TBD add GetDecoder(dlt) to decode module and hide all
 3087 // protocol decoder functions.
 3088 static int SetPktProcessor(void)
 3089 {
 3090     const char* slink = NULL;
 3091     const char* extra = NULL;
 3092     int dlt = DAQ_GetBaseProtocol();
 3093 
 3094     switch ( dlt )
 3095     {
 3096         case DLT_EN10MB:
 3097             slink = "Ethernet";
 3098             grinder = DecodeEthPkt;
 3099             break;
 3100 
 3101 #ifdef DLT_LOOP
 3102         case DLT_LOOP:
 3103 #endif
 3104         case DLT_NULL:
 3105             /* loopback and stuff.. you wouldn't perform intrusion detection
 3106              * on it, but it's ok for testing. */
 3107             slink = "LoopBack";
 3108             extra = "Data link layer header parsing for this network type "
 3109                     "isn't implemented yet";
 3110             grinder = DecodeNullPkt;
 3111             break;
 3112 
 3113         case DLT_RAW:
 3114         case DLT_IPV4:
 3115             slink = "Raw IP4";
 3116             extra = "There's no second layer header available for this datalink";
 3117             grinder = DecodeRawPkt;
 3118             break;
 3119 
 3120         case DLT_IPV6:
 3121             slink = "Raw IP6";
 3122             extra = "There's no second layer header available for this datalink";
 3123             grinder = DecodeRawPkt6;
 3124             break;
 3125 
 3126 #ifdef DLT_I4L_IP
 3127         case DLT_I4L_IP:
 3128             slink = "I4L-ip";
 3129             grinder = DecodeEthPkt;
 3130             break;
 3131 #endif
 3132 
 3133 #ifndef NO_NON_ETHER_DECODER
 3134 #ifdef DLT_I4L_CISCOHDLC
 3135         case DLT_I4L_CISCOHDLC:
 3136             slink = "I4L-cisco-h";
 3137             grinder = DecodeI4LCiscoIPPkt;
 3138             break;
 3139 #endif
 3140 
 3141         case DLT_PPP:
 3142             slink = "PPP";
 3143             extra = "Second layer header parsing for this datalink "
 3144                     "isn't implemented yet";
 3145             grinder = DecodePppPkt;
 3146             break;
 3147 
 3148 #ifdef DLT_I4L_RAWIP
 3149         case DLT_I4L_RAWIP:
 3150             // you need the I4L modified version of libpcap to get this stuff
 3151             // working
 3152             slink = "I4L-rawip";
 3153             grinder = DecodeI4LRawIPPkt;
 3154             break;
 3155 #endif
 3156 
 3157 #ifdef DLT_IEEE802_11
 3158         case DLT_IEEE802_11:
 3159             slink = "IEEE 802.11";
 3160             grinder = DecodeIEEE80211Pkt;
 3161             break;
 3162 #endif
 3163 #ifdef DLT_ENC
 3164         case DLT_ENC:
 3165             slink = "Encapsulated data";
 3166             grinder = DecodeEncPkt;
 3167             break;
 3168 
 3169 #else
 3170         case 13:
 3171 #endif /* DLT_ENC */
 3172         case DLT_IEEE802:
 3173             slink = "Token Ring";
 3174             grinder = DecodeTRPkt;
 3175             break;
 3176 
 3177         case DLT_FDDI:
 3178             slink = "FDDI";
 3179             grinder = DecodeFDDIPkt;
 3180             break;
 3181 
 3182 #ifdef DLT_CHDLC
 3183         case DLT_CHDLC:
 3184             slink = "Cisco HDLC";
 3185             grinder = DecodeChdlcPkt;
 3186             break;
 3187 #endif
 3188 
 3189         case DLT_SLIP:
 3190             slink = "SLIP";
 3191             extra = "Second layer header parsing for this datalink "
 3192                     "isn't implemented yet\n";
 3193             grinder = DecodeSlipPkt;
 3194             break;
 3195 
 3196 #ifdef DLT_PPP_SERIAL
 3197         case DLT_PPP_SERIAL:         /* PPP with full HDLC header*/
 3198             slink = "PPP Serial";
 3199             extra = "Second layer header parsing for this datalink "
 3200                     " isn't implemented yet";
 3201             grinder = DecodePppSerialPkt;
 3202             break;
 3203 #endif
 3204 
 3205 #ifdef DLT_LINUX_SLL
 3206         case DLT_LINUX_SLL:
 3207             slink = "Linux SLL";
 3208             grinder = DecodeLinuxSLLPkt;
 3209             break;
 3210 #endif
 3211 
 3212 #ifdef DLT_PFLOG
 3213         case DLT_PFLOG:
 3214             slink = "OpenBSD PF log";
 3215             grinder = DecodePflog;
 3216             break;
 3217 #endif
 3218 
 3219 #ifdef DLT_OLDPFLOG
 3220         case DLT_OLDPFLOG:
 3221             slink = "Old OpenBSD PF log";
 3222             grinder = DecodeOldPflog;
 3223             break;
 3224 #endif
 3225 #endif  // NO_NON_ETHER_DECODER
 3226 
 3227         default:
 3228             /* oops, don't know how to handle this one */
 3229             FatalError("Cannot decode data link type %d\n", dlt);
 3230             break;
 3231     }
 3232 
 3233     if ( !ScReadMode() || ScPcapShow() )
 3234     {
 3235         LogMessage("Decoding %s\n", slink);
 3236     }
 3237     if (extra && ScOutputDataLink())
 3238     {
 3239         LogMessage("%s\n", extra);
 3240         snort_conf->output_flags &= ~OUTPUT_FLAG__SHOW_DATA_LINK;
 3241     }
 3242 #ifdef ACTIVE_RESPONSE
 3243     Encode_Init();
 3244 #endif
 3245     return 0;
 3246 }
 3247 
 3248 /*
 3249  *  Handle idle time checks in snort packet processing loop
 3250  */
 3251 static void SnortIdle(void)
 3252 {
 3253     /* Rollover of performance log */
 3254     if (IsSetRotatePerfFileFlag())
 3255     {
 3256         sfRotateBaseStatsFile(perfmon_config);
 3257         sfRotateFlowStatsFile(perfmon_config);
 3258         ClearRotatePerfFileFlag();
 3259     }
 3260 #ifdef OPENBSD
 3261 #ifdef SNORT_RELOAD
 3262     else if (reload_signal != reload_total)
 3263         nanosleep(&packet_sleep, NULL);
 3264 #endif
 3265 #endif
 3266 
 3267 #ifndef REG_TEST
 3268     if( session_api )
 3269         session_api->check_session_timeout(FLOW_COUNT, time(NULL));
 3270 #ifdef SNORT_RELOAD
 3271     ReloadAdjust(true, time(NULL));
 3272 #endif
 3273 #endif
 3274     ControlSocketDoWork(1);
 3275 #ifdef SIDE_CHANNEL
 3276     SideChannelDrainRX(0);
 3277 #endif
 3278     IdleProcessingExecute();
 3279 }
 3280 
 3281 void PacketLoop (void)
 3282 {
 3283     int error = 0;
 3284     int pkts_to_read = (int)snort_conf->pkt_cnt;
 3285     time_t curr_time, last_time;
 3286 
 3287     curr_time = time(NULL);
 3288     last_time = curr_time;
 3289     TimeStart();
 3290 
 3291     while ( !exit_logged )
 3292     {
 3293         error = DAQ_Acquire(pkts_to_read, PacketCallback, NULL);
 3294 
 3295 #ifdef CONTROL_SOCKET
 3296         if (packet_dump_stop)
 3297             PacketDumpClose();
 3298 #endif
 3299 
 3300 #ifdef SIDE_CHANNEL
 3301         /* If we didn't manage to lock the process lock in a DAQ acquire callback, lock it now. */
 3302         if (ScSideChannelEnabled() && !snort_process_lock_held)
 3303         {
 3304             pthread_mutex_lock(&snort_process_lock);
 3305             snort_process_lock_held = true;
 3306         }
 3307 #endif
 3308 
 3309         if ( error )
 3310         {
 3311             //Update the time tracker
 3312             curr_time = packet_time();
 3313             last_time = curr_time;
 3314 
 3315             if ( !ScReadMode() || !PQ_Next() )
 3316             {
 3317                 /* If not read-mode or no next pcap, we're done */
 3318                 break;
 3319             }
 3320 #ifdef REG_TEST
 3321             else
 3322                 regTestCheckIPIncrement();
 3323 #endif
 3324         }
 3325         /* Check for any pending signals when no packets are read*/
 3326         else
 3327         {
 3328             // TBD SnortIdle() only checks for perf file rotation
 3329             // and that can only be done after calling SignalCheck()
 3330             // so either move SnortIdle() to SignalCheck() or directly
 3331             // set the flag in the signal handler (and then clear it
 3332             // in SnortIdle()).
 3333 
 3334             if ( !ScReadMode() )
 3335             {
 3336                 time_t new_time = time(NULL);
 3337                 curr_time += new_time - last_time;
 3338                 last_time = new_time;
 3339 
 3340                 // Check if its time to dump perf data
 3341                 sfPerformanceStatsOOB(perfmon_config, curr_time);
 3342             }
 3343 
 3344             // check for signals
 3345             if ( SignalCheck() )
 3346             {
 3347 #ifndef SNORT_RELOAD
 3348                 // Got SIGNAL_SNORT_RELOAD
 3349                 Restart();
 3350 #endif
 3351             }
 3352             CheckForReload();
 3353         }
 3354         if ( pkts_to_read > 0 )
 3355         {
 3356             if ( snort_conf->pkt_cnt <= pc.total_from_daq )
 3357                 break;
 3358             else
 3359                 pkts_to_read = (int)(snort_conf->pkt_cnt - pc.total_from_daq);
 3360         }
 3361         // idle time processing..quick things to check or do ...
 3362         // TBD fix this per above ... and if it stays here, should
 3363         // prolly change the name if acquire breaks due to a signal
 3364         // (since in that case we aren't idle here)
 3365         SnortIdle();
 3366 
 3367 #ifdef SIDE_CHANNEL
 3368         /* Unlock the Snort process lock once we've hit the DAQ acquire timeout. */
 3369         if (snort_process_lock_held)
 3370         {
 3371             snort_process_lock_held = false;
 3372             pthread_mutex_unlock(&snort_process_lock);
 3373         }
 3374 #endif
 3375     }
 3376 #ifdef CONTROL_SOCKET
 3377     PacketDumpClose();
 3378 #endif
 3379 
 3380 #ifdef SIDE_CHANNEL
 3381     /* Error conditions can lead to exiting the packet loop prior to unlocking the process lock.  */
 3382     if (snort_process_lock_held)
 3383     {
 3384         snort_process_lock_held = false;
 3385         pthread_mutex_unlock(&snort_process_lock);
 3386     }
 3387 #endif
 3388 
 3389     if ( !exit_logged && error )
 3390     {
 3391         if ( error == DAQ_READFILE_EOF )
 3392             error = 0;
 3393         else if ( error > 0 )
 3394         {
 3395             SnortShutdownThreads(error);
 3396             DAQ_Abort();
 3397             exit(1);
 3398         }
 3399         CleanExit(error);
 3400     }
 3401     done_processing = 1;
 3402 }
 3403 
 3404 /* Resets Snort to a post-configuration state */
 3405 static void SnortReset(void)
 3406 {
 3407     PreprocSignalFuncNode *idxPreprocReset;
 3408     PreprocSignalFuncNode *idxPreprocResetStats;
 3409 
 3410     /* reset preprocessors */
 3411     idxPreprocReset = preproc_reset_funcs;
 3412     while (idxPreprocReset != NULL)
 3413     {
 3414         idxPreprocReset->func(-1, idxPreprocReset->arg);
 3415         idxPreprocReset = idxPreprocReset->next;
 3416     }
 3417 
 3418     SnortEventqReset();
 3419     Replace_ResetQueue();
 3420 #ifdef ACTIVE_RESPONSE
 3421     Active_ResetQueue();
 3422 #endif
 3423 
 3424     sfthreshold_reset_active();
 3425     RateFilter_ResetActive();
 3426     TagCacheReset();
 3427 
 3428 #ifdef PERF_PROFILING
 3429     ShowPreprocProfiles();
 3430     ShowRuleProfiles();
 3431 #endif
 3432 
 3433     DropStats(0);
 3434 
 3435     /* zero out packet count */
 3436     memset(&pc, 0, sizeof(pc));
 3437 
 3438 #ifdef PERF_PROFILING
 3439     ResetRuleProfiling();
 3440     ResetPreprocProfiling();
 3441 #endif
 3442 
 3443     /* reset preprocessor stats */
 3444     idxPreprocResetStats = preproc_reset_stats_funcs;
 3445     while (idxPreprocResetStats != NULL)
 3446     {
 3447         idxPreprocResetStats->func(-1, idxPreprocResetStats->arg);
 3448         idxPreprocResetStats = idxPreprocResetStats->next;
 3449     }
 3450 }
 3451 
 3452 
 3453 #if 0
 3454 /* locate one of the possible default config files */
 3455 /* allocates memory to hold filename */
 3456 static char *ConfigFileSearch(void)
 3457 {
 3458     struct stat st;
 3459     int i;
 3460     char *conf_files[]={"/etc/snort.conf", "./snort.conf", NULL};
 3461     char *fname = NULL;
 3462     char *rval = NULL;
 3463 
 3464     i = 0;
 3465 
 3466     /* search the default set of config files */
 3467     while(conf_files[i])
 3468     {
 3469         fname = conf_files[i];
 3470 
 3471         if(stat(fname, &st) != -1)
 3472         {
 3473             rval = SnortStrdup(fname);
 3474             break;
 3475         }
 3476         i++;
 3477     }
 3478 
 3479     /* search for .snortrc in the HOMEDIR */
 3480     if(!rval)
 3481     {
 3482         char *home_dir = NULL;
 3483 
 3484         if((home_dir = getenv("HOME")) != NULL)
 3485         {
 3486             char *snortrc = "/.snortrc";
 3487             int path_len;
 3488 
 3489             path_len = strlen(home_dir) + strlen(snortrc) + 1;
 3490 
 3491             /* create the full path */
 3492             fname = (char *)SnortAlloc(path_len);
 3493 
 3494             SnortSnprintf(fname, path_len, "%s%s", home_dir, snortrc);
 3495 
 3496             if(stat(fname, &st) != -1)
 3497                 rval = fname;
 3498             else
 3499                 free(fname);
 3500         }
 3501     }
 3502 
 3503     return rval;
 3504 }
 3505 #endif
 3506 
 3507 /* Signal Handlers ************************************************************/
 3508 static void SigExitHandler(int signal)
 3509 {
 3510 
 3511     if (exit_signal != 0)
 3512         return;
 3513 
 3514     /* If snort received signal to exit before its initialization,
 3515      * we can just close DAQ interfaces and exit quickly, otherwise 
 3516      * lets follow normal path. Snort will not print stats when
 3517      * it is asked to exit during initialization.
 3518      */
 3519     if (snort_initializing)
 3520     {
 3521         DAQ_Abort();
 3522         exit(0);
 3523     } 
 3524 
 3525     exit_signal = signal;
 3526 }
 3527 
 3528 static void SigDumpStatsHandler(int signal)
 3529 {
 3530     dump_stats_signal = true;
 3531 }
 3532 
 3533 static void SigRotateStatsHandler(int signal)
 3534 {
 3535     rotate_stats_signal = true;
 3536 }
 3537 
 3538 static void SigReloadHandler(int signal)
 3539 {
 3540 #if defined(SNORT_RELOAD) && !defined(WIN32)
 3541     reload_signal++;
 3542 #else
 3543     reload_signal = true;
 3544 #endif
 3545 }
 3546 
 3547 #ifdef CONTROL_SOCKET
 3548 static void SigPipeHandler(int signal)
 3549 {
 3550 }
 3551 #endif
 3552 
 3553 #ifdef TARGET_BASED
 3554 void SigNoAttributeTableHandler(int signal)
 3555 {
 3556    no_attr_table_signal = true;
 3557 }
 3558 #endif
 3559 
 3560 static void SigOopsHandler(int signal)
 3561 {
 3562     if ( s_packet.pkth )
 3563     {
 3564         s_pkth = *s_packet.pkth;
 3565 
 3566         if ( s_packet.pkt )
 3567             memcpy(s_data, s_packet.pkt, 0xFFFF & s_packet.pkth->caplen);
 3568     }
 3569     SnortAddSignal(signal, SIG_DFL, 0);
 3570 
 3571     raise(signal);
 3572 }
 3573 
 3574 static void PrintStatistics (void)
 3575 {
 3576     if ( ScTestMode() || ScVersionMode() || ScRuleDumpMode() )
 3577         return;
 3578 
 3579     fpShowEventStats(snort_conf);
 3580 
 3581 #ifdef PERF_PROFILING
 3582     {
 3583         int saved_internal_log_level = internal_log_level;
 3584         internal_log_level = INTERNAL_LOG_LEVEL__MESSAGE;
 3585 
 3586         ShowPreprocProfiles();
 3587         ShowRuleProfiles();
 3588 
 3589         internal_log_level = saved_internal_log_level;
 3590     }
 3591 #endif
 3592 
 3593     DropStats(2);
 3594     print_thresholding(snort_conf->threshold_config, 1);
 3595 }
 3596 
 3597 /****************************************************************************
 3598  *
 3599  * Function: CleanExit()
 3600  *
 3601  * Purpose:  Clean up misc file handles and such and exit
 3602  *
 3603  * Arguments: exit value;
 3604  *
 3605  * Returns: void function
 3606  *
 3607  ****************************************************************************/
 3608 void CleanExit(int exit_val)
 3609 {
 3610     SnortConfig tmp;
 3611 
 3612 #ifdef TARGET_BASED
 3613 #ifdef DEBUG
 3614 #if 0
 3615     SFLAT_dump();
 3616 #endif
 3617 #endif
 3618 #endif
 3619 
 3620     /* Have to trick LogMessage to log correctly after snort_conf
 3621      * is freed */
 3622     memset(&tmp, 0, sizeof(tmp));
 3623 
 3624     if (snort_conf != NULL)
 3625     {
 3626         tmp.internal_log_level = snort_conf->internal_log_level;
 3627         tmp.run_mode = snort_conf->run_mode;
 3628         tmp.run_flags |= (snort_conf->run_flags & RUN_FLAG__DAEMON);
 3629 
 3630         tmp.logging_flags |=
 3631             (snort_conf->logging_flags & LOGGING_FLAG__SYSLOG);
 3632     }
 3633 
 3634     SnortCleanup(exit_val);
 3635     snort_conf = &tmp;
 3636 
 3637     if (!ScVersionMode())
 3638     {
 3639         LogMessage("Snort exiting\n");
 3640     }
 3641 #ifndef WIN32
 3642     closelog();
 3643 #endif
 3644     if ( !done_processing )
 3645         exit(exit_val);
 3646 }
 3647 
 3648 void SnortShutdownThreads(int exit_val)
 3649 {
 3650     LogMessage("Snort is shutting down other threads, exit_val %d", exit_val);
 3651 
 3652     if (!InMainThread())
 3653     {
 3654         LogMessage("Snort shutdown thread is not called at main thread, so exiting..!");
 3655         return;
 3656     }
 3657 
 3658     if (already_exiting != 0)
 3659     {
 3660         LogMessage("Exiting shutdown Threads, exit processing by another thread");
 3661         return;
 3662     }
 3663 
 3664     if (pthread_mutex_trylock(&cleanup_mutex) != 0)
 3665     {
 3666         LogMessage("Exiting shutdown Threads, as someother thread is cleaning!");
 3667         return;
 3668     }
 3669 
 3670     already_exiting = 1;
 3671     snort_exiting = 1;
 3672     snort_initializing = false;
 3673 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
 3674     if (inline_failopen_thread_running)
 3675     {
 3676         pthread_kill(inline_failopen_thread_id, SIGKILL);
 3677     }
 3678 #endif
 3679 
 3680     if (DAQ_WasStarted())
 3681     {
 3682 #ifdef EXIT_CHECK
 3683         if (snort_conf->exit_check)
 3684             ExitCheckEnd();
 3685 #endif
 3686     }
 3687 
 3688     ControlSocketCleanUp();
 3689 #ifdef SIDE_CHANNEL
 3690     if (ScSideChannelEnabled())
 3691     {
 3692         SideChannelStopTXThread();
 3693         SideChannelCleanUp();
 3694     }
 3695 #endif
 3696 
 3697 #if defined(SNORT_RELOAD) && !defined(WIN32)
 3698     if (snort_reload_thread_created)
 3699     {
 3700         pthread_join(snort_reload_thread_id, NULL);
 3701     }
 3702 #endif
 3703 
 3704 #if defined(TARGET_BASED) && !defined(WIN32)
 3705     if (attribute_reload_thread_running)
 3706     {
 3707         attribute_reload_thread_stop = 1;
 3708         pthread_kill(attribute_reload_thread_id, SIGVTALRM);
 3709         while (attribute_reload_thread_running)
 3710             nanosleep(&thread_sleep, NULL);
 3711         pthread_join(attribute_reload_thread_id, NULL);
 3712     }
 3713 #endif
 3714 
 3715     PrintStatistics();
 3716     pthread_mutex_unlock(&cleanup_mutex);
 3717     LogMessage("Shutting down the threads -- Done");
 3718 }
 3719 
 3720 static void SnortCleanup(int exit_val)
 3721 {
 3722     PreprocSignalFuncNode *idxPreproc = NULL;
 3723     PluginSignalFuncNode *idxPlugin = NULL;
 3724 
 3725     /* This function can be called more than once.  For example,
 3726      * once from the SIGINT signal handler, and once recursively
 3727      * as a result of calling pcap_close() below.  We only need
 3728      * to perform the cleanup once.
 3729      */
 3730     if (pthread_mutex_trylock(&cleanup_mutex) == 0)
 3731     {
 3732         /*
 3733          * We have the lock now, make sure no one else called this
 3734          * function before this thread did.
 3735          */
 3736         if (already_exiting != 0 )
 3737         {
 3738             pthread_mutex_unlock(&cleanup_mutex);
 3739             return;
 3740         }
 3741     }
 3742     else
 3743     {
 3744         /*
 3745          * Someother thread is cleaning up. Return.
 3746          */
 3747         return;
 3748     }
 3749 
 3750     already_exiting = 1;
 3751     snort_exiting = 1;
 3752     snort_initializing = false;  /* just in case we cut out early */
 3753 
 3754     Active_Suspend();  // rules that fire now can't actually block
 3755 
 3756 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
 3757     if (inline_failopen_thread_running)
 3758         pthread_kill(inline_failopen_thread_id, SIGKILL);
 3759 #endif
 3760 
 3761     if ( DAQ_WasStarted() )
 3762     {
 3763 #ifdef EXIT_CHECK
 3764         if (snort_conf->exit_check)
 3765             ExitCheckEnd();
 3766 #endif
 3767         DAQ_Stop();
 3768     }
 3769 
 3770     ControlSocketCleanUp();
 3771 #ifdef SIDE_CHANNEL
 3772     SideChannelStopTXThread();
 3773     SideChannelCleanUp();
 3774 #endif
 3775     IdleProcessingCleanUp();
 3776 
 3777     if ( snort_conf->dirty_pig )
 3778     {
 3779         DAQ_Delete();
 3780         DAQ_Term();
 3781         ScRestoreInternalLogLevel();
 3782         PrintStatistics();
 3783         pthread_mutex_unlock(&cleanup_mutex);
 3784         return;
 3785     }
 3786 #if defined(SNORT_RELOAD) && !defined(WIN32)
 3787     /* Setting snort_exiting will cause the thread to break out
 3788      * of it's loop and exit */
 3789     if (snort_reload_thread_created)
 3790         pthread_join(snort_reload_thread_id, NULL);
 3791 #endif
 3792 
 3793 #if defined(TARGET_BASED) && !defined(WIN32)
 3794     if (attribute_reload_thread_running)
 3795     {
 3796         /* Set the flag to stop the attribute reload thread and
 3797          * send VTALRM signal to pull it out of the idle sleep.
 3798          * Thread exits normally on next iteration through its
 3799          * loop.
 3800          *
 3801          * If its doing other processing, that continues post
 3802          * interrupt and thread exits normally.
 3803          */
 3804         attribute_reload_thread_stop = 1;
 3805         pthread_kill(attribute_reload_thread_id, SIGVTALRM);
 3806         while (attribute_reload_thread_running)
 3807             nanosleep(&thread_sleep, NULL);
 3808         pthread_join(attribute_reload_thread_id, NULL);
 3809     }
 3810 #endif
 3811  
 3812     /* Do some post processing on any incomplete Preprocessor Data */
 3813     idxPreproc = preproc_shutdown_funcs;
 3814     while (idxPreproc)
 3815     {
 3816         idxPreproc->func(SIGQUIT, idxPreproc->arg);
 3817         idxPreproc = idxPreproc->next;
 3818     }
 3819 
 3820     /* Do some post processing on any incomplete Plugin Data */
 3821     idxPlugin = plugin_shutdown_funcs;
 3822     while(idxPlugin)
 3823     {
 3824         idxPlugin->func(SIGQUIT, idxPlugin->arg);
 3825         idxPlugin = idxPlugin->next;
 3826     }
 3827 
 3828     if (!ScTestMode() && !ScVersionMode() && !ScRuleDumpMode() )
 3829     {
 3830         if ( !exit_val )
 3831             TimeStop();
 3832     }
 3833 
 3834     /* Exit preprocessors */
 3835     idxPreproc = preproc_clean_exit_funcs;
 3836     while(idxPreproc)
 3837     {
 3838         idxPreproc->func(SIGQUIT, idxPreproc->arg);
 3839         idxPreproc = idxPreproc->next;
 3840     }
 3841 
 3842     /* Do some post processing on any incomplete Plugin Data */
 3843     idxPlugin = plugin_clean_exit_funcs;
 3844     while(idxPlugin)
 3845     {
 3846         idxPlugin->func(SIGQUIT, idxPlugin->arg);
 3847         idxPlugin = idxPlugin->next;
 3848     }
 3849 
 3850     if (decoderActionQ != NULL)
 3851     {
 3852         sfActionQueueDestroy (decoderActionQ);
 3853         mempool_destroy (&decoderAlertMemPool);
 3854         decoderActionQ = NULL;
 3855         memset(&decoderAlertMemPool, 0, sizeof(decoderAlertMemPool));
 3856     }
 3857 
 3858     MemoryStatsFree();
 3859     DAQ_Delete();
 3860     DAQ_Term();
 3861     ScRestoreInternalLogLevel(); // Do we need this?
 3862     PrintStatistics();
 3863 
 3864 #ifdef ACTIVE_RESPONSE
 3865     Active_Term();
 3866     Encode_Term();
 3867 #endif
 3868 
 3869 
 3870     CleanupProtoNames();
 3871 
 3872 #ifdef TARGET_BASED
 3873     SFAT_Cleanup();
 3874     FreeProtoocolReferenceTable();
 3875 #endif
 3876 
 3877     PQ_CleanUp();
 3878 
 3879     ClosePidFile();
 3880 
 3881     /* remove pid file */
 3882     if (SnortStrnlen(snort_conf->pid_filename, sizeof(snort_conf->pid_filename)) > 0)
 3883     {
 3884         int ret;
 3885 
 3886         ret = unlink(snort_conf->pid_filename);
 3887 
 3888         if (ret != 0)
 3889         {
 3890             ErrorMessage("Could not remove pid file %s: %s\n",
 3891                          snort_conf->pid_filename, strerror(errno));
 3892         }
 3893     }
 3894 
 3895 #ifdef INTEL_SOFT_CPM
 3896     //IntelPmPrintBufferStats();
 3897 #endif
 3898 
 3899     /* free allocated memory */
 3900     if (snort_conf == snort_cmd_line_conf)
 3901     {
 3902         SnortConfFree(snort_cmd_line_conf);
 3903         snort_cmd_line_conf = NULL;
 3904         snort_conf = NULL;
 3905     }
 3906     else
 3907     {
 3908         SnortConfFree(snort_cmd_line_conf);
 3909         snort_cmd_line_conf = NULL;
 3910 #ifdef SNORT_RELOAD
 3911         if (!reloadInProgress) 
 3912         {
 3913             SnortConfFree(snort_conf);
 3914             snort_conf = NULL;
 3915         }
 3916 #else
 3917         SnortConfFree(snort_conf);
 3918         snort_conf = NULL;
 3919 #endif
 3920         
 3921     }
 3922 
 3923 #ifdef SNORT_RELOAD
 3924     if (snort_conf_new != NULL)
 3925     {
 3926         /* If main thread is exiting, it won't swap in the new configuration,
 3927          * so free it here, really just to quiet valgrind.  Note this needs to
 3928          * be done here since some preprocessors, will potentially need access
 3929          * to the data here since stream5 flushes out its cache and potentially
 3930          * sends reassembled packets back through Preprocess */
 3931         SnortConfFree(snort_conf_new);
 3932         snort_conf_new = NULL;
 3933     }
 3934 #endif
 3935 
 3936     EventTrace_Term();
 3937 
 3938     detection_filter_cleanup();
 3939     sfthreshold_free();
 3940     RateFilter_Cleanup();
 3941     asn1_free_mem();
 3942 
 3943 #ifdef SNORT_RELOAD
 3944     if (!reloadInProgress) 
 3945     {
 3946 #endif
 3947         FreeOutputConfigFuncs();
 3948         FreePreprocConfigFuncs();
 3949 
 3950         FreeRuleOptConfigFuncs(rule_opt_config_funcs);
 3951         rule_opt_config_funcs = NULL;
 3952 
 3953         FreeRuleOptOverrideInitFuncs(rule_opt_override_init_funcs);
 3954         rule_opt_override_init_funcs = NULL;
 3955 
 3956         FreeRuleOptByteOrderFuncs(rule_opt_byte_order_funcs);
 3957         rule_opt_byte_order_funcs = NULL;
 3958 
 3959         FreeRuleOptParseCleanupList(rule_opt_parse_cleanup_list);
 3960         rule_opt_parse_cleanup_list = NULL;
 3961 #ifdef SNORT_RELOAD
 3962     }
 3963 #endif
 3964 
 3965     FreeOutputList(AlertList);
 3966     AlertList = NULL;
 3967 
 3968     FreeOutputList(LogList);
 3969     LogList = NULL;
 3970 
 3971     /* Global lists */
 3972     FreePreprocStatsFuncs(preproc_stats_funcs);
 3973     preproc_stats_funcs = NULL;
 3974 
 3975     FreePreprocSigFuncs(preproc_shutdown_funcs);
 3976     preproc_shutdown_funcs = NULL;
 3977 
 3978     FreePreprocSigFuncs(preproc_clean_exit_funcs);
 3979     preproc_clean_exit_funcs = NULL;
 3980 
 3981     FreePreprocSigFuncs(preproc_reset_funcs);
 3982     preproc_reset_funcs = NULL;
 3983 
 3984     FreePreprocSigFuncs(preproc_reset_stats_funcs);
 3985     preproc_reset_stats_funcs = NULL;
 3986 
 3987     FreePluginSigFuncs(plugin_shutdown_funcs);
 3988     plugin_shutdown_funcs = NULL;
 3989 
 3990     FreePluginSigFuncs(plugin_clean_exit_funcs);
 3991     plugin_clean_exit_funcs = NULL;
 3992 
 3993 #ifdef SNORT_RELOAD
 3994     FreePluginPostConfigFuncs(plugin_reload_funcs);
 3995     plugin_reload_funcs = NULL;
 3996 #endif
 3997 
 3998     FreePeriodicFuncs(periodic_check_funcs);
 3999     periodic_check_funcs = NULL;
 4000 
 4001     ParserCleanup();
 4002 
 4003     CloseDynamicPreprocessorLibs();
 4004     CloseDynamicEngineLibs();
 4005 #ifdef SIDE_CHANNEL
 4006     CloseDynamicSideChannelLibs();
 4007 #endif
 4008     output_unload();
 4009 
 4010     CleanupTag();
 4011     ClearDumpBuf();
 4012 
 4013 #ifdef PERF_PROFILING
 4014     CleanupPreprocStatsNodeList();
 4015 #endif
 4016 
 4017     if (netmasks != NULL)
 4018     {
 4019         free(netmasks);
 4020         netmasks = NULL;
 4021     }
 4022 
 4023     if (protocol_names != NULL)
 4024     {
 4025         int i;
 4026 
 4027         for (i = 0; i < NUM_IP_PROTOS; i++)
 4028         {
 4029             if (protocol_names[i] != NULL)
 4030                 free(protocol_names[i]);
 4031         }
 4032 
 4033         free(protocol_names);
 4034         protocol_names = NULL;
 4035     }
 4036 
 4037 #ifdef INTEL_SOFT_CPM
 4038     IntelPmStopInstance();
 4039 #endif
 4040 
 4041     SynToMulticastDstIpDestroy();
 4042     MulticastReservedIpDestroy();
 4043 
 4044     FreeVarList(cmd_line_var_list);
 4045 
 4046     if (snort_conf_file != NULL)
 4047         free(snort_conf_file);
 4048 
 4049     if (snort_conf_dir != NULL)
 4050         free(snort_conf_dir);
 4051 
 4052     if (s_packet.ip6_extensions != NULL)
 4053     free(s_packet.ip6_extensions);
 4054 
 4055     close_fileAPI();
 4056     pthread_mutex_unlock(&cleanup_mutex);
 4057 }
 4058 
 4059 void Restart(void)
 4060 {
 4061     int daemon_mode = ScDaemonMode();
 4062 
 4063 #ifndef WIN32
 4064     if ((!ScReadMode() && (getuid() != 0)) ||
 4065         (snort_conf->chroot_dir != NULL))
 4066     {
 4067         LogMessage("Reload via Signal Reload does not work if you aren't root "
 4068                    "or are chroot'ed.\n");
 4069 # ifdef SNORT_RELOAD
 4070         /* We are restarting because of a configuration verification problem */
 4071         CleanExit(1);
 4072 # else
 4073         return;
 4074 # endif
 4075     }
 4076 #endif  /* WIN32 */
 4077 
 4078     LogMessage("\n");
 4079     LogMessage("***** Restarting Snort *****\n");
 4080     LogMessage("\n");
 4081     SnortCleanup(0);
 4082 
 4083     if (daemon_mode)
 4084     {
 4085         int ch;
 4086         int option_index = -1;
 4087 
 4088         optind = 1;
 4089 
 4090         while ((ch = getopt_long(snort_argc, snort_argv, valid_options, long_options, &option_index)) != -1)
 4091         {
 4092             switch (ch)
 4093             {
 4094                 case 'D':
 4095                     {
 4096                         int i = optind-1, j;
 4097                         int index = strlen(snort_argv[i]) - 1;
 4098 
 4099                         /* 'D' isn't the last option in the opt string so
 4100                          * optind hasn't moved past this option string yet */
 4101                         if ((snort_argv[i][0] != '-')
 4102                                 || ((index > 0) && (snort_argv[i][1] == '-'))
 4103                                 || (snort_argv[i][index] != 'D'))
 4104                         {
 4105                             i++;
 4106                         }
 4107 
 4108                         /* Replace -D with -E to indicate we've already daemonized */
 4109                         for (j = 0; j < (int)strlen(snort_argv[i]); j++)
 4110                         {
 4111                             if (snort_argv[i][j] == 'D')
 4112                             {
 4113                                 snort_argv[i][j] = 'E';
 4114                                 break;
 4115                             }
 4116                         }
 4117                     }
 4118 
 4119                     break;
 4120 
 4121                 default:
 4122                     break;
 4123             }
 4124         }
 4125     }
 4126 
 4127 #ifdef PARANOID
 4128     execv(snort_argv[0], snort_argv);
 4129 #else
 4130     execvp(snort_argv[0], snort_argv);
 4131 #endif
 4132 
 4133     /* only get here if we failed to restart */
 4134     LogMessage("Restarting %s failed: %s\n", snort_argv[0], strerror(errno));
 4135 
 4136 #ifndef WIN32
 4137     closelog();
 4138 #endif
 4139 
 4140     exit(-1);
 4141 }
 4142 
 4143 void print_packet_count(void)
 4144 {
 4145     LogMessage("[" STDu64 "]", pc.total_from_daq);
 4146 }
 4147 
 4148 /*
 4149  *  Check for signal activity
 4150  */
 4151 int SignalCheck(void)
 4152 {
 4153     switch (exit_signal)
 4154     {
 4155         case SIGTERM:
 4156             if (!exit_logged)
 4157             {
 4158                 ErrorMessage("*** Caught Term-Signal\n");
 4159                 exit_logged = 1;
 4160                 if ( DAQ_BreakLoop(DAQ_SUCCESS) )
 4161                     return 0;
 4162             }
 4163             CleanExit(0);
 4164             break;
 4165 
 4166         case SIGINT:
 4167             if (!exit_logged)
 4168             {
 4169                 ErrorMessage("*** Caught Int-Signal\n");
 4170                 exit_logged = 1;
 4171                 if ( DAQ_BreakLoop(DAQ_SUCCESS) )
 4172                     return 0;
 4173             }
 4174             CleanExit(0);
 4175             break;
 4176 
 4177         case SIGQUIT:
 4178             if (!exit_logged)
 4179             {
 4180                 ErrorMessage("*** Caught Quit-Signal\n");
 4181                 exit_logged = 1;
 4182                 if ( DAQ_BreakLoop(DAQ_SUCCESS) )
 4183                     return 0;
 4184             }
 4185             CleanExit(0);
 4186             break;
 4187 
 4188         default:
 4189             break;
 4190     }
 4191 
 4192     if (dump_stats_signal)
 4193     {
 4194         ErrorMessage("*** Caught Dump Stats-Signal\n");
 4195         DropStats(0);
 4196     }
 4197 
 4198     dump_stats_signal = false;
 4199 
 4200     if (rotate_stats_signal)
 4201     {
 4202         ErrorMessage("*** Caught Signal: 'Rotate Perfmonitor Stats'\n");
 4203 
 4204         /* Make sure the preprocessor is enabled - it can only be enabled
 4205          * in default policy */
 4206         if (!ScIsPreprocEnabled(PP_PERFMONITOR, 0))
 4207         {
 4208             ErrorMessage("!!! Cannot rotate stats - Perfmonitor is not configured !!!\n");
 4209         }
 4210         else
 4211         {
 4212             SetRotatePerfFileFlag();
 4213         }
 4214     }
 4215 
 4216     rotate_stats_signal = false;
 4217 
 4218 #ifdef TARGET_BASED
 4219     if (no_attr_table_signal)
 4220         ErrorMessage("!!! Cannot reload attribute table - Attribute table is not configured !!!\n");
 4221     no_attr_table_signal = false;
 4222 #endif
 4223 
 4224 #ifndef SNORT_RELOAD
 4225     if (reload_signal )
 4226     {
 4227         ErrorMessage("*** Caught Reload-Signal\n");
 4228         reload_signal = false;
 4229         return 1;
 4230     }
 4231     reload_signal = false;
 4232 #endif
 4233 
 4234     return 0;
 4235 }
 4236 
 4237 static void InitGlobals(void)
 4238 {
 4239     memset(&pc, 0, sizeof(pc));
 4240 
 4241     InitNetmasks();
 4242     InitProtoNames();
 4243 #ifdef SIDE_CHANNEL
 4244     pthread_mutex_init(&snort_process_lock, NULL);
 4245 #endif
 4246     pthread_mutex_init(&cleanup_mutex, NULL);
 4247     pthread_mutex_init(&dynamic_rules_lock, NULL);
 4248 }
 4249 
 4250 /* Alot of this initialization can be skipped if not running in IDS mode
 4251  * but the goal is to minimize config checks at run time when running in
 4252  * IDS mode so we keep things simple and enforce that the only difference
 4253  * among run_modes is how we handle packets via the log_func. */
 4254 SnortConfig * SnortConfNew(void)
 4255 {
 4256     SnortConfig *sc = (SnortConfig *)SnortAlloc(sizeof(SnortConfig));
 4257 
 4258     sc->pkt_cnt = 0;
 4259 #ifdef REG_TEST
 4260     sc->pkt_skip = 0;
 4261 #endif
 4262     sc->pkt_snaplen = -1;
 4263     /*user_id and group_id should be initialized to -1 by default, because
 4264      * chown() use this later, -1 means no change to user_id/group_id*/
 4265     sc->user_id = -1;
 4266     sc->group_id = -1;
 4267 
 4268     sc->checksum_flags = CHECKSUM_FLAG__ALL;
 4269     sc->tagged_packet_limit = 256;
 4270     sc->default_rule_state = RULE_STATE_ENABLED;
 4271     sc->pcre_match_limit = 1500;
 4272     sc->pcre_match_limit_recursion = 1500;
 4273     sc->ipv6_max_frag_sessions = 10000;
 4274     sc->ipv6_frag_timeout = 60;  /* This is the default timeout on BSD */
 4275 
 4276     memset(sc->pid_path, 0, sizeof(sc->pid_path));
 4277     memset(sc->pid_filename, 0, sizeof(sc->pid_filename));
 4278     memset(sc->pidfile_suffix, 0, sizeof(sc->pidfile_suffix));
 4279 
 4280 #ifdef TARGET_BASED
 4281     /* Default max size of the attribute table */
 4282     sc->max_attribute_hosts = DEFAULT_MAX_ATTRIBUTE_HOSTS;
 4283     sc->max_attribute_services_per_host = DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST;
 4284 
 4285     /* Default max number of services per rule */
 4286     sc->max_metadata_services = DEFAULT_MAX_METADATA_SERVICES;
 4287 #endif
 4288 #if defined(FEAT_OPEN_APPID)
 4289 #ifdef TARGET_BASED
 4290     sc->max_metadata_appid = DEFAULT_MAX_METADATA_APPID;
 4291 #endif
 4292 #endif /* defined(FEAT_OPEN_APPID) */
 4293 
 4294 #ifdef MPLS
 4295     sc->mpls_stack_depth = DEFAULT_LABELCHAIN_LENGTH;
 4296 #endif
 4297 
 4298     sc->targeted_policies = NULL;
 4299     sc->num_policies_allocated = 0;
 4300 
 4301     sc->paf_max = DEFAULT_PAF_MAX;
 4302 
 4303     /* Default secure hash pattern type */
 4304     sc->Default_Protected_Content_Hash_Type = SECHASH_NONE;
 4305 
 4306     sc->max_ip6_extensions = DEFAULT_MAX_IP6_EXTENSIONS;
 4307 
 4308     sc->internal_log_level = INTERNAL_LOG_LEVEL__MESSAGE;
 4309 
 4310     return sc;
 4311 }
 4312 
 4313 void SnortConfFree(SnortConfig *sc)
 4314 {
 4315     tSfPolicyId i;
 4316 
 4317     if (sc == NULL)
 4318         return;
 4319 
 4320     if (sc->dynamic_rules_path != NULL)
 4321         free(sc->dynamic_rules_path);
 4322 
 4323     if (sc->log_dir != NULL)
 4324         free(sc->log_dir);
 4325 
 4326     if (sc->orig_log_dir != NULL)
 4327         free(sc->orig_log_dir);
 4328 
 4329     if (sc->interface != NULL)
 4330         free(sc->interface);
 4331 
 4332     if (sc->bpf_file != NULL)
 4333         free(sc->bpf_file);
 4334 
 4335     if (sc->pcap_log_file != NULL)
 4336         free(sc->pcap_log_file);
 4337 
 4338     if (sc->chroot_dir != NULL)
 4339         free(sc->chroot_dir);
 4340 
 4341     if (sc->alert_file != NULL)
 4342         free(sc->alert_file);
 4343 
 4344     if (sc->perf_file != NULL)
 4345         free(sc->perf_file);
 4346 
 4347     if (sc->bpf_filter != NULL)
 4348         free(sc->bpf_filter);
 4349 
 4350     if (sc->event_trace_file != NULL)
 4351         free(sc->event_trace_file);
 4352 
 4353 #ifdef PERF_PROFILING
 4354     if (sc->profile_rules.filename != NULL)
 4355         free(sc->profile_rules.filename);
 4356 
 4357     if (sc->profile_preprocs.filename != NULL)
 4358         free(sc->profile_preprocs.filename);
 4359 #endif
 4360 
 4361     /* Main Thread only should cleanup if snort is exiting unless dynamic libs have changed */
 4362     if (detection_lib_changed || (InMainThread() && snort_exiting)) {
 4363         pthread_mutex_lock(&dynamic_rules_lock);
 4364         DynamicRuleListFree(sc->dynamic_rules);
 4365         sc->dynamic_rules = NULL;
 4366         pthread_mutex_unlock(&dynamic_rules_lock);
 4367         CloseDynamicDetectionLibs(sc);
 4368         detection_lib_changed = false;
 4369     }
 4370 
 4371     FreeDynamicLibInfos(sc);
 4372 
 4373     FreeOutputConfigs(sc->output_configs);
 4374     FreeOutputConfigs(sc->rule_type_output_configs);
 4375 #ifdef SIDE_CHANNEL
 4376     FreeSideChannelModuleConfigs(sc->side_channel_config.module_configs);
 4377 #ifdef REG_TEST
 4378     if (sc && sc->file_config)
 4379       FileSSConfigFree(sc->file_config);
 4380 #endif
 4381 #endif
 4382     FreePreprocConfigs(sc);
 4383 
 4384     if (sc->config_table != NULL)
 4385         sfghash_delete(sc->config_table);
 4386 
 4387     if (sc->base_version != NULL)
 4388         free(sc->base_version);
 4389 
 4390     for (i = 0; i < sc->num_policies_allocated; i++)
 4391     {
 4392         SnortPolicyFree(sc->targeted_policies[i]);
 4393     }
 4394 
 4395     FreeRuleStateList(sc->rule_state_list);
 4396     FreeClassifications(sc->classifications);
 4397     FreeReferences(sc->references);
 4398 
 4399     FreeRuleLists(sc);
 4400     SoRuleOtnLookupFree(sc->so_rule_otn_map);
 4401     OtnLookupFree(sc->otn_map);
 4402     VarTablesFree(sc);
 4403     PortTablesFree(sc->port_tables);
 4404     FastPatternConfigFree(sc->fast_pattern_config);
 4405 
 4406     ThresholdConfigFree(sc->threshold_config);
 4407     RateFilter_ConfigFree(sc->rate_filter_config);
 4408     DetectionFilterConfigFree(sc->detection_filter_config);
 4409 
 4410     FreePlugins(sc);
 4411 
 4412     PreprocessorRuleOptionsFree(sc->preproc_rule_options);
 4413 
 4414     OtnxMatchDataFree(sc->omd);
 4415 
 4416     if (sc->pcre_ovector != NULL)
 4417         free(sc->pcre_ovector);
 4418 
 4419     if ( sc->event_queue_config )
 4420         EventQueueConfigFree(sc->event_queue_config);
 4421 
 4422     if ( sc->event_queue )
 4423         SnortEventqFree(sc->event_queue);
 4424 
 4425     if (sc->ip_proto_only_lists != NULL)
 4426     {
 4427         unsigned int j;
 4428 
 4429         for (j = 0; j < NUM_IP_PROTOS; j++)
 4430             sflist_free_all(sc->ip_proto_only_lists[j], NULL);
 4431 
 4432         free(sc->ip_proto_only_lists);
 4433     }
 4434 
 4435     sfPolicyFini(sc->policy_config);
 4436 
 4437     fpDeleteFastPacketDetection(sc);
 4438 
 4439     if (sc->rtn_hash_table)
 4440         sfxhash_delete(sc->rtn_hash_table);
 4441 
 4442     for (i = 0; i < sc->num_policies_allocated; i++)
 4443     {
 4444         SnortPolicy *p = sc->targeted_policies[i];
 4445 
 4446         if (p != NULL)
 4447             free(p);
 4448        
 4449         if (sc->udp_ips_port_filter_list) {
 4450             IpsPortFilter *ips_portfilter = sc->udp_ips_port_filter_list[i];
 4451             if (ips_portfilter)
 4452                 free(ips_portfilter);
 4453         }
 4454     }
 4455 
 4456     if (sc->udp_ips_port_filter_list) 
 4457         free (sc->udp_ips_port_filter_list);
 4458 
 4459     free(sc->targeted_policies);
 4460 
 4461     if ( sc->react_page )
 4462         free(sc->react_page);
 4463 
 4464     if ( sc->daq_type )
 4465         free(sc->daq_type);
 4466 
 4467     if ( sc->daq_mode )
 4468         free(sc->daq_mode);
 4469 
 4470     if ( sc->daq_vars )
 4471         StringVector_Delete(sc->daq_vars);
 4472 
 4473     if ( sc->daq_dirs )
 4474         StringVector_Delete(sc->daq_dirs);
 4475 
 4476 #ifdef ACTIVE_RESPONSE
 4477     if ( sc->respond_device )
 4478         free(sc->respond_device);
 4479 
 4480      if (sc->eth_dst )
 4481         free(sc->eth_dst);
 4482 #endif
 4483 
 4484     if (sc->gtp_ports)
 4485         free(sc->gtp_ports);
 4486 
 4487     if(sc->cs_dir)
 4488         free(sc->cs_dir);
 4489 
 4490 #ifdef REG_TEST
 4491 
 4492     if(sc->ha_out)
 4493         free(sc->ha_out);
 4494 
 4495     if(sc->ha_in)
 4496         free(sc->ha_in);
 4497 
 4498     if(sc->ha_pdts_in)
 4499         free(sc->ha_pdts_in);
 4500 
 4501 #endif
 4502 
 4503     free_file_config(sc->file_config);
 4504 
 4505 #ifdef SIDE_CHANNEL
 4506     if (sc->side_channel_config.opts)
 4507         free(sc->side_channel_config.opts);
 4508 #endif
 4509 
 4510 #ifdef DUMP_BUFFER
 4511     if (sc->buffer_dump_file)
 4512         StringVector_Delete(sc->buffer_dump_file);
 4513 #endif
 4514 
 4515 #ifdef INTEL_SOFT_CPM
 4516     IntelPmRelease(sc->ipm_handles);
 4517 #endif
 4518 
 4519 #ifdef SNORT_RELOAD
 4520     FreePreprocessorReloadData(sc);
 4521     ReloadFreeAdjusters(sc);
 4522 #endif
 4523 
 4524     FreeMandatoryEarlySessionCreators(sc->mandatoryESCreators);
 4525 
 4526     free(sc);
 4527 #ifdef HAVE_MALLOC_TRIM
 4528     malloc_trim(0);
 4529 #endif
 4530 
 4531 }
 4532 
 4533 /****************************************************************************
 4534  *
 4535  * Function: InitNetMasks()
 4536  *
 4537  * Purpose: Loads the netmask struct in network order.  Yes, I know I could
 4538  *          just load the array when I define it, but this is what occurred
 4539  *          to me when I wrote this at 3:00 AM.
 4540  *
 4541  * Arguments: None.
 4542  *
 4543  * Returns: void function
 4544  *
 4545  ****************************************************************************/
 4546 static void InitNetmasks(void)
 4547 {
 4548     if (netmasks == NULL)
 4549         netmasks = (uint32_t *)SnortAlloc(33 * sizeof(uint32_t));
 4550 
 4551     netmasks[0]  = 0x00000000;
 4552     netmasks[1]  = 0x80000000;
 4553     netmasks[2]  = 0xC0000000;
 4554     netmasks[3]  = 0xE0000000;
 4555     netmasks[4]  = 0xF0000000;
 4556     netmasks[5]  = 0xF8000000;
 4557     netmasks[6]  = 0xFC000000;
 4558     netmasks[7]  = 0xFE000000;
 4559     netmasks[8]  = 0xFF000000;
 4560     netmasks[9]  = 0xFF800000;
 4561     netmasks[10] = 0xFFC00000;
 4562     netmasks[11] = 0xFFE00000;
 4563     netmasks[12] = 0xFFF00000;
 4564     netmasks[13] = 0xFFF80000;
 4565     netmasks[14] = 0xFFFC0000;
 4566     netmasks[15] = 0xFFFE0000;
 4567     netmasks[16] = 0xFFFF0000;
 4568     netmasks[17] = 0xFFFF8000;
 4569     netmasks[18] = 0xFFFFC000;
 4570     netmasks[19] = 0xFFFFE000;
 4571     netmasks[20] = 0xFFFFF000;
 4572     netmasks[21] = 0xFFFFF800;
 4573     netmasks[22] = 0xFFFFFC00;
 4574     netmasks[23] = 0xFFFFFE00;
 4575     netmasks[24] = 0xFFFFFF00;
 4576     netmasks[25] = 0xFFFFFF80;
 4577     netmasks[26] = 0xFFFFFFC0;
 4578     netmasks[27] = 0xFFFFFFE0;
 4579     netmasks[28] = 0xFFFFFFF0;
 4580     netmasks[29] = 0xFFFFFFF8;
 4581     netmasks[30] = 0xFFFFFFFC;
 4582     netmasks[31] = 0xFFFFFFFE;
 4583     netmasks[32] = 0xFFFFFFFF;
 4584 }
 4585 
 4586 /****************************************************************************
 4587  *
 4588  * Function: InitProtoNames()
 4589  *
 4590  * Purpose: Initializes the protocol names
 4591  *
 4592  * Arguments: None.
 4593  *
 4594  * Returns: void function
 4595  *
 4596  ****************************************************************************/
 4597 static void InitProtoNames(void)
 4598 {
 4599     int i;
 4600 
 4601     if (protocol_names == NULL)
 4602         protocol_names = (char **)SnortAlloc(sizeof(char *) * NUM_IP_PROTOS);
 4603 
 4604     for (i = 0; i < NUM_IP_PROTOS; i++)
 4605     {
 4606         switch(i)
 4607         {
 4608 #ifdef REG_TEST
 4609 #define PROTO_000 "IP"        //Appears as HOPOPT on some systems
 4610 #define PROTO_004 "IPENCAP"   //Appears as IPV4 on some systems
 4611 #define PROTO_255 "PROTO:255" //Appears as RESERVED on some systems
 4612             case 0:
 4613                 protocol_names[i] = SnortStrdup(PROTO_000);
 4614                 break;
 4615             case 4:
 4616                 protocol_names[i] = SnortStrdup(PROTO_004);
 4617                 break;
 4618             case 255:
 4619                 protocol_names[i] = SnortStrdup(PROTO_255);
 4620                 break;
 4621 #endif
 4622             default:
 4623             {
 4624                 struct protoent *pt = getprotobynumber(i);
 4625 
 4626                 if (pt != NULL)
 4627                 {
 4628                     size_t j;
 4629 
 4630                     protocol_names[i] = SnortStrdup(pt->p_name);
 4631                     for (j = 0; j < strlen(protocol_names[i]); j++)
 4632                         protocol_names[i][j] = toupper(protocol_names[i][j]);
 4633                 }
 4634                 else
 4635                 {
 4636                     char protoname[10];
 4637 
 4638                     SnortSnprintf(protoname, sizeof(protoname), "PROTO:%03d", i);
 4639                     protocol_names[i] = SnortStrdup(protoname);
 4640                 }
 4641             }
 4642         }
 4643     }
 4644 }
 4645 
 4646 
 4647 static void SetSnortConfDir(void)
 4648 {
 4649     /* extract the config directory from the config filename */
 4650     if (snort_conf_file != NULL)
 4651     {
 4652 #ifndef WIN32
 4653         char *path_sep = strrchr(snort_conf_file, '/');
 4654 #else
 4655         char *path_sep = strrchr(snort_conf_file, '\\');
 4656 #endif
 4657 
 4658         /* is there a directory seperator in the filename */
 4659         if (path_sep != NULL)
 4660         {
 4661             path_sep++;  /* include path separator */
 4662             snort_conf_dir = SnortStrndup(snort_conf_file, path_sep - snort_conf_file);
 4663         }
 4664         else
 4665         {
 4666             snort_conf_dir = SnortStrdup("./");
 4667         }
 4668 
 4669         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Config file = %s, config dir = "
 4670                     "%s\n", snort_conf_file, snort_conf_dir););
 4671     }
 4672 }
 4673 
 4674 static void FreePlugins(SnortConfig *sc)
 4675 {
 4676     if (sc == NULL)
 4677         return;
 4678 
 4679     FreePreprocessors(sc);
 4680 
 4681     FreePluginPostConfigFuncs(sc->plugin_post_config_funcs);
 4682     sc->plugin_post_config_funcs = NULL;
 4683 }
 4684 
 4685 static void FreePreprocessors(SnortConfig *sc)
 4686 {
 4687     tSfPolicyId i;
 4688 
 4689     if (sc == NULL)
 4690         return;
 4691 
 4692     FreePreprocCheckConfigFuncs(sc->preproc_config_check_funcs);
 4693     sc->preproc_config_check_funcs = NULL;
 4694 
 4695     for (i = 0; i < sc->num_policies_allocated; i++)
 4696     {
 4697         SnortPolicy *p = sc->targeted_policies[i];
 4698 
 4699         if (p == NULL)
 4700             continue;
 4701 
 4702         FreePreprocEvalFuncs(p->preproc_eval_funcs);
 4703         p->preproc_eval_funcs = NULL;
 4704         p->num_preprocs = 0;
 4705 
 4706         FreePreprocEvalFuncs(p->unused_preproc_eval_funcs);
 4707         p->unused_preproc_eval_funcs = NULL;
 4708 
 4709         FreePreprocMetaEvalFuncs(p->preproc_meta_eval_funcs);
 4710         p->preproc_meta_eval_funcs = NULL;
 4711         p->num_meta_preprocs = 0;
 4712 
 4713         FreeDetectionEvalFuncs(p->detect_eval_funcs);
 4714         p->detect_eval_funcs = NULL;
 4715         p->num_detects = 0;
 4716     }
 4717 
 4718     FreePreprocPostConfigFuncs(sc->preproc_post_config_funcs);
 4719     sc->preproc_post_config_funcs = NULL;
 4720 }
 4721 
 4722 SnortConfig * MergeSnortConfs(SnortConfig *cmd_line, SnortConfig *config_file)
 4723 {
 4724     unsigned int i;
 4725 
 4726     /* Move everything from the command line config over to the
 4727      * config_file config */
 4728 
 4729     if (cmd_line == NULL)
 4730     {
 4731         FatalError("%s(%d) Merging snort configs: snort conf is NULL.\n",
 4732                    __FILE__, __LINE__);
 4733     }
 4734 
 4735     ResolveOutputPlugins(cmd_line, config_file);
 4736 
 4737     if (config_file == NULL)
 4738     {
 4739         if (cmd_line->log_dir == NULL)
 4740             cmd_line->log_dir = SnortStrdup(DEFAULT_LOG_DIR);
 4741     }
 4742     else if ((cmd_line->log_dir == NULL) && (config_file->log_dir == NULL))
 4743     {
 4744         config_file->log_dir = SnortStrdup(DEFAULT_LOG_DIR);
 4745     }
 4746     else if (cmd_line->log_dir != NULL)
 4747     {
 4748         if (config_file->log_dir != NULL)
 4749             free(config_file->log_dir);
 4750 
 4751         config_file->log_dir = SnortStrdup(cmd_line->log_dir);
 4752     }
 4753 
 4754     if (config_file == NULL)
 4755         return cmd_line;
 4756 
 4757     /* Used because of a potential chroot */
 4758     config_file->orig_log_dir = SnortStrdup(config_file->log_dir);
 4759 
 4760     config_file->run_mode = cmd_line->run_mode;
 4761     config_file->run_mode_flags |= cmd_line->run_mode_flags;
 4762 
 4763     if ((cmd_line->run_mode == RUN_MODE__TEST) &&
 4764         (config_file->run_flags & RUN_FLAG__DAEMON))
 4765     {
 4766         /* Just ignore deamon setting in conf file */
 4767         config_file->run_flags &= ~RUN_FLAG__DAEMON;
 4768     }
 4769 
 4770     config_file->run_flags |= cmd_line->run_flags;
 4771     config_file->output_flags |= cmd_line->output_flags;
 4772     config_file->logging_flags |= cmd_line->logging_flags;
 4773 
 4774     config_file->internal_log_level = cmd_line->internal_log_level;
 4775     config_file->suppress_config_log = cmd_line->suppress_config_log;
 4776 
 4777     /* Merge checksum flags.  If command line modified them, use from the
 4778      * command line, else just use from config_file. */
 4779     for (i = 0; i < config_file->num_policies_allocated; i++)
 4780     {
 4781         if (config_file->targeted_policies[i] != NULL)
 4782         {
 4783             if (cmd_line->checksum_flags_modified)
 4784                 config_file->targeted_policies[i]->checksum_flags = cmd_line->checksum_flags;
 4785 
 4786             if (cmd_line->checksum_drop_flags_modified)
 4787                 config_file->targeted_policies[i]->checksum_drop_flags = cmd_line->checksum_drop_flags;
 4788         }
 4789     }
 4790 
 4791     config_file->event_log_id = cmd_line->event_log_id;
 4792 
 4793     if (cmd_line->dynamic_rules_path != NULL)
 4794     {
 4795         if(strcmp(cmd_line->dynamic_rules_path, "")  != 0)
 4796         {
 4797             if( config_file->dynamic_rules_path != NULL )
 4798                 free(config_file->dynamic_rules_path);
 4799             config_file->dynamic_rules_path = SnortStrdup(cmd_line->dynamic_rules_path);
 4800         }
 4801     }
 4802 
 4803     if (cmd_line->dyn_engines != NULL)
 4804     {
 4805         FreeDynamicLibInfo(config_file->dyn_engines);
 4806         config_file->dyn_engines = DupDynamicLibInfo(cmd_line->dyn_engines);
 4807     }
 4808 
 4809     if (cmd_line->dyn_rules != NULL)
 4810     {
 4811         FreeDynamicLibInfo(config_file->dyn_rules);
 4812         config_file->dyn_rules = DupDynamicLibInfo(cmd_line->dyn_rules);
 4813     }
 4814 
 4815     if (cmd_line->dyn_preprocs != NULL)
 4816     {
 4817         FreeDynamicLibInfo(config_file->dyn_preprocs);
 4818         config_file->dyn_preprocs = DupDynamicLibInfo(cmd_line->dyn_preprocs);
 4819     }
 4820 
 4821     if (cmd_line->pid_path[0] != '\0')
 4822         ConfigPidPath(config_file, cmd_line->pid_path);
 4823 
 4824     config_file->exit_check = cmd_line->exit_check;
 4825 
 4826     /* Command line only configures search method */
 4827     if (cmd_line->fast_pattern_config != NULL)
 4828         config_file->fast_pattern_config->search_method = cmd_line->fast_pattern_config->search_method;
 4829 
 4830     if (sfip_is_set(&cmd_line->obfuscation_net))
 4831         memcpy(&config_file->obfuscation_net, &cmd_line->obfuscation_net, sizeof(sfcidr_t));
 4832 
 4833     if (sfip_is_set(&cmd_line->homenet))
 4834         memcpy(&config_file->homenet, &cmd_line->homenet, sizeof(sfcidr_t));
 4835 
 4836     if (cmd_line->interface != NULL)
 4837     {
 4838         if (config_file->interface != NULL)
 4839             free(config_file->interface);
 4840         config_file->interface = SnortStrdup(cmd_line->interface);
 4841     }
 4842 
 4843     if (cmd_line->bpf_file != NULL)
 4844     {
 4845         if (config_file->bpf_file != NULL)
 4846             free(config_file->bpf_file);
 4847         config_file->bpf_file = SnortStrdup(cmd_line->bpf_file);
 4848     }
 4849 
 4850     if (cmd_line->bpf_filter != NULL)
 4851         config_file->bpf_filter = SnortStrdup(cmd_line->bpf_filter);
 4852 
 4853     if (cmd_line->pkt_snaplen != -1)
 4854         config_file->pkt_snaplen = cmd_line->pkt_snaplen;
 4855 
 4856     if (cmd_line->pkt_cnt != 0)
 4857         config_file->pkt_cnt = cmd_line->pkt_cnt;
 4858 
 4859 #ifdef REG_TEST
 4860     if (cmd_line->pkt_skip != 0)
 4861         config_file->pkt_skip = cmd_line->pkt_skip;
 4862 #endif
 4863 
 4864     if (cmd_line->group_id != -1)
 4865         config_file->group_id = cmd_line->group_id;
 4866 
 4867     if (cmd_line->user_id != -1)
 4868         config_file->user_id = cmd_line->user_id;
 4869 
 4870     /* Only configurable on command line */
 4871     if (cmd_line->pcap_log_file != NULL)
 4872         config_file->pcap_log_file = SnortStrdup(cmd_line->pcap_log_file);
 4873 
 4874     if (cmd_line->file_mask != 0)
 4875         config_file->file_mask = cmd_line->file_mask;
 4876 
 4877     if (cmd_line->pidfile_suffix[0] != '\0')
 4878     {
 4879         SnortStrncpy(config_file->pidfile_suffix, cmd_line->pidfile_suffix,
 4880                      sizeof(config_file->pidfile_suffix));
 4881     }
 4882 
 4883     if (cmd_line->chroot_dir != NULL)
 4884     {
 4885         if (config_file->chroot_dir != NULL)
 4886             free(config_file->chroot_dir);
 4887         config_file->chroot_dir = SnortStrdup(cmd_line->chroot_dir);
 4888     }
 4889 
 4890     if (cmd_line->perf_file != NULL)
 4891     {
 4892         if (config_file->perf_file != NULL)
 4893             free(config_file->perf_file);
 4894         config_file->perf_file = SnortStrdup(cmd_line->perf_file);
 4895     }
 4896 
 4897     if ( cmd_line->daq_type )
 4898         config_file->daq_type = SnortStrdup(cmd_line->daq_type);
 4899 
 4900     if ( cmd_line->daq_mode )
 4901         config_file->daq_mode = SnortStrdup(cmd_line->daq_mode);
 4902 
 4903     if ( cmd_line->dirty_pig )
 4904         config_file->dirty_pig = cmd_line->dirty_pig;
 4905 
 4906     if ( cmd_line->daq_vars )
 4907     {
 4908         /* Command line overwrites daq_vars */
 4909         if (config_file->daq_vars)
 4910             StringVector_Delete(config_file->daq_vars);
 4911 
 4912         config_file->daq_vars = StringVector_New();
 4913         StringVector_AddVector(config_file->daq_vars, cmd_line->daq_vars);
 4914     }
 4915     if ( cmd_line->daq_dirs )
 4916     {
 4917         /* Command line overwrites daq_dirs */
 4918         if (config_file->daq_dirs)
 4919             StringVector_Delete(config_file->daq_dirs);
 4920 
 4921         config_file->daq_dirs = StringVector_New();
 4922         StringVector_AddVector(config_file->daq_dirs, cmd_line->daq_dirs);
 4923     }
 4924 #ifdef MPLS
 4925     if (cmd_line->mpls_stack_depth != DEFAULT_LABELCHAIN_LENGTH)
 4926         config_file->mpls_stack_depth = cmd_line->mpls_stack_depth;
 4927 
 4928     /* Set MPLS payload type here if it hasn't been defined */
 4929     if ((cmd_line->mpls_payload_type == 0) &&
 4930         (config_file->mpls_payload_type == 0))
 4931     {
 4932         config_file->mpls_payload_type = DEFAULT_MPLS_PAYLOADTYPE;
 4933     }
 4934     else if (cmd_line->mpls_payload_type != 0)
 4935     {
 4936         config_file->mpls_payload_type = cmd_line->mpls_payload_type;
 4937     }
 4938 #endif
 4939 
 4940     if (cmd_line->run_flags & RUN_FLAG__PROCESS_ALL_EVENTS)
 4941         config_file->event_queue_config->process_all_events = 1;
 4942 
 4943     if (cmd_line->cs_dir != NULL)
 4944     {
 4945         if (config_file->cs_dir != NULL)
 4946             free(config_file->cs_dir);
 4947         config_file->cs_dir = SnortStrdup(cmd_line->cs_dir);
 4948     }
 4949     if (config_file->cs_dir)
 4950     {
 4951 
 4952 #ifndef WIN32
 4953         /*
 4954          *  If an absolute path is specified, then use that.
 4955          *  otherwise, relative to pid path
 4956          */
 4957         if ((config_file->cs_dir[0] != '/') && config_file->pid_path[0])
 4958         {
 4959 
 4960             char fullpath[PATH_MAX];
 4961 
 4962             if (config_file->pid_path[strlen(config_file->pid_path) - 1] == '/')
 4963             {
 4964                 SnortSnprintf(fullpath, sizeof(fullpath),
 4965                         "%s%s", config_file->pid_path, config_file->cs_dir);
 4966             }
 4967             else
 4968             {
 4969                 SnortSnprintf(fullpath, sizeof(fullpath),
 4970                         "%s/%s", config_file->pid_path, config_file->cs_dir);
 4971             }
 4972             free (config_file->cs_dir);
 4973             config_file->cs_dir = SnortStrdup(fullpath);
 4974 
 4975         }
 4976 #else
 4977         /*Not supported in WINDOWS*/
 4978         free (config_file->cs_dir);
 4979         config_file->cs_dir = NULL;
 4980 #endif
 4981         ControlSocketConfigureDirectory(config_file->cs_dir);
 4982     }
 4983 
 4984 #ifdef REG_TEST
 4985     config_file->ha_peer = cmd_line->ha_peer;
 4986 
 4987     if ( cmd_line->ha_out )
 4988     {
 4989         if(config_file->ha_out != NULL)
 4990             free(config_file->ha_out);
 4991         config_file->ha_out = strdup(cmd_line->ha_out);
 4992     }
 4993 
 4994     if ( cmd_line->ha_in )
 4995     {
 4996         if(config_file->ha_in != NULL)
 4997             free(config_file->ha_in);
 4998         config_file->ha_in = strdup(cmd_line->ha_in);
 4999     }
 5000     if ( cmd_line->ha_pdts_in )
 5001     {
 5002         if(config_file->ha_pdts_in != NULL)
 5003             free(config_file->ha_pdts_in);
 5004         config_file->ha_pdts_in = strdup(cmd_line->ha_pdts_in);
 5005     }
 5006 
 5007 #endif
 5008 
 5009 #ifdef DUMP_BUFFER
 5010     /* Command line overwrites daq_dirs */
 5011     if (config_file->buffer_dump_file)
 5012         StringVector_Delete(config_file->buffer_dump_file);
 5013 
 5014     config_file->buffer_dump_file = StringVector_New();
 5015     StringVector_AddVector(config_file->buffer_dump_file, cmd_line->buffer_dump_file);
 5016 #endif
 5017 
 5018     return config_file;
 5019 }
 5020 
 5021 static void FreeDynamicLibInfos(SnortConfig *sc)
 5022 {
 5023     if (sc == NULL)
 5024         return;
 5025 
 5026     if (sc->dyn_engines != NULL)
 5027     {
 5028         FreeDynamicLibInfo(sc->dyn_engines);
 5029         sc->dyn_engines = NULL;
 5030     }
 5031 
 5032     if (sc->dyn_rules != NULL)
 5033     {
 5034         FreeDynamicLibInfo(sc->dyn_rules);
 5035         sc->dyn_rules = NULL;
 5036     }
 5037 
 5038     if (sc->dyn_preprocs != NULL)
 5039     {
 5040         FreeDynamicLibInfo(sc->dyn_preprocs);
 5041         sc->dyn_preprocs = NULL;
 5042     }
 5043 
 5044 #ifdef SIDE_CHANNEL
 5045     if (sc->dyn_side_channels != NULL)
 5046     {
 5047         FreeDynamicLibInfo(sc->dyn_side_channels);
 5048         sc->dyn_side_channels = NULL;
 5049     }
 5050 #endif
 5051 }
 5052 
 5053 static void FreeDynamicLibInfo(DynamicLibInfo *lib_info)
 5054 {
 5055     unsigned i;
 5056 
 5057     if (lib_info == NULL)
 5058         return;
 5059 
 5060     for (i = 0; i < lib_info->count; i++)
 5061     {
 5062         free(lib_info->lib_paths[i]->path);
 5063         free(lib_info->lib_paths[i]);
 5064     }
 5065 
 5066     free(lib_info);
 5067 }
 5068 
 5069 static DynamicLibInfo * DupDynamicLibInfo(DynamicLibInfo *src)
 5070 {
 5071     DynamicLibInfo *dst;
 5072     unsigned i;
 5073 
 5074     if (src == NULL)
 5075         return NULL;
 5076 
 5077     dst = (DynamicLibInfo *)SnortAlloc(sizeof(DynamicLibInfo));
 5078     dst->type = src->type;
 5079     dst->count = src->count;
 5080 
 5081     for (i = 0; i < src->count; i++)
 5082     {
 5083         DynamicLibPath *dylib_path = (DynamicLibPath *)SnortAlloc(sizeof(DynamicLibPath));
 5084 
 5085         dylib_path->ptype = src->lib_paths[i]->ptype;
 5086         dylib_path->path = SnortStrdup(src->lib_paths[i]->path);
 5087 
 5088         dst->lib_paths[i] = dylib_path;
 5089     }
 5090 
 5091     return dst;
 5092 }
 5093 
 5094 void FreeVarList(VarNode *head)
 5095 {
 5096     while (head != NULL)
 5097     {
 5098         VarNode *tmp = head;
 5099 
 5100         head = head->next;
 5101 
 5102         if (tmp->name != NULL)
 5103             free(tmp->name);
 5104 
 5105         if (tmp->value != NULL)
 5106             free(tmp->value);
 5107 
 5108         if (tmp->line != NULL)
 5109             free(tmp->line);
 5110 
 5111         free(tmp);
 5112     }
 5113 }
 5114 
 5115 void SnortInit(int argc, char **argv)
 5116 {
 5117 #ifdef WIN32
 5118     char dllSearchPath[PATH_MAX];
 5119 #endif
 5120     InitSignals();
 5121 
 5122 #if defined(NOCOREFILE) && !defined(WIN32)
 5123     SetNoCores();
 5124 #else
 5125     StoreSnortInfoStrings();
 5126 #endif
 5127 
 5128 #ifdef WIN32
 5129     if(GetSystemDirectory(dllSearchPath, PATH_MAX))
 5130     {
 5131         LogMessage("System directory is: %s\n", dllSearchPath);
 5132         if (!SetDllDirectory(dllSearchPath))
 5133             FatalError("Failed to set Windows DLL search path.\n");
 5134     }
 5135     else
 5136         FatalError("Could not find the Windows System directory.\n");
 5137 
 5138     if (!init_winsock()) // TBD moves to windows daq
 5139         FatalError("Could not Initialize Winsock!\n");
 5140 #endif
 5141 
 5142     InitGlobals();
 5143 
 5144     /* chew up the command line */
 5145     ParseCmdLine(argc, argv);
 5146 
 5147     switch (snort_conf->run_mode)
 5148     {
 5149         case RUN_MODE__VERSION:
 5150             break;
 5151 
 5152         case RUN_MODE__RULE_DUMP:
 5153             LogMessage("Running in Rule Dump mode\n");
 5154             break;
 5155 
 5156         case RUN_MODE__IDS:
 5157             LogMessage("Running in IDS mode\n");
 5158             break;
 5159 
 5160         case RUN_MODE__TEST:
 5161             LogMessage("Running in Test mode\n");
 5162             break;
 5163 
 5164         case RUN_MODE__PACKET_LOG:
 5165             LogMessage("Running in packet logging mode\n");
 5166             break;
 5167 
 5168         case RUN_MODE__PACKET_DUMP:
 5169             LogMessage("Running in packet dump mode\n");
 5170             break;
 5171 
 5172         default:
 5173             break;
 5174     }
 5175 
 5176     if (ScSuppressConfigLog() || ScVersionMode())
 5177         ScSetInternalLogLevel(INTERNAL_LOG_LEVEL__ERROR);
 5178 
 5179     LogMessage("\n");
 5180     LogMessage("        --== Initializing Snort ==--\n");
 5181 
 5182     if (SnortStrnlen(signal_error_msg, STD_BUF)> 0)
 5183     {
 5184         ErrorMessage("%s", signal_error_msg);
 5185     }
 5186 
 5187     if (!ScVersionMode())
 5188     {
 5189         /* Every run mode except version will potentially need output
 5190          * If output plugins should become dynamic, this needs to move */
 5191         RegisterOutputPlugins();
 5192 #ifdef DEBUG
 5193         DumpOutputPlugins();
 5194 #endif
 5195     }
 5196 
 5197     init_fileAPI();
 5198     /* if we're using the rules system, it gets initialized here */
 5199     if (snort_conf_file != NULL)
 5200     {
 5201         SnortConfig *sc;
 5202 
 5203         /* initialize all the plugin modules */
 5204         RegisterPreprocessors();
 5205         RegisterRuleOptions();
 5206         InitTag();
 5207 
 5208 #ifdef DEBUG
 5209         DumpPreprocessors();
 5210         DumpRuleOptions();
 5211 #endif
 5212 
 5213 #ifdef PERF_PROFILING
 5214         /* Register the main high level perf stats */
 5215         RegisterPreprocessorProfile("detect", &detectPerfStats, 0, &totalPerfStats, NULL);
 5216         RegisterPreprocessorProfile("mpse", &mpsePerfStats, 1, &detectPerfStats, NULL);
 5217         RegisterPreprocessorProfile("rule eval", &rulePerfStats, 1, &detectPerfStats, NULL);
 5218         RegisterPreprocessorProfile("rtn eval", &ruleRTNEvalPerfStats, 2, &rulePerfStats, NULL);
 5219         RegisterPreprocessorProfile("rule tree eval", &ruleOTNEvalPerfStats, 2, &rulePerfStats, NULL);
 5220         RegisterPreprocessorProfile("preproc_rule_options", &preprocRuleOptionPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
 5221         RegisterPreprocessorProfile("decode", &decodePerfStats, 0, &totalPerfStats, NULL);
 5222         RegisterPreprocessorProfile("eventq", &eventqPerfStats, 0, &totalPerfStats, NULL);
 5223         RegisterPreprocessorProfile("total", &totalPerfStats, 0, NULL, NULL);
 5224         RegisterPreprocessorProfile("daq meta", &metaPerfStats, 0, NULL, NULL);
 5225         (void)PerfIndicator_RegisterPreprocStat( &totalPerfStats,
 5226                                                  Perf_Indicator_Type_Packet_Latency );
 5227 
 5228 #endif
 5229 
 5230         LogMessage("Parsing Rules file \"%s\"\n", snort_conf_file);
 5231 
 5232         sc = ParseSnortConf();
 5233 
 5234         /* Merge the command line and config file confs to take care of
 5235          * command line overriding config file.
 5236          * Set the global snort_conf that will be used during run time */
 5237         snort_conf = MergeSnortConfs(snort_cmd_line_conf, sc);
 5238 
 5239         InitSynToMulticastDstIp(snort_conf);
 5240         InitMulticastReservedIp(snort_conf);
 5241 
 5242 #ifdef TARGET_BASED
 5243         /* Parse attribute table stuff here since config max_attribute_hosts
 5244          * is apart from attribute table configuration.
 5245          * Only attribute table in default policy is processed. Attribute table in
 5246          * other policies indicates that attribute table in default table should
 5247          * be used. Filenames for attribute_table should be same across all policies.
 5248          */
 5249         {
 5250             tSfPolicyId defaultPolicyId = sfGetDefaultPolicy(snort_conf->policy_config);
 5251             TargetBasedConfig *tbc = &snort_conf->targeted_policies[defaultPolicyId]->target_based_config;
 5252 
 5253             if (tbc->args != NULL)
 5254             {
 5255                 char *saved_file_name = file_name;
 5256                 int saved_file_line = file_line;
 5257 
 5258                 file_name = tbc->file_name;
 5259                 file_line = tbc->file_line;
 5260 
 5261                 SFAT_ParseAttributeTable(tbc->args, snort_conf);
 5262 #ifndef WIN32
 5263         if (!ScDisableAttrReload(snort_conf))
 5264         {
 5265             /* Register signal handler for attribute table. */
 5266             SnortAddSignal(SIGNAL_SNORT_READ_ATTR_TBL,SigAttributeTableReloadHandler,0);
 5267             
 5268             if(errno != 0)
 5269                 errno = 0;
 5270         }
 5271 #endif
 5272                 file_name = saved_file_name;
 5273                 file_line = saved_file_line;
 5274             }
 5275         }
 5276 #endif
 5277 
 5278         if (snort_conf->asn1_mem != 0)
 5279             asn1_init_mem(snort_conf->asn1_mem);
 5280         else
 5281             asn1_init_mem(256);
 5282 
 5283         if (snort_conf->alert_file != NULL)
 5284         {
 5285             char *tmp = snort_conf->alert_file;
 5286             snort_conf->alert_file = ProcessFileOption(snort_conf, snort_conf->alert_file);
 5287             free(tmp);
 5288         }
 5289 
 5290 #ifdef PERF_PROFILING
 5291         /* Parse profiling here because of file option and potential
 5292          * dependence on log directory */
 5293         {
 5294             char *opts = NULL;
 5295             int in_table;
 5296 
 5297             in_table = sfghash_find2(snort_conf->config_table,
 5298                                      CONFIG_OPT__PROFILE_PREPROCS, (void *)&opts);
 5299             if (in_table)
 5300                 ConfigProfilePreprocs(snort_conf, opts);
 5301 
 5302             in_table = sfghash_find2(snort_conf->config_table,
 5303                                      CONFIG_OPT__PROFILE_RULES, (void *)&opts);
 5304             if (in_table)
 5305                 ConfigProfileRules(snort_conf, opts);
 5306         }
 5307 #endif
 5308 
 5309         if (ScAlertBeforePass())
 5310         {
 5311             OrderRuleLists(snort_conf, "activation dynamic drop sdrop reject alert pass log");
 5312         }
 5313 
 5314         LogMessage("Tagged Packet Limit: %ld\n", snort_conf->tagged_packet_limit);
 5315 
 5316 
 5317         /* Handles Fatal Errors itself. */
 5318         SnortEventqNew(snort_conf->event_queue_config, snort_conf->event_queue);
 5319     }
 5320     else if (ScPacketLogMode() || ScPacketDumpMode())
 5321     {
 5322         /* Make sure there is a log directory */
 5323         /* This will return the cmd line conf and resolve the output
 5324          * configuration */
 5325         SnortConfig* sc = ParseSnortConf();
 5326         snort_conf = MergeSnortConfs(snort_cmd_line_conf, sc);
 5327         InitTag();
 5328         SnortEventqNew(snort_conf->event_queue_config, snort_conf->event_queue);
 5329     }
 5330 
 5331 
 5332     /* Allocate an array for IP6 extensions for the main Packet struct */
 5333     // Make sure this memory is freed on exit.
 5334     s_packet.ip6_extensions = SnortAlloc(sizeof(*s_packet.ip6_extensions) * ScMaxIP6Extensions());
 5335 
 5336     /* Finish up the pcap list and put in the queues */
 5337     PQ_SetUp();
 5338 
 5339     if ((snort_conf->bpf_filter == NULL) && (snort_conf->bpf_file != NULL))
 5340     {
 5341         LogMessage("Reading filter from bpf file: %s\n", snort_conf->bpf_file);
 5342         snort_conf->bpf_filter = read_infile(snort_conf->bpf_file);
 5343     }
 5344 
 5345     if (snort_conf->bpf_filter != NULL)
 5346         LogMessage("Snort BPF option: %s\n", snort_conf->bpf_filter);
 5347 
 5348     LoadDynamicPlugins(snort_conf);
 5349 
 5350     /* Display snort version information here so that we can also show dynamic
 5351      * plugin versions, if loaded.  */
 5352     if (ScVersionMode())
 5353     {
 5354         ScRestoreInternalLogLevel();
 5355         PrintVersion(snort_conf);
 5356         CleanExit(0);
 5357     }
 5358 
 5359     /* Validate the log directory for logging packets - probably should
 5360      * add test mode as well, but not expected behavior */
 5361     if ( !(ScNoLog() && ScNoAlert()) )
 5362     {
 5363         if (ScPacketLogMode())
 5364             CheckLogDir();
 5365 
 5366         LogMessage("Log directory = %s\n", snort_conf->log_dir);
 5367     }
 5368 
 5369     if (ScOutputUseUtc())
 5370         snort_conf->thiszone = 0;
 5371     else
 5372         snort_conf->thiszone = gmt2local(0);  /* ripped from tcpdump */
 5373 
 5374     ConfigureOutputPlugins(snort_conf);
 5375 
 5376     /* Have to split up configuring preprocessors between internal and dynamic
 5377      * because the dpd structure has a pointer to the stream api and stream5
 5378      * needs to be configured first to set this */
 5379     ConfigurePreprocessors(snort_conf, 0);
 5380 
 5381     InitDynamicEngines(snort_conf->dynamic_rules_path);
 5382 
 5383     if (ScRuleDumpMode())
 5384     {
 5385         if( snort_conf->dynamic_rules_path == NULL )
 5386         {
 5387             FatalError("%s(%d) Please specify the directory path for dumping the dynamic rules \n",
 5388                                        __FILE__, __LINE__);
 5389         }
 5390 
 5391         DumpDetectionLibRules(snort_conf);
 5392         CleanExit(0);
 5393     }
 5394 
 5395     /* This will load each dynamic preprocessor module specified and set
 5396      * the _dpd structure for each */
 5397     InitDynamicPreprocessors();
 5398 
 5399     /* Now configure the dynamic preprocessors since the dpd structure
 5400      * should be filled in and have the correct values */
 5401     ConfigurePreprocessors(snort_conf, 1);
 5402 
 5403     ParseRules(snort_conf);
 5404     RuleOptParseCleanup();
 5405 
 5406     InitDynamicDetectionPlugins(snort_conf);
 5407 
 5408     EventTrace_Init();
 5409 
 5410     if (ScIdsMode() || ScTestMode())
 5411     {
 5412         detection_filter_print_config(snort_conf->detection_filter_config);
 5413         RateFilter_PrintConfig(snort_conf->rate_filter_config);
 5414         print_thresholding(snort_conf->threshold_config, 0);
 5415         PrintRuleOrder(snort_conf->rule_lists);
 5416 
 5417         /* Check rule state lists, enable/disabled
 5418          * and err on 'special' GID without OTN.
 5419          */
 5420         /*
 5421          * Modified toi use sigInfo.shared in otn instead of the GENERATOR ID  - man
 5422          */
 5423         SetRuleStates(snort_conf);
 5424 
 5425         /* Verify the preprocessors are configured properly */
 5426         if (CheckPreprocessorsConfig(snort_conf))
 5427         {
 5428             SnortFatalExit();
 5429         }
 5430 
 5431         /* Remove disabled preprocessors if policies are disabled  */
 5432         FilterConfigPreprocessors(snort_conf);
 5433 
 5434         /* Need to do this after dynamic detection stuff is initialized, too */
 5435         FlowBitsVerify();
 5436     }
 5437 
 5438     snort_conf->udp_ips_port_filter_list = ParseIpsPortList(snort_conf, IPPROTO_UDP);
 5439 
 5440     if (snort_conf->file_mask != 0)
 5441         umask(snort_conf->file_mask);
 5442     else
 5443         umask(077);    /* set default to be sane */
 5444 
 5445     // the following was moved from unpriv init; hopefully it can live here.
 5446     decoderActionQ = sfActionQueueInit(snort_conf->event_queue_config->max_events*2);
 5447     if (mempool_init(&decoderAlertMemPool,
 5448                 snort_conf->event_queue_config->max_events*2, sizeof(EventNode)) != 0)
 5449     {
 5450         FatalError("%s(%d) Could not initialize decoder action queue memory pool.\n",
 5451                 __FILE__, __LINE__);
 5452     }
 5453 
 5454     fpCreateFastPacketDetection(snort_conf);
 5455 
 5456 #ifdef INTEL_SOFT_CPM
 5457     if (snort_conf->fast_pattern_config->search_method == MPSE_INTEL_CPM)
 5458         IntelPmActivate(snort_conf);
 5459 #endif
 5460 
 5461 #ifdef PPM_MGR
 5462     PPM_PRINT_CFG(&snort_conf->ppm_cfg);
 5463 #endif
 5464 
 5465 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
 5466     // This is needed when PPM is disabled and enabling snort-engine debugs
 5467     if (!ppm_tpu)
 5468        ppm_tpu = (PPM_TICKS)get_ticks_per_usec();
 5469 #endif
 5470 
 5471 #ifdef SIDE_CHANNEL
 5472     RegisterSideChannelModules();
 5473     InitDynamicSideChannelPlugins();
 5474     ConfigureSideChannelModules(snort_conf);
 5475     SideChannelConfigure(snort_conf);
 5476     SideChannelInit();
 5477 #ifndef REG_TEST
 5478     if (snort_conf && snort_conf->file_config)
 5479        check_sidechannel_enabled(snort_conf->file_config);
 5480 #endif
 5481 #endif
 5482 
 5483     FileServiceInstall();
 5484 
 5485     // If we suppressed output at the beginning of SnortInit(),
 5486     // then restore it now.
 5487     ScRestoreInternalLogLevel();
 5488 }
 5489 
 5490 #if defined(INLINE_FAILOPEN) && !defined(WIN32)
 5491 static void * SnortPostInitThread(void *data)
 5492 {
 5493     sigset_t mtmask;
 5494 
 5495     inline_failopen_thread_pid = gettid();
 5496     inline_failopen_thread_running = 1;
 5497 
 5498     /* Don't handle any signals here */
 5499     sigfillset(&mtmask);
 5500     pthread_sigmask(SIG_BLOCK, &mtmask, NULL);
 5501 
 5502     while (!inline_failopen_initialized)
 5503         nanosleep(&thread_sleep, NULL);
 5504 
 5505     SnortUnprivilegedInit();
 5506 
 5507     pthread_exit((void *)NULL);
 5508 }
 5509 
 5510 static DAQ_Verdict IgnoreCallback (
 5511     void *user, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
 5512 {
 5513     /* Empty function -- do nothing with the packet we just read */
 5514     inline_failopen_pass_pkt_cnt++;
 5515 
 5516 #ifdef DEBUG
 5517     {
 5518         FILE *tmp = fopen("/var/tmp/fo_threadid", "a");
 5519         if ( tmp )
 5520         {
 5521             fprintf(tmp, "Packet Count %d\n", inline_failopen_pass_pkt_cnt);
 5522             fclose(tmp);
 5523         }
 5524     }
 5525 #endif
 5526     return DAQ_VERDICT_PASS;
 5527 }
 5528 #endif /* defined(INLINE_FAILOPEN) && !defined(WIN32) */
 5529 
 5530 // this function should only include initialization that must be done as a
 5531 // non-root user such as creating log files.  other initialization stuff should
 5532 // be in the main initialization function since, depending on platform and
 5533 // configuration, this may be running in a background thread while passing
 5534 // packets in a fail open mode in the main thread.  we don't want big delays
 5535 // here to cause excess latency or dropped packets in that thread which may
 5536 // be the case if all threads are pinned to a single cpu/core.
 5537 //
 5538 // clarification: once snort opens/starts the DAQ, packets are queued for snort
 5539 // and must be disposed of quickly or the queue will overflow and packets will
 5540 // be dropped so the fail open thread does the remaining initialization while
 5541 // the main thread passes packets.  prior to opening and starting the DAQ,
 5542 // packet passing is done by the driver/hardware.  the goal then is to put as
 5543 // much initialization stuff in SnortInit() as possible and to restrict this
 5544 // function to those things that depend on DAQ startup or non-root user/group.
 5545 static void SnortUnprivilegedInit(void)
 5546 {
 5547 #ifdef ACTIVE_RESPONSE
 5548     // this depends on instantiated daq capabilities
 5549     // so it is done here instead of SnortInit()
 5550     Active_Init(snort_conf);
 5551 #endif
 5552 
 5553     InitPidChrootAndPrivs(snort_main_thread_pid);
 5554 
 5555 #if defined(HAVE_LINUXTHREADS) && !defined(WIN32)
 5556     // this must be done after dropping privs for linux threads
 5557     // to ensure that child threads can communicate with parent
 5558     SnortStartThreads();
 5559 #endif
 5560 
 5561     // perfmon, for one, opens a log file for writing here
 5562     PostConfigPreprocessors(snort_conf);
 5563 
 5564     // log_tcpdump opens a log file for writing here; also ...
 5565     // note that things like opening log_tcpdump will fail here if the
 5566     // user specified -u (we dropped privileges) and the log defaults
 5567     // to /var/log/snort.  in this case they must override log path.
 5568     PostConfigInitPlugins(snort_conf, snort_conf->plugin_post_config_funcs);
 5569 
 5570 #ifdef SIDE_CHANNEL
 5571     SideChannelPostInit();
 5572 #endif
 5573 
 5574     LogMessage("\n");
 5575     LogMessage("        --== Initialization Complete ==--\n");
 5576 
 5577     /* Tell 'em who wrote it, and what "it" is */
 5578     PrintVersion(snort_conf);
 5579 
 5580     if (ScTestMode())
 5581     {
 5582         LogMessage("\n");
 5583         LogMessage("Snort successfully validated the configuration!\n");
 5584         CleanExit(0);
 5585     }
 5586 
 5587     LogMessage("Commencing packet processing (pid=%u)\n", snort_main_thread_pid);
 5588 
 5589     snort_initializing = false;
 5590 }
 5591 
 5592 #if defined(NOCOREFILE) && !defined(WIN32)
 5593 static void SetNoCores(void)
 5594 {
 5595     struct rlimit rlim;
 5596 
 5597     getrlimit(RLIMIT_CORE, &rlim);
 5598     rlim.rlim_max = 0;
 5599     setrlimit(RLIMIT_CORE, &rlim);
 5600 }
 5601 #endif
 5602 
 5603 /* Add a signal handler
 5604  *
 5605  * If check needed, also check whether previous signal_handler is neither SIG_IGN nor SIG_DFL
 5606  *
 5607  * Return:
 5608  *     0: error
 5609  *     1: success
 5610  */
 5611 int SnortAddSignal(int sig, sighandler_t signal_handler, int check_needed)
 5612 {
 5613     sighandler_t pre_handler;
 5614 
 5615 #ifdef HAVE_SIGACTION
 5616     struct sigaction action;
 5617     struct sigaction old_action;
 5618     sigemptyset(&action.sa_mask);
 5619     action.sa_flags = 0;
 5620     action.sa_handler = signal_handler;
 5621     sigaction(sig, &action, &old_action);
 5622     pre_handler = old_action.sa_handler;
 5623 #else
 5624     pre_handler = signal(sig, signal_handler);
 5625 #endif
 5626     if (SIG_ERR == pre_handler)
 5627     {
 5628         SnortSnprintfAppend(signal_error_msg, STD_BUF,
 5629                 "Could not add handler for signal %d \n", sig);
 5630         return 0;
 5631     }
 5632     else if (check_needed && (SIG_IGN != pre_handler) && (SIG_DFL!= pre_handler))
 5633     {
 5634         SnortSnprintfAppend(signal_error_msg, STD_BUF,
 5635                 "WARNING: Handler is already installed for signal %d.\n", sig);
 5636     }
 5637     return 1;
 5638 }
 5639 static void InitSignals(void)
 5640 {
 5641 
 5642 #ifndef WIN32
 5643 # if defined(LINUX) || defined(FREEBSD) || defined(OPENBSD) || \
 5644      defined(SOLARIS) || defined(BSD) || defined(MACOS)
 5645     sigset_t set;
 5646 
 5647     sigemptyset(&set);
 5648 #  if defined(INLINE_FAILOPEN) || \
 5649       defined(TARGET_BASED) || defined(SNORT_RELOAD)
 5650     pthread_sigmask(SIG_SETMASK, &set, NULL);
 5651 #  else
 5652     sigprocmask(SIG_SETMASK, &set, NULL);
 5653 #  endif /* INLINE_FAILOPEN */
 5654 # else
 5655     sigsetmask(0);
 5656 # endif /* LINUX, BSD, SOLARIS */
 5657 #endif  /* !WIN32 */
 5658 
 5659     /* Make this prog behave nicely when signals come along.
 5660      * Windows doesn't like all of these signals, and will
 5661      * set errno for some.  Ignore/reset this error so it
 5662      * doesn't interfere with later checks of errno value.  */
 5663     signal_error_msg[0] = '\0';
 5664     SnortAddSignal(SIGTERM, SigExitHandler, 1);
 5665     SnortAddSignal(SIGINT, SigExitHandler, 1);
 5666 #ifndef WIN32
 5667     SnortAddSignal(SIGQUIT, SigExitHandler, 1);
 5668     SnortAddSignal(SIGNAL_SNORT_DUMP_STATS, SigDumpStatsHandler, 1);
 5669     SnortAddSignal(SIGNAL_SNORT_RELOAD, SigReloadHandler, 1);
 5670     SnortAddSignal(SIGNAL_SNORT_ROTATE_STATS, SigRotateStatsHandler, 1);
 5671 #endif
 5672 
 5673 #ifdef CONTROL_SOCKET
 5674     SnortAddSignal(SIGPIPE, SigPipeHandler, 1);
 5675 #endif
 5676 
 5677 #ifdef TARGET_BASED
 5678 #ifndef WIN32
 5679     /* Used to print warning if attribute table is not configured
 5680      * When it is, it will set new signal handler */
 5681     SnortAddSignal(SIGNAL_SNORT_READ_ATTR_TBL, SigNoAttributeTableHandler, 1);
 5682 #endif
 5683 #endif
 5684 
 5685     SnortAddSignal(SIGABRT, SigOopsHandler, 1);
 5686     SnortAddSignal(SIGSEGV, SigOopsHandler, 1);
 5687 #ifndef WIN32
 5688     SnortAddSignal(SIGBUS, SigOopsHandler, 1);
 5689 #endif
 5690 
 5691     errno = 0;
 5692 }
 5693 
 5694 static void FreeOutputConfigs(OutputConfig *head)
 5695 {
 5696     while (head != NULL)
 5697     {
 5698         OutputConfig *tmp = head;
 5699 
 5700         head = head->next;
 5701 
 5702         if (tmp->keyword != NULL)
 5703             free(tmp->keyword);
 5704 
 5705         if (tmp->opts != NULL)
 5706             free(tmp->opts);
 5707 
 5708         if (tmp->file_name != NULL)
 5709             free(tmp->file_name);
 5710 
 5711         /* Don't free listhead as it's just a pointer to the user defined
 5712          * rule's rule list node's list head */
 5713 
 5714         free(tmp);
 5715     }
 5716 }
 5717 
 5718 #ifdef SIDE_CHANNEL
 5719 static void FreeSideChannelModuleConfigs(SideChannelModuleConfig *head)
 5720 {
 5721     while (head != NULL)
 5722     {
 5723         SideChannelModuleConfig *tmp = head;
 5724 
 5725         head = head->next;
 5726 
 5727         if (tmp->keyword != NULL)
 5728             free(tmp->keyword);
 5729 
 5730         if (tmp->opts != NULL)
 5731             free(tmp->opts);
 5732 
 5733         if (tmp->file_name != NULL)
 5734             free(tmp->file_name);
 5735 
 5736         free(tmp);
 5737     }
 5738 }
 5739 #endif
 5740 
 5741 static void FreePreprocConfigs(SnortConfig *sc)
 5742 {
 5743     tSfPolicyId i;
 5744 
 5745     if (sc == NULL)
 5746         return;
 5747 
 5748     for (i = 0; i < sc->num_policies_allocated; i++)
 5749     {
 5750         SnortPolicy *p = sc->targeted_policies[i];
 5751         PreprocConfig *head;
 5752 
 5753         if (p == NULL)
 5754             continue;
 5755 
 5756         head = p->preproc_configs;
 5757 
 5758         while (head != NULL)
 5759         {
 5760             PreprocConfig *tmp = head;
 5761 
 5762             head = head->next;
 5763 
 5764             if (tmp->keyword != NULL)
 5765                 free(tmp->keyword);
 5766 
 5767             if (tmp->opts != NULL)
 5768                 free(tmp->opts);
 5769 
 5770             if (tmp->file_name != NULL)
 5771                 free(tmp->file_name);
 5772 
 5773             free(tmp);
 5774         }
 5775     }
 5776 }
 5777 
 5778 static void FreeRuleStateList(RuleState *head)
 5779 {
 5780     while (head != NULL)
 5781     {
 5782         RuleState *tmp = head;
 5783 
 5784         head = head->next;
 5785 
 5786         free(tmp);
 5787     }
 5788 }
 5789 
 5790 static void FreeClassifications(ClassType *head)
 5791 {
 5792     while (head != NULL)
 5793     {
 5794         ClassType *tmp = head;
 5795 
 5796         head = head->next;
 5797 
 5798         if (tmp->name != NULL)
 5799             free(tmp->name);
 5800 
 5801         if (tmp->type != NULL)
 5802             free(tmp->type);
 5803 
 5804         free(tmp);
 5805     }
 5806 }
 5807 
 5808 static void FreeReferences(ReferenceSystemNode *head)
 5809 {
 5810     while (head != NULL)
 5811     {
 5812         ReferenceSystemNode *tmp = head;
 5813 
 5814         head = head->next;
 5815 
 5816         if (tmp->name != NULL)
 5817             free(tmp->name);
 5818 
 5819         if (tmp->url != NULL)
 5820             free(tmp->url);
 5821 
 5822         free(tmp);
 5823     }
 5824 }
 5825 
 5826 
 5827 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
 5828 void print_pktverdict (Packet *p,uint64_t ver