Branch data Line data Source code
1 : : // $Id: main.cc 6829 2009-07-09 09:12:59Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <unistd.h>
10 : : #include <signal.h>
11 : : #ifdef HAVE_GETOPT_H
12 : : #include <getopt.h>
13 : : #endif
14 : :
15 : : #ifdef USE_IDMEF
16 : : extern "C" {
17 : : #include <libidmef/idmefxml.h>
18 : : }
19 : : #endif
20 : :
21 : : extern "C" void OPENSSL_add_all_algorithms_conf(void);
22 : :
23 : : #include "bsd-getopt-long.h"
24 : : #include "input.h"
25 : : #include "Active.h"
26 : : #include "ScriptAnaly.h"
27 : : #include "DNS_Mgr.h"
28 : : #include "Frame.h"
29 : : #include "Scope.h"
30 : : #include "Event.h"
31 : : #include "File.h"
32 : : #include "Logger.h"
33 : : #include "Net.h"
34 : : #include "NetVar.h"
35 : : #include "Var.h"
36 : : #include "Timer.h"
37 : : #include "Stmt.h"
38 : : #include "Debug.h"
39 : : #include "DFA.h"
40 : : #include "RuleMatcher.h"
41 : : #include "Anon.h"
42 : : #include "Serializer.h"
43 : : #include "RemoteSerializer.h"
44 : : #include "PersistenceSerializer.h"
45 : : #include "EventRegistry.h"
46 : : #include "Stats.h"
47 : : #include "ConnCompressor.h"
48 : : #include "DPM.h"
49 : :
50 : : #include "binpac_bro.h"
51 : :
52 : : #ifndef HAVE_STRSEP
53 : : extern "C" {
54 : : char* strsep(char**, const char*);
55 : : };
56 : : #endif
57 : :
58 : : extern "C" {
59 : : #include "setsignal.h"
60 : : };
61 : :
62 : : #ifdef USE_PERFTOOLS
63 : : HeapLeakChecker* heap_checker = 0;
64 : : int perftools_leaks = 0;
65 : : int perftools_profile = 0;
66 : : #endif
67 : :
68 : : const char* prog;
69 : : char* writefile = 0;
70 : 6 : name_list prefixes;
71 : : DNS_Mgr* dns_mgr;
72 : : TimerMgr* timer_mgr;
73 : : Logger* bro_logger;
74 : : Func* alarm_hook = 0;
75 : : Stmt* stmts;
76 : 3 : EventHandlerPtr bro_signal = 0;
77 : 3 : EventHandlerPtr net_done = 0;
78 : : RuleMatcher* rule_matcher = 0;
79 : : PersistenceSerializer* persistence_serializer = 0;
80 : : FileSerializer* event_serializer = 0;
81 : : FileSerializer* state_serializer = 0;
82 : : RemoteSerializer* remote_serializer = 0;
83 : : EventPlayer* event_player = 0;
84 : : EventRegistry* event_registry = 0;
85 : : ProfileLogger* profiling_logger = 0;
86 : : ProfileLogger* segment_logger = 0;
87 : : SampleLogger* sample_logger = 0;
88 : : int signal_val = 0;
89 : : DPM* dpm = 0;
90 : : int optimize = 0;
91 : : int do_notice_analysis = 0;
92 : : int rule_bench = 0;
93 : : int print_loaded_scripts = 0;
94 : : SecondaryPath* secondary_path = 0;
95 : : ConnCompressor* conn_compressor = 0;
96 : : extern char version[];
97 : : char* command_line_policy = 0;
98 : 6 : vector<string> params;
99 : : char* proc_status_file = 0;
100 : :
101 : : int FLAGS_use_binpac = false;
102 : :
103 : : // Keep copy of command line
104 : : int bro_argc;
105 : : char** bro_argv;
106 : :
107 : 2 : const char* bro_version()
108 : : {
109 : : #ifdef DEBUG
110 : : static char* debug_version = 0;
111 : :
112 [ + + ]: 2 : if ( ! debug_version )
113 : : {
114 : 1 : int n = strlen(version) + sizeof("-debug") + 1;
115 : 1 : debug_version = new char[n];
116 : 1 : snprintf(debug_version, n, "%s%s", version, "-debug");
117 : : }
118 : :
119 : 2 : return debug_version;
120 : : #else
121 : : return version;
122 : : #endif
123 : : }
124 : :
125 : 0 : void usage()
126 : : {
127 : 0 : fprintf(stderr, "bro version %s\n", bro_version());
128 : 0 : fprintf(stderr, "usage: %s [options] [file ...]\n", prog);
129 : 0 : fprintf(stderr, " <file> | policy file, or read stdin\n");
130 : : #ifdef ACTIVE_MAPPING
131 : : fprintf(stderr, " -a|--active-mapping <mapfile> | use active mapping results\n");
132 : : #endif
133 : 0 : fprintf(stderr, " -d|--debug-policy | activate policy file debugging\n");
134 : 0 : fprintf(stderr, " -e|--exec <bro code> | augment loaded policies by given code\n");
135 : 0 : fprintf(stderr, " -f|--filter <filter> | tcpdump filter\n");
136 : 0 : fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n");
137 : 0 : fprintf(stderr, " -h|--help|-? | command line help\n");
138 : 0 : fprintf(stderr, " -i|--iface <interface> | read from given interface\n");
139 : 0 : fprintf(stderr, " -l|--print-scripts | print all loaded scripts\n");
140 : 0 : fprintf(stderr, " -p|--prefix <prefix> | add given prefix to policy file resolution\n");
141 : 0 : fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file\n");
142 : 0 : fprintf(stderr, " -y|--flowfile <file>[=<ident>] | read from given flow file\n");
143 : 0 : fprintf(stderr, " -Y|--netflow <ip>:<prt>[=<id>] | read flow from socket\n");
144 : 0 : fprintf(stderr, " -s|--rulefile <rulefile> | read rules from given file\n");
145 : 0 : fprintf(stderr, " -t|--tracefile <tracefile> | activate execution tracing\n");
146 : 0 : fprintf(stderr, " -w|--writefile <writefile> | write to given tcpdump file\n");
147 : 0 : fprintf(stderr, " -v|--version | print version and exit\n");
148 : 0 : fprintf(stderr, " -x|--print-state <file.bst> | print contents of state file\n");
149 : 0 : fprintf(stderr, " -z|--analyze <analysis> | run the specified policy file analysis\n");
150 : 0 : fprintf(stderr, " -A|--transfile <writefile> | write transformed trace to given tcpdump file\n");
151 : : #ifdef DEBUG
152 : 0 : fprintf(stderr, " -B|--debug <dbgstreams> | Enable debugging output for selected streams\n");
153 : : #endif
154 : 0 : fprintf(stderr, " -C|--no-checksums | ignore checksums\n");
155 : 0 : fprintf(stderr, " -D|--dfa-size <size> | DFA state cache size\n");
156 : 0 : fprintf(stderr, " -F|--force-dns | force DNS\n");
157 : 0 : fprintf(stderr, " -I|--print-id <ID name> | print out given ID\n");
158 : 0 : fprintf(stderr, " -K|--md5-hashkey <hashkey> | set key for MD5-keyed hashing\n");
159 : 0 : fprintf(stderr, " -L|--rule-benchmark | benchmark for rules\n");
160 : 0 : fprintf(stderr, " -O|--optimize | optimize policy script\n");
161 : 0 : fprintf(stderr, " -P|--prime-dns | prime DNS\n");
162 : 0 : fprintf(stderr, " -R|--replay <events.bst> | replay events\n");
163 : 0 : fprintf(stderr, " -S|--debug-rules | enable rule debugging\n");
164 : 0 : fprintf(stderr, " -T|--re-level <level> | set 'RE_level' for rules\n");
165 : 0 : fprintf(stderr, " -U|--status-file <file> | Record process status in file\n");
166 : 0 : fprintf(stderr, " -W|--watchdog | activate watchdog timer\n");
167 : :
168 : : #ifdef USE_PERFTOOLS
169 : : fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n");
170 : : fprintf(stderr, " -M|--mem-profile | record heap [perftools]\n");
171 : : #endif
172 : : #if 0 // Broken
173 : : fprintf(stderr, " -X <file.bst> | print contents of state file as XML\n");
174 : : #endif
175 : 0 : fprintf(stderr, " --pseudo-realtime[=<speedup>] | enable pseudo-realtime for performance evaluation (default 1)\n");
176 : 0 : fprintf(stderr, " --load-seeds <file> | load seeds from given file\n");
177 : 0 : fprintf(stderr, " --save-seeds <file> | save seeds to given file\n");
178 : :
179 : : #ifdef USE_IDMEF
180 : : fprintf(stderr, " -n|--idmef-dtd <idmef-msg.dtd> | specify path to IDMEF DTD file\n");
181 : : #endif
182 : :
183 : 0 : fprintf(stderr, " --use-binpac | use new-style BinPAC parsers when available\n");
184 : :
185 : 0 : fprintf(stderr, " $BROPATH | file search path (%s)\n", bro_path());
186 : 0 : fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes());
187 : :
188 : 0 : exit(1);
189 : : }
190 : :
191 : 1 : void done_with_network()
192 : : {
193 : 1 : set_processing_status("TERMINATING", "done_with_network");
194 : :
195 : : // Release the port, which is important for checkpointing Bro.
196 [ + - ]: 1 : if ( remote_serializer )
197 : 1 : remote_serializer->StopListening();
198 : :
199 : : // Cancel any pending alarms (watchdog, in particular).
200 : 1 : (void) alarm(0);
201 : :
202 [ + - ]: 1 : if ( net_done )
203 : : {
204 : 1 : val_list* args = new val_list;
205 : 1 : args->append(new Val(timer_mgr->Time(), TYPE_TIME));
206 : 1 : mgr.Drain();
207 : :
208 : : // Don't propagate this event to remote clients.
209 : 1 : mgr.Dispatch(new Event(net_done, args), true);
210 : : }
211 : :
212 : : // Save state before expiring the remaining events/timers.
213 : 1 : persistence_serializer->WriteState(false);
214 : :
215 [ - + ]: 1 : if ( profiling_logger )
216 : 0 : profiling_logger->Log();
217 : :
218 : 1 : terminating = true;
219 : :
220 : 1 : dpm->Done();
221 : 1 : timer_mgr->Expire();
222 : 1 : mgr.Drain();
223 : :
224 [ + - ]: 1 : if ( remote_serializer )
225 : 1 : remote_serializer->Finish();
226 : :
227 : 1 : net_finish(1);
228 : :
229 : : #ifdef USE_PERFTOOLS
230 : :
231 : : if ( perftools_profile )
232 : : {
233 : : HeapProfilerDump("post net_run");
234 : : HeapProfilerStop();
235 : : }
236 : :
237 : : if ( heap_checker && ! heap_checker->NoLeaks() )
238 : : {
239 : : fprintf(stderr, "Memory leaks - aborting.\n");
240 : : abort();
241 : : }
242 : : #endif
243 : 1 : }
244 : :
245 : 1 : void terminate_bro()
246 : : {
247 : 1 : set_processing_status("TERMINATING", "terminate_bro");
248 : :
249 : 1 : terminating = true;
250 : :
251 : 1 : EventHandlerPtr bro_done = internal_handler("bro_done");
252 [ + - ]: 1 : if ( bro_done )
253 : 1 : mgr.QueueEvent(bro_done, new val_list);
254 : :
255 : 1 : timer_mgr->Expire();
256 : 1 : mgr.Drain();
257 : :
258 [ - + ]: 1 : if ( profiling_logger )
259 : : {
260 : : // FIXME: There are some occasional crashes in the memory
261 : : // allocation code when killing Bro. Disabling this for now.
262 [ # # ][ # # ]: 0 : if ( ! (signal_val == SIGTERM || signal_val == SIGINT) )
263 : 0 : profiling_logger->Log();
264 : :
265 [ # # ]: 0 : delete profiling_logger;
266 : : }
267 : :
268 [ + - ]: 1 : if ( remote_serializer )
269 : 1 : remote_serializer->LogStats();
270 : :
271 [ + - ]: 1 : delete timer_mgr;
272 [ + - ]: 1 : delete bro_logger;
273 [ + - ]: 1 : delete dns_mgr;
274 [ + - ]: 1 : delete persistence_serializer;
275 [ - + ]: 1 : delete event_player;
276 [ - + ]: 1 : delete event_serializer;
277 [ - + ]: 1 : delete state_serializer;
278 [ + - ]: 1 : delete event_registry;
279 [ + - ]: 1 : delete secondary_path;
280 [ + - ]: 1 : delete conn_compressor;
281 [ + - ]: 1 : delete remote_serializer;
282 [ + - ]: 1 : delete dpm;
283 : 1 : }
284 : :
285 : 0 : void termination_signal()
286 : : {
287 : 0 : set_processing_status("TERMINATING", "termination_signal");
288 : :
289 : 0 : Val sval(signal_val, TYPE_COUNT);
290 : 0 : message("received termination signal");
291 : 0 : net_get_final_stats();
292 : 0 : done_with_network();
293 : 0 : net_delete();
294 : :
295 : 0 : terminate_bro();
296 : :
297 : : // Close files after net_delete(), because net_delete()
298 : : // might write to connection content files.
299 : 0 : BroFile::CloseCachedFiles();
300 : :
301 [ # # ]: 0 : delete rule_matcher;
302 : :
303 : 0 : exit(0);
304 : : }
305 : :
306 : 0 : RETSIGTYPE sig_handler(int signo)
307 : : {
308 : 0 : set_processing_status("TERMINATING", "sig_handler");
309 : 0 : signal_val = signo;
310 : : return RETSIGVAL;
311 : : }
312 : :
313 : 3 : static void atexit_handler()
314 : : {
315 : 3 : set_processing_status("TERMINATED", "atexit");
316 : 3 : }
317 : :
318 : 0 : static void bro_new_handler()
319 : : {
320 : 0 : out_of_memory("new");
321 : 0 : }
322 : :
323 : 3 : int main(int argc, char** argv)
324 : : {
325 : 3 : bro_argc = argc;
326 : 3 : bro_argv = new char* [argc];
327 : :
328 [ + + ]: 23 : for ( int i = 0; i < argc; i++ )
329 : 20 : bro_argv[i] = copy_string(argv[i]);
330 : :
331 : 3 : name_list interfaces;
332 : 3 : name_list read_files;
333 : 3 : name_list netflows;
334 : 3 : name_list flow_files;
335 : 3 : name_list rule_files;
336 : 3 : char* transformed_writefile = 0;
337 : 3 : char* bst_file = 0;
338 : 3 : char* id_name = 0;
339 : 3 : char* events_file = 0;
340 : 3 : char* seed_load_file = 0;
341 : 3 : char* seed_save_file = 0;
342 : 3 : int seed = 0;
343 : 3 : int dump_cfg = false;
344 : 3 : int to_xml = 0;
345 : 3 : int do_watchdog = 0;
346 : 3 : int override_ignore_checksums = 0;
347 : 3 : int rule_debug = 0;
348 : 3 : int RE_level = 4;
349 : :
350 : : static struct option long_opts[] = {
351 : : {"debug-policy", no_argument, 0, 'd'},
352 : : {"dump-config", no_argument, 0, 'g'},
353 : : {"exec", required_argument, 0, 'e'},
354 : : {"filter", required_argument, 0, 'f'},
355 : : {"help", no_argument, 0, 'h'},
356 : : {"iface", required_argument, 0, 'i'},
357 : : {"print-scripts", no_argument, 0, 'l'},
358 : : {"prefix", required_argument, 0, 'p'},
359 : : {"readfile", required_argument, 0, 'r'},
360 : : {"flowfile", required_argument, 0, 'y'},
361 : : {"netflow", required_argument, 0, 'Y'},
362 : : {"rulefile", required_argument, 0, 's'},
363 : : {"tracefile", required_argument, 0, 't'},
364 : : {"writefile", required_argument, 0, 'w'},
365 : : {"version", no_argument, 0, 'v'},
366 : : {"print-state", required_argument, 0, 'x'},
367 : : {"analyze", required_argument, 0, 'z'},
368 : : {"transfile", required_argument, 0, 'A'},
369 : : {"no-checksums", no_argument, 0, 'C'},
370 : : {"dfa-cache", required_argument, 0, 'D'},
371 : : {"force-dns", no_argument, 0, 'F'},
372 : : {"load-seeds", required_argument, 0, 'G'},
373 : : {"save-seeds", required_argument, 0, 'H'},
374 : : {"set-seed", required_argument, 0, 'J'},
375 : : {"md5-hashkey", required_argument, 0, 'K'},
376 : : {"rule-benchmark", no_argument, 0, 'L'},
377 : : {"optimize", no_argument, 0, 'O'},
378 : : {"prime-dns", no_argument, 0, 'P'},
379 : : {"replay", required_argument, 0, 'R'},
380 : : {"debug-rules", no_argument, 0, 'S'},
381 : : {"re-level", required_argument, 0, 'R'},
382 : : {"watchdog", no_argument, 0, 'W'},
383 : : {"print-id", required_argument, 0, 'I'},
384 : : {"status-file", required_argument, 0, 'U'},
385 : :
386 : : #ifdef ACTIVE_MAPPING
387 : : {"active-mapping", no_argument, 0, 'a'},
388 : : #endif
389 : : #ifdef DEBUG
390 : : {"debug", required_argument, 0, 'B'},
391 : : #endif
392 : : #ifdef USE_IDMEF
393 : : {"idmef-dtd", required_argument, 0, 'n'},
394 : : #endif
395 : : #ifdef USE_PERFTOOLS
396 : : {"mem-leaks", no_argument, 0, 'm'},
397 : : {"mem-profile", no_argument, 0, 'M'},
398 : : #endif
399 : :
400 : : {"pseudo-realtime", optional_argument, 0, 'E'},
401 : :
402 : : {"use-binpac", no_argument, &FLAGS_use_binpac, 1},
403 : :
404 : : {0, 0, 0, 0},
405 : : };
406 : :
407 : 3 : enum DNS_MgrMode dns_type = DNS_DEFAULT;
408 : :
409 [ - + ]: 3 : dns_type = getenv("BRO_DNS_FAKE") ? DNS_FAKE : DNS_DEFAULT;
410 : :
411 : : RETSIGTYPE (*oldhandler)(int);
412 : :
413 : 3 : prog = argv[0];
414 : :
415 : 3 : prefixes.append(""); // "" = "no prefix"
416 : :
417 : 3 : char* p = getenv("BRO_PREFIXES");
418 [ - + ]: 3 : if ( p )
419 : 0 : add_to_name_list(p, ':', prefixes);
420 : :
421 : 3 : string active_file;
422 : :
423 : : #ifdef USE_IDMEF
424 : : string libidmef_dtd_path = "idmef-message.dtd";
425 : : #endif
426 : :
427 : : extern char* optarg;
428 : : extern int optind, opterr;
429 : :
430 : : int long_optsind;
431 : 3 : opterr = 0;
432 : :
433 : : char opts[256];
434 : : safe_strncpy(opts, "A:a:B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGHLOPSWdghlv",
435 : 3 : sizeof(opts));
436 : :
437 : : #ifdef USE_PERFTOOLS
438 : : strncat(opts, "mM", 2);
439 : : #endif
440 : :
441 : : int op;
442 [ + + ]: 8 : while ( (op = getopt_long(argc, argv, opts, long_opts, &long_optsind)) != EOF )
443 [ - - - + - : 5 : switch ( op ) {
- - - + -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - ]
444 : : case 'a':
445 : : #ifdef ACTIVE_MAPPING
446 : : fprintf(stderr, "Using active mapping file %s.\n", optarg);
447 : : active_file = optarg;
448 : : #else
449 : 0 : fprintf(stderr, "Bro not compiled for active mapping.\n");
450 : 0 : exit(1);
451 : : #endif
452 : : break;
453 : :
454 : : case 'd':
455 : 0 : fprintf(stderr, "Policy file debugging ON.\n");
456 : 0 : g_policy_debug = true;
457 : 0 : break;
458 : :
459 : : case 'e':
460 : 0 : command_line_policy = optarg;
461 : 0 : break;
462 : :
463 : : case 'f':
464 : 2 : user_pcap_filter = optarg;
465 : 2 : break;
466 : :
467 : : case 'g':
468 : 0 : dump_cfg = true;
469 : 0 : break;
470 : :
471 : : case 'i':
472 : 0 : interfaces.append(optarg);
473 : 0 : break;
474 : :
475 : : case 'l':
476 : 0 : print_loaded_scripts = 1;
477 : 0 : break;
478 : :
479 : : case 'p':
480 : 0 : prefixes.append(optarg);
481 : 0 : break;
482 : :
483 : : case 'r':
484 : 3 : read_files.append(optarg);
485 : 3 : break;
486 : :
487 : : case 's':
488 : 0 : rule_files.append(optarg);
489 : 0 : break;
490 : :
491 : : case 't':
492 : 0 : g_trace_state.SetTraceFile(optarg);
493 : 0 : g_trace_state.TraceOn();
494 : 0 : break;
495 : :
496 : : case 'w':
497 : 0 : writefile = optarg;
498 : 0 : break;
499 : :
500 : : case 'y':
501 : 0 : flow_files.append(optarg);
502 : 0 : break;
503 : :
504 : : case 'z':
505 [ # # ]: 0 : if ( streq(optarg, "notice") )
506 : 0 : do_notice_analysis = 1;
507 : : else
508 : : {
509 : 0 : fprintf(stderr, "Unknown analysis type: %s\n", optarg);
510 : 0 : exit(1);
511 : : }
512 : 0 : break;
513 : :
514 : : case 'A':
515 : 0 : transformed_writefile = optarg;
516 : 0 : break;
517 : :
518 : : case 'C':
519 : 0 : override_ignore_checksums = 1;
520 : 0 : break;
521 : :
522 : : case 'D':
523 : 0 : dfa_state_cache_size = atoi(optarg);
524 : 0 : break;
525 : :
526 : : case 'E':
527 : 0 : pseudo_realtime = 1.0;
528 [ # # ]: 0 : if ( optarg )
529 : 0 : pseudo_realtime = atof(optarg);
530 : 0 : break;
531 : :
532 : : case 'F':
533 [ # # ]: 0 : if ( dns_type != DNS_DEFAULT )
534 : 0 : usage();
535 : 0 : dns_type = DNS_FORCE;
536 : 0 : break;
537 : :
538 : : case 'G':
539 : 0 : seed_load_file = optarg;
540 : 0 : break;
541 : :
542 : : case 'H':
543 : 0 : seed_save_file = optarg;
544 : 0 : break;
545 : :
546 : : case 'I':
547 : 0 : id_name = optarg;
548 : 0 : break;
549 : :
550 : : case 'J':
551 : 0 : seed = atoi(optarg);
552 : 0 : break;
553 : :
554 : : case 'K':
555 : : hash_md5(strlen(optarg), (const u_char*) optarg,
556 : 0 : shared_hmac_md5_key);
557 : 0 : hmac_key_set = 1;
558 : 0 : break;
559 : :
560 : : case 'L':
561 : 0 : ++rule_bench;
562 : 0 : break;
563 : :
564 : : case 'O':
565 : 0 : optimize = 1;
566 : 0 : break;
567 : :
568 : : case 'P':
569 [ # # ]: 0 : if ( dns_type != DNS_DEFAULT )
570 : 0 : usage();
571 : 0 : dns_type = DNS_PRIME;
572 : 0 : break;
573 : :
574 : : case 'R':
575 : 0 : events_file = optarg;
576 : 0 : break;
577 : :
578 : : case 'S':
579 : 0 : rule_debug = 1;
580 : 0 : break;
581 : :
582 : : case 'T':
583 : 0 : RE_level = atoi(optarg);
584 : 0 : break;
585 : :
586 : : case 'U':
587 : 0 : proc_status_file = optarg;
588 : 0 : break;
589 : :
590 : : case 'W':
591 : 0 : do_watchdog = 1;
592 : 0 : break;
593 : :
594 : : case 'Y':
595 : 0 : netflows.append(optarg);
596 : 0 : break;
597 : :
598 : : case 'h':
599 : 0 : usage();
600 : 0 : break;
601 : :
602 : : case 'v':
603 : 0 : fprintf(stderr, "%s version %s\n", prog, bro_version());
604 : 0 : exit(0);
605 : : break;
606 : :
607 : : #ifdef USE_PERFTOOLS
608 : : case 'm':
609 : : perftools_leaks = 1;
610 : : break;
611 : :
612 : : case 'M':
613 : : perftools_profile = 1;
614 : : break;
615 : : #endif
616 : :
617 : : case 'x':
618 : 0 : bst_file = optarg;
619 : 0 : break;
620 : : #if 0 // broken
621 : : case 'X':
622 : : bst_file = optarg;
623 : : to_xml = 1;
624 : : break;
625 : : #endif
626 : :
627 : : #ifdef USE_IDMEF
628 : : case 'n':
629 : : fprintf(stderr, "Using IDMEF XML DTD from %s\n", optarg);
630 : : libidmef_dtd_path = optarg;
631 : : break;
632 : : #endif
633 : :
634 : : case 'B':
635 : : #ifdef DEBUG
636 : 0 : debug_logger.EnableStreams(optarg);
637 : : #endif
638 : 0 : break;
639 : :
640 : : case 0:
641 : : // This happens for long options that don't have
642 : : // a short-option equivalent.
643 : 0 : break;
644 : :
645 : : case '?':
646 : : default:
647 : 0 : usage();
648 : : break;
649 : : }
650 : :
651 : 3 : atexit(atexit_handler);
652 : 3 : set_processing_status("INITIALIZING", "main");
653 : :
654 : 3 : bro_start_time = current_time(true);
655 : :
656 : 3 : init_random_seed(seed, seed_load_file, seed_save_file);
657 : : // DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key));
658 : 3 : init_hash_function();
659 : :
660 : 3 : ERR_load_crypto_strings();
661 : 3 : OPENSSL_add_all_algorithms_conf();
662 : 3 : SSL_library_init();
663 : 3 : SSL_load_error_strings();
664 : :
665 : : // FIXME: On systems that don't provide /dev/urandom, OpenSSL doesn't
666 : : // seed the PRNG. We should do this here (but at least Linux, FreeBSD
667 : : // and Solaris provide /dev/urandom).
668 : :
669 [ + - - + ]: 3 : if ( (interfaces.length() > 0 || netflows.length() > 0) &&
[ # # ][ # # ]
[ - + ]
670 : : (read_files.length() > 0 || flow_files.length() > 0 ))
671 : 0 : usage();
672 : :
673 : : #ifdef USE_IDMEF
674 : : char* libidmef_dtd_path_cstr = new char[libidmef_dtd_path.length() + 1];
675 : : safe_strncpy(libidmef_dtd_path_cstr, libidmef_dtd_path.c_str(),
676 : : libidmef_dtd_path.length());
677 : : globalsInit(libidmef_dtd_path_cstr); // Init LIBIDMEF globals
678 : : createCurrentDoc("1.0"); // Set a global XML document
679 : : #endif
680 : :
681 : 3 : timer_mgr = new PQ_TimerMgr("<GLOBAL>");
682 : : // timer_mgr = new CQ_TimerMgr();
683 : :
684 : 3 : add_input_file("bro.init");
685 : :
686 [ - + # # ]: 3 : if ( optind == argc &&
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ]
687 : : read_files.length() == 0 && flow_files.length() == 0 &&
688 : : ! (id_name || bst_file) && ! command_line_policy )
689 : 0 : add_input_file("-");
690 : :
691 : : // Process remaining arguments. X=Y arguments indicate script
692 : : // variable/parameter assignments. The remainder are treated
693 : : // as scripts to load.
694 [ + + ]: 10 : while ( optind < argc )
695 : : {
696 [ - + ]: 7 : if ( strchr(argv[optind], '=') )
697 : 0 : params.push_back(argv[optind++]);
698 : : else
699 : 7 : add_input_file(argv[optind++]);
700 : : }
701 : :
702 [ - + ]: 3 : if ( ! load_mapping_table(active_file.c_str()) )
703 : : {
704 : : fprintf(stderr, "Could not load active mapping file %s\n",
705 : 0 : active_file.c_str());
706 : 0 : exit(1);
707 : : }
708 : :
709 : 3 : dns_mgr = new DNS_Mgr(dns_type);
710 : :
711 : : // It would nice if this were configurable. This is similar to the
712 : : // chicken and the egg problem. It would be configurable by parsing
713 : : // policy, but we can't parse policy without DNS resolution.
714 : 3 : dns_mgr->SetDir(".state");
715 : :
716 : 3 : persistence_serializer = new PersistenceSerializer();
717 : 3 : remote_serializer = new RemoteSerializer();
718 : 3 : event_registry = new EventRegistry;
719 : :
720 [ - + ]: 3 : if ( events_file )
721 : 0 : event_player = new EventPlayer(events_file);
722 : :
723 : 3 : init_event_handlers();
724 : :
725 : 3 : push_scope(0);
726 : :
727 : 3 : dpm = new DPM;
728 : 3 : dpm->PreScriptInit();
729 : :
730 : : // The leak-checker tends to produce some false
731 : : // positives (memory which had already been
732 : : // allocated before we start the checking is
733 : : // nevertheless reported; see perftools docs), thus
734 : : // we suppress some messages here.
735 : :
736 : : #ifdef USE_PERFTOOLS
737 : : {
738 : : HeapLeakChecker::Disabler disabler;
739 : : #endif
740 : :
741 : 3 : yyparse();
742 : :
743 : : #ifdef USE_PERFTOOLS
744 : : }
745 : : #endif
746 : :
747 [ - + ]: 2 : if ( nerr > 0 )
748 : : {
749 [ # # ]: 0 : delete dns_mgr;
750 : 0 : exit(1);
751 : : }
752 : :
753 : 2 : init_general_global_var();
754 : :
755 : : // Parse rule files defined on the script level.
756 : : char* script_rule_files =
757 : 2 : copy_string(internal_val("signature_files")->AsString()->CheckString());
758 : :
759 : 2 : char* tmp = script_rule_files;
760 : : char* s;
761 [ + + ]: 5 : while ( (s = strsep(&tmp, " \t")) )
762 [ + + ]: 3 : if ( *s )
763 : 2 : rule_files.append(s);
764 : :
765 [ + + ]: 2 : if ( rule_files.length() > 0 )
766 : : {
767 : 1 : rule_matcher = new RuleMatcher(RE_level);
768 [ + - ]: 1 : if ( ! rule_matcher->ReadFiles(rule_files) )
769 : : {
770 [ + - ]: 1 : delete dns_mgr;
771 : 1 : exit(1);
772 : : }
773 : :
774 [ # # ]: 0 : if ( rule_debug )
775 : 0 : rule_matcher->PrintDebug();
776 : : }
777 : :
778 [ + - ]: 1 : delete [] script_rule_files;
779 : :
780 : 1 : conn_compressor = new ConnCompressor();
781 : :
782 [ - + ]: 1 : if ( g_policy_debug )
783 : : // ### Add support for debug command file.
784 : 0 : dbg_init_debugger(0);
785 : :
786 : 1 : Val* bro_alarm_file = internal_val("bro_alarm_file");
787 : : bro_logger = new Logger("bro",
788 : : bro_alarm_file ?
789 [ - + ]: 1 : bro_alarm_file->AsFile() : new BroFile(stderr));
790 : :
791 [ - + # # ]: 1 : if ( (flow_files.length() == 0 || read_files.length() == 0) &&
[ - + ][ # # ]
[ + - ]
792 : : (netflows.length() == 0 || interfaces.length() == 0) )
793 : : {
794 : 1 : Val* interfaces_val = internal_val("interfaces");
795 [ + - ]: 1 : if ( interfaces_val )
796 : : {
797 : : char* interfaces_str =
798 : 1 : interfaces_val->AsString()->Render();
799 : :
800 [ - + ]: 1 : if ( interfaces_str[0] != '\0' )
801 : 0 : add_to_name_list(interfaces_str, ' ', interfaces);
802 : :
803 [ + - ]: 1 : delete [] interfaces_str;
804 : : }
805 : : }
806 : :
807 : : // Initialize the secondary path, if it's needed.
808 : 1 : secondary_path = new SecondaryPath();
809 : :
810 [ + - ]: 1 : if ( dns_type != DNS_PRIME )
811 : : net_init(interfaces, read_files, netflows, flow_files,
812 : : writefile, transformed_writefile,
813 : : user_pcap_filter ? user_pcap_filter : "tcp or udp",
814 [ + - ]: 1 : secondary_path->Filter(), do_watchdog);
815 : :
816 [ - + ]: 1 : if ( ! reading_traces )
817 : : // Only enable actual syslog'ing for live input.
818 : 0 : bro_logger->SetEnabled(enable_syslog);
819 : : else
820 : 1 : bro_logger->SetEnabled(0);
821 : :
822 : 1 : BroFile::SetDefaultRotation(log_rotate_interval, log_max_size);
823 : :
824 : 1 : alarm_hook = internal_func("alarm_hook");
825 : 1 : bro_signal = internal_handler("bro_signal");
826 : 1 : net_done = internal_handler("net_done");
827 : :
828 [ + - ]: 1 : if ( ! g_policy_debug )
829 : : {
830 : 1 : (void) setsignal(SIGTERM, sig_handler);
831 : 1 : (void) setsignal(SIGINT, sig_handler);
832 : 1 : (void) setsignal(SIGPIPE, SIG_IGN);
833 : : }
834 : :
835 : : // Cooperate with nohup(1).
836 [ - + ]: 1 : if ( (oldhandler = setsignal(SIGHUP, sig_handler)) != SIG_DFL )
837 : 0 : (void) setsignal(SIGHUP, oldhandler);
838 : :
839 [ - + ]: 1 : if ( dns_type == DNS_PRIME )
840 : : {
841 : 0 : dns_mgr->Verify();
842 : 0 : dns_mgr->Resolve();
843 : :
844 [ # # ]: 0 : if ( ! dns_mgr->Save() )
845 : : {
846 : 0 : bro_logger->Log("**Can't update DNS cache");
847 : 0 : exit(1);
848 : : }
849 : :
850 : 0 : mgr.Drain();
851 [ # # ]: 0 : delete dns_mgr;
852 : 0 : exit(0);
853 : : }
854 : :
855 : : // Just read state file from disk.
856 [ - + ]: 1 : if ( bst_file )
857 : : {
858 [ # # ]: 0 : if ( to_xml )
859 : : {
860 : : BinarySerializationFormat* b =
861 : 0 : new BinarySerializationFormat();
862 : 0 : XMLSerializationFormat* x = new XMLSerializationFormat();
863 : 0 : ConversionSerializer s(b, x);
864 : 0 : s.Convert(bst_file, "/dev/stdout");
865 : : }
866 : : else
867 : : {
868 : 0 : FileSerializer s;
869 : 0 : UnserialInfo info(&s);
870 : 0 : info.print = stdout;
871 : 0 : info.install_uniques = true;
872 : 0 : s.Read(&info, bst_file);
873 : : }
874 : :
875 : 0 : exit(0);
876 : : }
877 : :
878 [ - + ]: 1 : if ( using_communication )
879 : 0 : remote_serializer->Init();
880 : :
881 : 1 : persistence_serializer->SetDir((const char *)state_dir->AsString()->CheckString());
882 : :
883 : : // Print the ID.
884 [ - + ]: 1 : if ( id_name )
885 : : {
886 : 0 : persistence_serializer->ReadAll(true, false);
887 : :
888 : 0 : ID* id = global_scope()->Lookup(id_name);
889 [ # # ]: 0 : if ( ! id )
890 : : {
891 : 0 : fprintf(stderr, "No such ID: %s\n", id_name);
892 : 0 : exit(1);
893 : : }
894 : :
895 : 0 : ODesc desc;
896 : 0 : desc.SetQuotes(true);
897 : 0 : desc.SetIncludeStats(true);
898 : 0 : id->DescribeExtended(&desc);
899 : :
900 : 0 : fprintf(stdout, "%s\n", desc.Description());
901 : 0 : exit(0);
902 : : }
903 : :
904 : 1 : persistence_serializer->ReadAll(true, true);
905 : :
906 [ - + ]: 1 : if ( dump_cfg )
907 : : {
908 : 0 : persistence_serializer->WriteConfig(false);
909 : 0 : exit(0);
910 : : }
911 : :
912 [ - + ]: 1 : if ( profiling_interval > 0 )
913 : : {
914 : : profiling_logger = new ProfileLogger(profiling_file->AsFile(),
915 : 0 : profiling_interval);
916 : :
917 [ # # ]: 0 : if ( segment_profiling )
918 : 0 : segment_logger = profiling_logger;
919 : : }
920 : :
921 [ + - ][ - + ]: 1 : if ( ! reading_live && ! reading_traces )
922 : : // Set up network_time to track real-time, since
923 : : // we don't have any other source for it.
924 : 0 : network_time = current_time();
925 : :
926 : 1 : EventHandlerPtr bro_init = internal_handler("bro_init");
927 [ + - ]: 1 : if ( bro_init ) //### this should be a function
928 : 1 : mgr.QueueEvent(bro_init, new val_list);
929 : :
930 : : EventRegistry::string_list* dead_handlers =
931 : 1 : event_registry->UnusedHandlers();
932 : :
933 [ + - - + ]: 1 : if ( dead_handlers->length() > 0 && check_for_unused_event_handlers )
[ - + ]
934 : : {
935 : 0 : warn("event handlers never invoked:");
936 [ # # ]: 0 : for ( int i = 0; i < dead_handlers->length(); ++i )
937 : 0 : warn("\t", (*dead_handlers)[i]);
938 : : }
939 : :
940 [ + - ]: 1 : delete dead_handlers;
941 : :
942 : : EventRegistry::string_list* alive_handlers =
943 : 1 : event_registry->UsedHandlers();
944 : :
945 [ + - - + ]: 1 : if ( alive_handlers->length() > 0 && dump_used_event_handlers )
[ - + ]
946 : : {
947 : 0 : message("invoked event handlers:");
948 [ # # ]: 0 : for ( int i = 0; i < alive_handlers->length(); ++i )
949 : 0 : message((*alive_handlers)[i]);
950 : : }
951 : :
952 [ + - ]: 1 : delete alive_handlers;
953 : :
954 [ - + ]: 1 : if ( do_notice_analysis )
955 : 0 : notice_analysis();
956 : :
957 [ + - ]: 1 : if ( stmts )
958 : : {
959 : : stmt_flow_type flow;
960 : 1 : Frame f(current_scope()->Length(), 0, 0);
961 : 1 : g_frame_stack.push_back(&f);
962 : 1 : stmts->Exec(&f, flow);
963 : 1 : g_frame_stack.pop_back();
964 : : }
965 : :
966 [ - + ]: 1 : if ( override_ignore_checksums )
967 : 0 : ignore_checksums = 1;
968 : :
969 : 1 : dpm->PostScriptInit();
970 : :
971 : 1 : mgr.Drain();
972 : :
973 [ - + # # ]: 1 : have_pending_timers = ! reading_traces && timer_mgr->Size() > 0;
974 : :
975 [ - + ][ # # ]: 1 : if ( io_sources.Size() > 0 || have_pending_timers )
[ + - ]
976 : : {
977 [ - + ]: 1 : if ( profiling_logger )
978 : 0 : profiling_logger->Log();
979 : :
980 : : #ifdef USE_PERFTOOLS
981 : : if ( perftools_leaks )
982 : : heap_checker = new HeapLeakChecker("net_run");
983 : :
984 : : if ( perftools_profile )
985 : : {
986 : : HeapProfilerStart("heap");
987 : : HeapProfilerDump("pre net_run");
988 : : }
989 : :
990 : : #endif
991 : 1 : net_run();
992 : 1 : done_with_network();
993 : 1 : net_delete();
994 : :
995 : 1 : terminate_bro();
996 : :
997 : : // Close files after net_delete(), because net_delete()
998 : : // might write to connection content files.
999 : 1 : BroFile::CloseCachedFiles();
1000 : : }
1001 : : else
1002 : : {
1003 : 0 : persistence_serializer->WriteState(false);
1004 : 0 : terminate_bro();
1005 : : }
1006 : :
1007 [ - + ]: 1 : delete rule_matcher;
1008 : :
1009 : 1 : return 0;
1010 [ + - ][ + - ]: 6 : }
|