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