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