Branch data Line data Source code
1 : : // $Id: Net.cc 6915 2009-09-22 05:04:17Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <sys/types.h>
8 : : #ifdef TIME_WITH_SYS_TIME
9 : : # include <sys/time.h>
10 : : # include <time.h>
11 : : #else
12 : : # ifdef HAVE_SYS_TIME_H
13 : : # include <sys/time.h>
14 : : # else
15 : : # include <time.h>
16 : : # endif
17 : : #endif
18 : :
19 : : #include <errno.h>
20 : : #include <signal.h>
21 : : #include <stdlib.h>
22 : : #include <unistd.h>
23 : :
24 : : #include "NetVar.h"
25 : : #include "Sessions.h"
26 : : #include "Event.h"
27 : : #include "Timer.h"
28 : : #include "Var.h"
29 : : #include "Logger.h"
30 : : #include "Net.h"
31 : : #include "TCP_Rewriter.h"
32 : : #include "Anon.h"
33 : : #include "PacketSort.h"
34 : : #include "Serializer.h"
35 : : #include "PacketDumper.h"
36 : :
37 : : extern "C" {
38 : : #include "setsignal.h"
39 : : };
40 : :
41 : : extern "C" {
42 : : extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
43 : : }
44 : :
45 : 6 : PList(PktSrc) pkt_srcs;
46 : :
47 : : // FIXME: We should really merge PktDumper and PacketDumper.
48 : : // It's on my to-do [Robin].
49 : : PktDumper* pkt_dumper = 0;
50 : : PktDumper* pkt_transformed_dumper = 0;
51 : :
52 : : // For trace of rewritten packets
53 : : PacketDumper* transformed_pkt_dump = 0;
54 : : // For trace of original packets from selected connections
55 : : PacketDumper* source_pkt_dump = 0;
56 : : int transformed_pkt_dump_MTU = 1514;
57 : :
58 : : int reading_live = 0;
59 : : int reading_traces = 0;
60 : : int have_pending_timers = 0;
61 : : double pseudo_realtime = 0.0;
62 : : char* user_pcap_filter = 0;
63 : : bool using_communication = false;
64 : :
65 : : double network_time = 0.0; // time according to last packet timestamp
66 : : // (or current time)
67 : : double processing_start_time = 0.0; // time started working on current pkt
68 : : double bro_start_time = 0.0; // time Bro started.
69 : : double bro_start_network_time; // timestamp of first packet
70 : : double last_watchdog_proc_time = 0.0; // value of above during last watchdog
71 : : bool terminating = false; // whether we're done reading and finishing up
72 : :
73 : : PacketSortGlobalPQ* packet_sorter = 0;
74 : :
75 : : const struct pcap_pkthdr* current_hdr = 0;
76 : : const u_char* current_pkt = 0;
77 : : int current_dispatched = 0;
78 : : int current_hdr_size = 0;
79 : : double current_timestamp = 0.0;
80 : : PktSrc* current_pktsrc = 0;
81 : : IOSource* current_iosrc;
82 : :
83 : :
84 : 0 : RETSIGTYPE watchdog(int /* signo */)
85 : : {
86 [ # # ]: 0 : if ( processing_start_time != 0.0 )
87 : : {
88 : : // The signal arrived while we're processing a packet and/or
89 : : // its corresponding event queue. Check whether we've been
90 : : // spending too much time, which we take to mean we've wedged.
91 : :
92 : : // Note that it's subtle how exactly to test this. In
93 : : // processing_start_time we have the timestamp of the packet
94 : : // we're currently working on. But that *doesn't* mean that
95 : : // we began work on the packet at that time; we could have
96 : : // begun at a much later time, depending on how long the
97 : : // packet filter waited (to fill its buffer) before handing
98 : : // up this packet. So what we require is that the current
99 : : // processing_start_time matches the processing_start_time we
100 : : // observed last time the watchdog went off. If so, then
101 : : // we've been working on the current packet for at least
102 : : // watchdog_interval seconds.
103 : :
104 [ # # ]: 0 : if ( processing_start_time == last_watchdog_proc_time )
105 : : {
106 : : // snprintf() calls alloc/free routines if you use %f!
107 : : // We need to avoid doing that given we're in a single
108 : : // handler and the allocation routines are not
109 : : // reentrant.
110 : :
111 : 0 : double ct = current_time();
112 : :
113 : 0 : int int_ct = int(ct);
114 : 0 : int frac_ct = int((ct - int_ct) * 1e6);
115 : :
116 : 0 : int int_pst = int(processing_start_time);
117 : : int frac_pst =
118 : 0 : int((processing_start_time - int_pst) * 1e6);
119 : :
120 : : char msg[512];
121 : : safe_snprintf(msg, sizeof(msg),
122 : : "**watchdog timer expired, t = %d.%06d, start = %d.%06d, dispatched = %d",
123 : : int_ct, frac_ct, int_pst, frac_pst,
124 : 0 : current_dispatched);
125 : :
126 : 0 : bro_logger->Log(msg);
127 : 0 : run_time("watchdog timer expired");
128 : :
129 [ # # ]: 0 : if ( current_hdr )
130 : : {
131 [ # # ]: 0 : if ( ! pkt_dumper )
132 : : {
133 : : // We aren't dumping packets; however,
134 : : // saving the packet which caused the
135 : : // watchdog to trigger may be helpful,
136 : : // so we'll save that one nevertheless.
137 : 0 : pkt_dumper = new PktDumper("watchdog-pkt.pcap");
138 [ # # ]: 0 : if ( pkt_dumper->IsError() )
139 : : {
140 : 0 : fprintf(stderr, "watchdog: can't open watchdog-pkt.pcap for writing\n");
141 : 0 : pkt_dumper = 0;
142 : : }
143 : : }
144 : :
145 [ # # ]: 0 : if ( pkt_dumper )
146 : 0 : pkt_dumper->Dump(current_hdr, current_pkt);
147 : : }
148 : :
149 : 0 : net_get_final_stats();
150 : 0 : net_finish(0);
151 : :
152 : 0 : abort();
153 : : exit(1);
154 : : }
155 : : }
156 : :
157 : 0 : last_watchdog_proc_time = processing_start_time;
158 : :
159 : 0 : (void) alarm(watchdog_interval);
160 : : return RETSIGVAL;
161 : : }
162 : :
163 : : void net_init(name_list& interfaces, name_list& readfiles,
164 : : name_list& netflows, name_list& flowfiles,
165 : : const char* writefile, const char* transformed_writefile,
166 : : const char* filter, const char* secondary_filter,
167 : 1 : int do_watchdog)
168 : : {
169 : 1 : init_net_var();
170 : :
171 [ - + # # ]: 1 : if ( readfiles.length() > 0 || flowfiles.length() > 0 )
[ + - ]
172 : : {
173 : 1 : reading_live = pseudo_realtime > 0.0;
174 : 1 : reading_traces = 1;
175 : :
176 [ + + ]: 2 : for ( int i = 0; i < readfiles.length(); ++i )
177 : : {
178 : 1 : PktFileSrc* ps = new PktFileSrc(readfiles[i], filter);
179 : :
180 [ - + ]: 1 : if ( ! ps->IsOpen() )
181 : : {
182 : : fprintf(stderr, "%s: problem with trace file %s - %s\n",
183 : 0 : prog, readfiles[i], ps->ErrorMsg());
184 : 0 : exit(1);
185 : : }
186 : : else
187 : : {
188 : 1 : pkt_srcs.append(ps);
189 : 1 : io_sources.Register(ps);
190 : : }
191 : :
192 [ - + ]: 1 : if ( secondary_filter )
193 : : {
194 : : // We use a second PktFileSrc for the
195 : : // secondary path.
196 : : PktFileSrc* ps = new PktFileSrc(readfiles[i],
197 : : secondary_filter,
198 : 0 : TYPE_FILTER_SECONDARY);
199 : :
200 [ # # ]: 0 : if ( ! ps->IsOpen() )
201 : : {
202 : : fprintf(stderr, "%s: problem with trace file %s - %s\n",
203 : : prog, readfiles[i],
204 : 0 : ps->ErrorMsg());
205 : 0 : exit(1);
206 : : }
207 : : else
208 : : {
209 : 0 : pkt_srcs.append(ps);
210 : 0 : io_sources.Register(ps);
211 : : }
212 : :
213 : 0 : ps->AddSecondaryTablePrograms();
214 : : }
215 : : }
216 : :
217 [ - + ]: 1 : for ( int i = 0; i < flowfiles.length(); ++i )
218 : : {
219 : 0 : FlowFileSrc* fs = new FlowFileSrc(flowfiles[i]);
220 : :
221 [ # # ]: 0 : if ( ! fs->IsOpen() )
222 : : {
223 : : fprintf(stderr, "%s: problem with netflow file %s - %s\n",
224 : 0 : prog, flowfiles[i], fs->ErrorMsg());
225 : 0 : exit(1);
226 : : }
227 : : else
228 : : {
229 : 0 : io_sources.Register(fs);
230 : : }
231 : : }
232 : : }
233 : :
234 [ # # ][ # # ]: 0 : else if ((interfaces.length() > 0 || netflows.length() > 0))
[ # # ]
235 : : {
236 : 0 : reading_live = 1;
237 : 0 : reading_traces = 0;
238 : :
239 [ # # ]: 0 : for ( int i = 0; i < interfaces.length(); ++i )
240 : : {
241 : : PktSrc* ps;
242 : 0 : ps = new PktInterfaceSrc(interfaces[i], filter);
243 : :
244 [ # # ]: 0 : if ( ! ps->IsOpen() )
245 : : {
246 : : fprintf(stderr, "%s: problem with interface %s - %s\n",
247 : 0 : prog, interfaces[i], ps->ErrorMsg());
248 : 0 : exit(1);
249 : : }
250 : : else
251 : : {
252 : 0 : pkt_srcs.append(ps);
253 : 0 : io_sources.Register(ps);
254 : : }
255 : :
256 [ # # ]: 0 : if ( secondary_filter )
257 : : {
258 : : PktSrc* ps;
259 : : ps = new PktInterfaceSrc(interfaces[i],
260 : 0 : filter, TYPE_FILTER_SECONDARY);
261 : :
262 [ # # ]: 0 : if ( ! ps->IsOpen() )
263 : : {
264 : : fprintf(stderr, "%s: problem with interface %s - %s\n",
265 : : prog, interfaces[i],
266 : 0 : ps->ErrorMsg());
267 : 0 : exit(1);
268 : : }
269 : : else
270 : : {
271 : 0 : pkt_srcs.append(ps);
272 : 0 : io_sources.Register(ps);
273 : : }
274 : :
275 : 0 : ps->AddSecondaryTablePrograms();
276 : : }
277 : : }
278 : :
279 [ # # ]: 0 : for ( int i = 0; i < netflows.length(); ++i )
280 : : {
281 : 0 : FlowSocketSrc* fs = new FlowSocketSrc(netflows[i]);
282 : :
283 [ # # ]: 0 : if ( ! fs->IsOpen() )
284 : : {
285 : : fprintf(stderr, "%s: problem with netflow socket %s - %s\n",
286 : 0 : prog, netflows[i], fs->ErrorMsg());
287 : 0 : exit(1);
288 : : }
289 : : else
290 : : {
291 : 0 : io_sources.Register(fs);
292 : : }
293 : : }
294 : :
295 : : }
296 : :
297 : : else
298 : : // have_pending_timers = 1, possibly. We don't set
299 : : // that here, though, because at this point we don't know
300 : : // whether the user's bro_init() event will indeed set
301 : : // a timer.
302 : 0 : reading_traces = reading_live = 0;
303 : :
304 [ - + ]: 1 : if ( writefile )
305 : : {
306 : : // ### This will fail horribly if there are multiple
307 : : // interfaces with different-lengthed media.
308 : 0 : pkt_dumper = new PktDumper(writefile);
309 [ # # ]: 0 : if ( pkt_dumper->IsError() )
310 : : {
311 : : fprintf(stderr, "%s: can't open write file \"%s\" - %s\n",
312 : 0 : prog, writefile, pkt_dumper->ErrorMsg());
313 : 0 : exit(1);
314 : : }
315 : :
316 : 0 : ID* id = global_scope()->Lookup("trace_output_file");
317 [ # # ]: 0 : if ( ! id )
318 : 0 : run_time("trace_output_file not defined in bro.init");
319 : : else
320 : 0 : id->SetVal(new StringVal(writefile));
321 : : }
322 : :
323 [ - + ]: 1 : if ( transformed_writefile )
324 : : {
325 : 0 : pkt_transformed_dumper = new PktDumper(transformed_writefile);
326 [ # # ]: 0 : if ( pkt_transformed_dumper->IsError() )
327 : : {
328 : : fprintf(stderr, "%s: can't open trace transformation write file \"%s\" - %s\n",
329 : : prog, writefile,
330 : 0 : pkt_transformed_dumper->ErrorMsg());
331 : 0 : exit(1);
332 : : }
333 : :
334 : : transformed_pkt_dump =
335 : 0 : new PacketDumper(pkt_transformed_dumper->PcapDumper());
336 : :
337 : : // If both -A and -w are specified, -A will be the transformed
338 : : // trace file and -w will be the source packet trace file.
339 : : // Otherwise the packets will go to the same file.
340 [ # # ]: 0 : if ( pkt_dumper )
341 : : source_pkt_dump =
342 : 0 : new PacketDumper(pkt_dumper->PcapDumper());
343 : : }
344 : :
345 [ - + ]: 1 : else if ( pkt_dumper )
346 : : transformed_pkt_dump =
347 : 0 : new PacketDumper(pkt_dumper->PcapDumper());
348 : :
349 [ - + ]: 1 : if ( anonymize_ip_addr )
350 : 0 : init_ip_addr_anonymizers();
351 : : else
352 [ + + ]: 6 : for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i )
353 : 5 : ip_anonymizer[i] = 0;
354 : :
355 [ - + ]: 1 : if ( packet_sort_window > 0 )
356 : 0 : packet_sorter = new PacketSortGlobalPQ();
357 : :
358 : 1 : sessions = new NetSessions();
359 : :
360 [ - + ]: 1 : if ( do_watchdog )
361 : : {
362 : : // Set up the watchdog to make sure we don't wedge.
363 : 0 : (void) setsignal(SIGALRM, watchdog);
364 : 0 : (void) alarm(watchdog_interval);
365 : : }
366 : 1 : }
367 : :
368 : 21347 : void expire_timers(PktSrc* src_ps)
369 : : {
370 : 21347 : SegmentProfiler(segment_logger, "expiring-timers");
371 : : TimerMgr* tmgr =
372 : : src_ps ? sessions->LookupTimerMgr(src_ps->GetCurrentTag())
373 [ + - ]: 21347 : : timer_mgr;
374 : :
375 : : current_dispatched +=
376 : : tmgr->Advance(network_time,
377 : 21347 : max_timer_expires - current_dispatched);
378 : 21347 : }
379 : :
380 : : void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr,
381 : : const u_char* pkt, int hdr_size,
382 : 21347 : PktSrc* src_ps, PacketSortElement* pkt_elem)
383 : : {
384 [ + + ]: 21347 : if ( ! bro_start_network_time )
385 : 1 : bro_start_network_time = t;
386 : :
387 : : TimerMgr* tmgr =
388 : : src_ps ? sessions->LookupTimerMgr(src_ps->GetCurrentTag())
389 [ + - ]: 21347 : : timer_mgr;
390 : :
391 : : // network_time never goes back.
392 [ + + ]: 21347 : network_time = tmgr->Time() < t ? t : tmgr->Time();
393 : :
394 : 21347 : current_pktsrc = src_ps;
395 : 21347 : current_iosrc = src_ps;
396 : 21347 : processing_start_time = t;
397 : :
398 : 21347 : expire_timers(src_ps);
399 : :
400 : 21347 : SegmentProfiler* sp = 0;
401 : :
402 [ - + ]: 21347 : if ( load_sample )
403 : : {
404 : : static uint32 load_freq = 0;
405 : :
406 [ # # ]: 0 : if ( load_freq == 0 )
407 : 0 : load_freq = uint32(0xffffffff) / uint32(load_sample_freq);
408 : :
409 [ # # ]: 0 : if ( uint32(random() & 0xffffffff) < load_freq )
410 : : {
411 : : // Drain the queued timer events so they're not
412 : : // charged against this sample.
413 : 0 : mgr.Drain();
414 : :
415 : 0 : sample_logger = new SampleLogger();
416 : 0 : sp = new SegmentProfiler(sample_logger, "load-samp");
417 : : }
418 : : }
419 : :
420 : 21347 : sessions->DispatchPacket(t, hdr, pkt, hdr_size, src_ps, pkt_elem);
421 : 21347 : mgr.Drain();
422 : :
423 [ - + ]: 21347 : if ( sp )
424 : : {
425 [ # # ]: 0 : delete sp;
426 [ # # ]: 0 : delete sample_logger;
427 : 0 : sample_logger = 0;
428 : : }
429 : :
430 : 21347 : processing_start_time = 0.0; // = "we're not processing now"
431 : 21347 : current_dispatched = 0;
432 : 21347 : current_iosrc = 0;
433 : 21347 : current_pktsrc = 0;
434 : 21347 : }
435 : :
436 : 0 : int process_packet_sorter(double latest_packet_time)
437 : : {
438 [ # # ]: 0 : if ( ! packet_sorter )
439 : 0 : return 0;
440 : :
441 : 0 : double min_t = latest_packet_time - packet_sort_window;
442 : :
443 : 0 : int num_pkts_dispatched = 0;
444 : : PacketSortElement* pkt_elem;
445 : :
446 : : // Dispatch packets in the packet_sorter until timestamp min_t.
447 : : // It's possible that zero or multiple packets are dispatched.
448 [ # # ]: 0 : while ( (pkt_elem = packet_sorter->RemoveMin(min_t)) != 0 )
449 : : {
450 : : net_packet_dispatch(pkt_elem->TimeStamp(),
451 : : pkt_elem->Hdr(), pkt_elem->Pkt(),
452 : : pkt_elem->HdrSize(), pkt_elem->Src(),
453 : 0 : pkt_elem);
454 : 0 : ++num_pkts_dispatched;
455 [ # # ]: 0 : delete pkt_elem;
456 : : }
457 : :
458 : 0 : return num_pkts_dispatched;
459 : : }
460 : :
461 : : void net_packet_arrival(double t, const struct pcap_pkthdr* hdr,
462 : : const u_char* pkt, int hdr_size,
463 : 21347 : PktSrc* src_ps)
464 : : {
465 [ - + ]: 21347 : if ( packet_sorter )
466 : : {
467 : : // Note that when we enable packet sorter, there will
468 : : // be a small window between the time packet arrives
469 : : // to Bro and when it is processed ("dispatched"). We
470 : : // define network_time to be the latest timestamp for
471 : : // packets *dispatched* so far (usually that's the
472 : : // timestamp of the current packet).
473 : :
474 : : // Add the packet to the packet_sorter.
475 : : packet_sorter->Add(
476 : 0 : new PacketSortElement(src_ps, t, hdr, pkt, hdr_size));
477 : :
478 : : // Do we have any packets to dispatch from packet_sorter?
479 : 0 : process_packet_sorter(t);
480 : : }
481 : : else
482 : : // Otherwise we dispatch the packet immediately
483 : 21347 : net_packet_dispatch(t, hdr, pkt, hdr_size, src_ps, 0);
484 : 21347 : }
485 : :
486 : 1 : void net_run()
487 : : {
488 : 1 : set_processing_status("RUNNING", "net_run");
489 : :
490 [ + + ][ - + ]: 21350 : while ( io_sources.Size() ||
[ # # ][ + + ]
491 : : (packet_sorter && ! packet_sorter->Empty()) )
492 : : {
493 : : double ts;
494 : 21349 : IOSource* src = io_sources.FindSoonest(&ts);
495 : :
496 : : #ifdef DEBUG
497 : : static int loop_counter = 0;
498 : :
499 : : // If no source is ready, we log only every 100th cycle,
500 : : // starting with the first.
501 [ + + + + ]: 21349 : if ( src || loop_counter++ % 100 == 0 )
[ + + ]
502 : : {
503 [ + + ][ + + ]: 21348 : DBG_LOG(DBG_MAINLOOP, "realtime=%.6f iosrc=%s ts=%.6f",
504 : : current_time(), src ? src->Tag() : "<all dry>", src ? ts : -1);
505 : :
506 [ + + ]: 21348 : if ( src )
507 : 21347 : loop_counter = 0;
508 : : }
509 : : #endif
510 : 21349 : current_iosrc = src;
511 : :
512 [ + + ]: 21349 : if ( src )
513 : 21347 : src->Process(); // which will call net_packet_arrival()
514 : :
515 [ - + ][ # # ]: 2 : else if ( reading_live && ! pseudo_realtime)
516 : : { // live but no source is currently active
517 : 0 : double ct = current_time();
518 [ # # # # ]: 0 : if ( packet_sorter && ! packet_sorter->Empty() )
[ # # ]
519 : 0 : process_packet_sorter(ct);
520 [ # # ]: 0 : else if ( ! net_is_processing_suspended() )
521 : : {
522 : : // Take advantage of the lull to get up to
523 : : // date on timers and events.
524 : 0 : network_time = ct;
525 : 0 : expire_timers();
526 : : }
527 : : }
528 : :
529 [ - + ][ # # ]: 2 : else if ( packet_sorter && ! packet_sorter->Empty() )
[ - + ]
530 : : {
531 : : // We are no longer reading live; done with all the
532 : : // sources.
533 : : // Drain packets remaining in the packet sorter.
534 : : process_packet_sorter(
535 : 0 : network_time + packet_sort_window + 1000000);
536 : : }
537 : :
538 [ + - ][ - + ]: 2 : else if ( (have_pending_timers || using_communication) &&
[ # # ]
539 : : ! pseudo_realtime )
540 : : {
541 : : // Take advantage of the lull to get up to
542 : : // date on timers and events. Because we only
543 : : // have timers as sources, going to sleep here
544 : : // doesn't risk blocking on other inputs.
545 : 0 : network_time = current_time();
546 : 0 : expire_timers();
547 : :
548 : : // Avoid busy-waiting - pause for 100 ms.
549 : : // We pick a sleep value of 100 msec that buys
550 : : // us a lot of idle time, but doesn't delay near-term
551 : : // timers too much. (Delaying them somewhat is okay,
552 : : // since Bro timers are not high-precision anyway.)
553 [ # # ]: 0 : if ( ! using_communication )
554 : 0 : usleep(100000);
555 : :
556 : : // Flawfinder says about usleep:
557 : : //
558 : : // This C routine is considered obsolete (as opposed
559 : : // to the shell command by the same name). The
560 : : // interaction of this function with SIGALRM and
561 : : // other timer functions such as sleep(), alarm(),
562 : : // setitimer(), and nanosleep() is unspecified.
563 : : // Use nanosleep(2) or setitimer(2) instead.
564 : : }
565 : :
566 : 21349 : mgr.Drain();
567 : :
568 : 21349 : processing_start_time = 0.0; // = "we're not processing now"
569 : 21349 : current_dispatched = 0;
570 : 21349 : current_iosrc = 0;
571 : :
572 : : // Should we put the signal handling into an IOSource?
573 : : extern void termination_signal();
574 : :
575 [ + - - + ]: 21349 : if ( signal_val == SIGTERM || signal_val == SIGINT )
576 : : // We received a signal while processing the
577 : : // current packet and its related events.
578 : 0 : termination_signal();
579 : :
580 : : #ifdef DEBUG_COMMUNICATION
581 : : if ( signal_val == SIGPROF && remote_serializer )
582 : : remote_serializer->DumpDebugData();
583 : : #endif
584 : :
585 [ - + ]: 21349 : if ( ! reading_traces )
586 : : // Check whether we have timers scheduled for
587 : : // the future on which we need to wait.
588 : 0 : have_pending_timers = timer_mgr->Size() > 0;
589 : : }
590 : :
591 : : // Get the final statistics now, and not when net_finish() is
592 : : // called, since that might happen quite a bit in the future
593 : : // due to expiring pending timers, and we don't want to ding
594 : : // for any packets dropped beyond this point.
595 : 1 : net_get_final_stats();
596 : 1 : }
597 : :
598 : 1 : void net_get_final_stats()
599 : : {
600 [ + + ]: 2 : loop_over_list(pkt_srcs, i)
601 : : {
602 : 1 : PktSrc* ps = pkt_srcs[i];
603 : :
604 [ - + ]: 1 : if ( ps->IsLive() )
605 : : {
606 : : struct PktSrc::Stats s;
607 : 0 : ps->Statistics(&s);
608 : : fprintf(stderr, "%d packets received on interface %s, %d dropped\n",
609 : 0 : s.received, ps->Interface(), s.dropped);
610 : : }
611 : : }
612 : 1 : }
613 : :
614 : 1 : void net_finish(int drain_events)
615 : : {
616 : 1 : set_processing_status("TERMINATING", "net_finish");
617 : :
618 [ + - ]: 1 : if ( drain_events )
619 : : {
620 [ + - ]: 1 : if ( sessions )
621 : 1 : sessions->Drain();
622 : :
623 : 1 : mgr.Drain();
624 : :
625 [ + - ]: 1 : if ( sessions )
626 : 1 : sessions->Done();
627 : : }
628 : :
629 [ - + ]: 1 : delete pkt_dumper;
630 [ - + ]: 1 : delete pkt_transformed_dumper;
631 : :
632 : : // fprintf(stderr, "uhash: %d/%d\n", hash_cnt_uhash, hash_cnt_all);
633 : :
634 : : #ifdef DEBUG
635 : : extern int reassem_seen_bytes, reassem_copied_bytes;
636 : : // DEBUG_MSG("Reassembly (TCP and IP/Frag): %d bytes seen, %d bytes copied\n",
637 : : // reassem_seen_bytes, reassem_copied_bytes);
638 : :
639 : : extern int num_packets_held, num_packets_cleaned;
640 : : // DEBUG_MSG("packets clean up: %d/%d\n", num_packets_cleaned, num_packets_held);
641 : : #endif
642 : 1 : }
643 : :
644 : 1 : void net_delete()
645 : : {
646 : 1 : set_processing_status("TERMINATING", "net_delete");
647 : :
648 [ + - ]: 1 : delete sessions;
649 [ - + ]: 1 : delete packet_sorter;
650 : :
651 : : // Can't put this in net_finish() because packets might be
652 : : // dumped when connections are deleted.
653 [ - + ]: 1 : if ( transformed_pkt_dump )
654 : 0 : delete transformed_pkt_dump;
655 : :
656 [ + + ]: 6 : for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i )
657 [ - + ]: 5 : delete ip_anonymizer[i];
658 : 1 : }
659 : :
660 : : // net_packet_match
661 : : //
662 : : // Description:
663 : : // - Checks if a packet matches a filter. It just wraps up a call to
664 : : // [pcap.h's] bpf_filter().
665 : : //
666 : : // Inputs:
667 : : // - fp: a BPF-compiled filter
668 : : // - pkt: a pointer to the packet
669 : : // - len: the original packet length
670 : : // - caplen: the captured packet length. This is pkt length
671 : : //
672 : : // Output:
673 : : // - return: 1 if the packet matches the filter, 0 otherwise
674 : :
675 : : int net_packet_match(BPF_Program* fp, const u_char* pkt,
676 : 0 : u_int len, u_int caplen)
677 : : {
678 : : // NOTE: I don't like too much un-const'ing the pkt variable.
679 : 0 : return bpf_filter(fp->GetProgram()->bf_insns, (u_char*) pkt, len, caplen);
680 : : }
681 : :
682 : :
683 : : int _processing_suspended = 0;
684 : :
685 : : static double suspend_start = 0;
686 : :
687 : 0 : void net_suspend_processing()
688 : : {
689 [ # # ]: 0 : if ( _processing_suspended == 0 )
690 : 0 : bro_logger->Log("processing suspended");
691 : :
692 : 0 : ++_processing_suspended;
693 : 0 : }
694 : :
695 : 0 : void net_continue_processing()
696 : : {
697 [ # # ]: 0 : if ( _processing_suspended == 1 )
698 : : {
699 : 0 : bro_logger->Log("processing continued");
700 [ # # ]: 0 : loop_over_list(pkt_srcs, i)
701 : 0 : pkt_srcs[i]->ContinueAfterSuspend();
702 : : }
703 : :
704 : 0 : --_processing_suspended;
705 [ + - ][ + - ]: 6 : }
|