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