trafgen: comment out unimplemented functions
[netsniff-ng.git] / src / netsniff-ng.c
blobb9e4bf96559076d281768fdb5b6db6f3aabd9d69
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009-2011 Daniel Borkmann.
5 * Copyright 2010 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
8 * The first sniffer that invoked both, the zero-copy RX_RING as well as
9 * the zero-copy TX_RING for high-performance network I/O and scatter/gather
10 * or mmaped PCAP I/O.
12 * "I knew that danger lay ahead, of course; but I did not expect to
13 * meet it in our own Shire. Can't a hobbit walk from the Water to the
14 * River in peace?" "But it is not your own Shire," said Gildor. "Others
15 * dwelt here before hobbits were; and others will dwell here again when
16 * hobbits are no more. The wide world is all about you: you can fence
17 * yourselves in, but you cannot for ever fence it out."
19 * -- The Lord of the Rings, Gildor to Frodo,
20 * Chapter 'Three is Company'.
25 =head1 NAME
27 netsniff-ng - the packet sniffing beast
29 =head1 SYNOPSIS
31 netsniff-ng -i|-d|--dev|--in <dev|pcap> -o|--out <dev|pcap|dir|txf>
32 [-f|--filter <bpf-file>][-t|--type <type>][-F|--interval <uint>]
33 [-s|--silent][-J|--jumbo-support][-n|--num <uint>][-r|--rand]
34 [-M|--no-promisc][-m|--mmap | -c|--clrw][-S|--ring-size <size>]
35 [-k|--kernel-pull <uint>][-b|--bind-cpu <cpu> | -B|--unbind-cpu <cpu>]
36 [-H|--prio-high][-Q|--notouch-irq][-q|--less | -X|--hex | -l|--ascii]
37 [-v|--version][-h|--help]
39 =head1 DESCRIPTION
41 The first sniffer that invoked both, the zero-copy RX_RING as well as
42 the zero-copy TX_RING for high-performance network I/O and scatter/gather
43 or mmaped PCAP I/O.
45 =head1 EXAMPLES
47 =over
49 =item netsniff-ng --in eth0 --out dump.pcap
51 Capture traffic from interface 'eth0' and save it pcap file 'dump.pcap'
53 =item netsniff-ng --in any --filter http.bpf --payload
55 Capture HTTP traffic from any interface and print its payload on stdout
57 =item netsniff-ng --in wlan0 --bind-cpu 0,1
59 Capture all traffic from wlan0 interface.
60 Schedule process on CPU 0 and 1.
62 =back
64 =head1 OPTIONS
66 =over
68 =item -i|-d|--dev|--in <dev|pcap>
70 Input source. Can be a network device or pcap file.
72 =item -o|--out <dev|pcap|dir|txf>
74 Output sink. Can be a network device, pcap file, a trafgen txf file or a
75 directory. (There's only pcap to txf translation possible.)
77 =item -f|--filter <bpf-file>
79 Use BPF filter file from bpfc.
81 =item -t|--type <type>
83 =over
85 =item Only handle packets of defined type:
87 =over
89 =item - broadcast
91 =item - multicast
93 =item - others
95 =item - outgoing
97 =back
99 =back
101 =item -F|--interval <uint>
103 Dump interval in seconds. if -o is a directory, a new pcap will be created at each interval.
104 The older files are left untouched. (default value: 60 seconds)
106 =item -s|--silent
108 Do not print captured packets to stdout.
110 =item -J|--jumbo-support
112 Support for 64KB Super Jumbo Frames.
114 =item -n|--num <uint>
116 When zerp, capture/replay until SIGINT is received (default).
117 When non-zero, capture/replay the number of packets.
119 =item -r|--rand
121 Randomize packet forwarding order (replay mode only).
123 =item -M|--no-promisc
125 Do not place the interface in promiscuous mode.
127 =item -m|--mmap
129 Mmap pcap file i.e., for replaying. Default: scatter/gather I/O.
131 =item -c|--clrw
133 Instead of using scatter/gather I/O use slower read(2)/write(2) I/O.
135 =item -S|--ring-size <size>
137 Manually set ring size in KB/MB/GB, e.g. '10MB'.
139 =item -k|--kernel-pull <uint>
141 Kernel pull from user interval in microseconds. Default is 10us. (replay mode only).
143 =item -b|--bind-cpu <cpu>
145 Bind to specific CPU (or CPU-range).
147 =item -B|--unbind-cpu <cpu>
149 Forbid to use specific CPU (or CPU-range).
151 =item -H|--prio-high
153 Run the process in high-priority mode.
155 =item -Q|--notouch-irq
157 Do not touch IRQ CPU affinity of NIC.
159 =item -q|--less
161 Print less-verbose packet information.
163 =item -X|--hex
165 Print packet data in hex format.
167 =item -l|--ascii
169 Print human-readable packet data.
171 =item -v|--version
173 Print version.
175 =item -h|--help
177 Print help text and lists all options.
179 =back
181 =head1 AUTHOR
183 Written by Daniel Borkmann <daniel@netsniff-ng.org> and Emmanuel Roullit <emmanuel@netsniff-ng.org>
185 =head1 DOCUMENTATION
187 Documentation by Emmanuel Roullit <emmanuel@netsniff-ng.org>
189 =head1 BUGS
191 Please report bugs to <bugs@netsniff-ng.org>
193 =cut
197 #define _GNU_SOURCE
198 #include <stdio.h>
199 #include <stdlib.h>
200 #include <signal.h>
201 #include <getopt.h>
202 #include <ctype.h>
203 #include <time.h>
204 #include <string.h>
205 #include <sys/socket.h>
206 #include <sys/types.h>
207 #include <sys/stat.h>
208 #include <sys/time.h>
209 #include <unistd.h>
210 #include <stdbool.h>
211 #include <pthread.h>
212 #include <fcntl.h>
214 #include "ring_rx.h"
215 #include "ring_tx.h"
216 #include "mac80211.h"
217 #include "xutils.h"
218 #include "built_in.h"
219 #include "pcap.h"
220 #include "bpf.h"
221 #include "xio.h"
222 #include "die.h"
223 #include "tprintf.h"
224 #include "dissector.h"
225 #include "xmalloc.h"
226 #include "mtrand.h"
228 #define CPU_UNKNOWN -1
229 #define CPU_NOTOUCH -2
230 #define PACKET_ALL -1
231 #define DUMP_INTERVAL 60
233 struct mode {
234 char *device_in;
235 char *device_out;
236 char *device_trans;
237 char *filter;
238 int cpu;
239 int rfraw;
240 int dump;
241 uint32_t link_type;
242 int print_mode;
243 unsigned int reserve_size;
244 int packet_type;
245 bool randomize;
246 bool promiscuous;
247 enum pcap_ops_groups pcap;
248 unsigned long kpull;
249 int jumbo_support;
250 int dump_dir;
251 unsigned long dump_interval;
254 struct tx_stats {
255 unsigned long tx_bytes;
256 unsigned long tx_packets;
259 volatile sig_atomic_t sigint = 0;
261 static int tx_sock;
262 static unsigned long frame_cnt_max = 0;
263 static unsigned long interval = TX_KERNEL_PULL_INT;
264 static struct itimerval itimer;
265 static volatile bool next_dump = false;
267 static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:B:HQmcsqXlvhF:Rg";
269 static struct option long_options[] = {
270 {"dev", required_argument, 0, 'd'},
271 {"in", required_argument, 0, 'i'},
272 {"out", required_argument, 0, 'o'},
273 {"rand", no_argument, 0, 'r'},
274 {"rfraw", no_argument, 0, 'R'},
275 {"mmap", no_argument, 0, 'm'},
276 {"sg", no_argument, 0, 'g'},
277 {"clrw", no_argument, 0, 'c'},
278 {"jumbo-support", no_argument, 0, 'J'},
279 {"filter", required_argument, 0, 'f'},
280 {"no-promisc", no_argument, 0, 'M'},
281 {"num", required_argument, 0, 'n'},
282 {"type", required_argument, 0, 't'},
283 {"interval", required_argument, 0, 'F'},
284 {"ring-size", required_argument, 0, 'S'},
285 {"kernel-pull", required_argument, 0, 'k'},
286 {"bind-cpu", required_argument, 0, 'b'},
287 {"unbind-cpu", required_argument, 0, 'B'},
288 {"prio-high", no_argument, 0, 'H'},
289 {"notouch-irq", no_argument, 0, 'Q'},
290 {"silent", no_argument, 0, 's'},
291 {"less", no_argument, 0, 'q'},
292 {"hex", no_argument, 0, 'X'},
293 {"ascii", no_argument, 0, 'l'},
294 {"version", no_argument, 0, 'v'},
295 {"help", no_argument, 0, 'h'},
296 {0, 0, 0, 0}
299 static void signal_handler(int number)
301 switch (number) {
302 case SIGINT:
303 sigint = 1;
304 break;
305 case SIGHUP:
306 break;
307 default:
308 break;
312 static void timer_elapsed(int number)
314 itimer.it_interval.tv_sec = 0;
315 itimer.it_interval.tv_usec = interval;
316 itimer.it_value.tv_sec = 0;
317 itimer.it_value.tv_usec = interval;
319 pull_and_flush_tx_ring(tx_sock);
320 setitimer(ITIMER_REAL, &itimer, NULL);
323 static void timer_next_dump(int number)
325 itimer.it_interval.tv_sec = interval;
326 itimer.it_interval.tv_usec = 0;
327 itimer.it_value.tv_sec = interval;
328 itimer.it_value.tv_usec = 0;
330 next_dump = true;
331 setitimer(ITIMER_REAL, &itimer, NULL);
334 static void enter_mode_pcap_to_tx(struct mode *mode)
336 int irq, ifindex, fd = 0, ret;
337 unsigned int size, it = 0;
338 struct ring tx_ring;
339 struct frame_map *hdr;
340 struct sock_fprog bpf_ops;
341 struct tx_stats stats;
342 uint8_t *out = NULL;
343 unsigned long trunced = 0;
344 struct timeval start, end, diff;
346 if (!device_up_and_running(mode->device_out))
347 panic("Device not up and running!\n");
349 tx_sock = pf_socket();
351 if (!pcap_ops[mode->pcap])
352 panic("pcap group not supported!\n");
353 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
354 ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type);
355 if (ret)
356 panic("error reading pcap header!\n");
357 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
358 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
359 if (ret)
360 panic("error prepare reading pcap!\n");
363 fmemset(&tx_ring, 0, sizeof(tx_ring));
364 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
365 fmemset(&stats, 0, sizeof(stats));
367 if (mode->rfraw) {
368 mode->device_trans = xstrdup(mode->device_out);
369 xfree(mode->device_out);
371 enter_rfmon_mac80211(mode->device_trans, &mode->device_out);
372 if (mode->link_type != LINKTYPE_IEEE802_11)
373 panic("Wrong linktype of pcap!\n");
376 ifindex = device_ifindex(mode->device_out);
377 size = ring_size(mode->device_out, mode->reserve_size);
379 bpf_parse_rules(mode->filter, &bpf_ops);
381 set_packet_loss_discard(tx_sock);
382 set_sockopt_hwtimestamp(tx_sock, mode->device_out);
383 setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support);
384 create_tx_ring(tx_sock, &tx_ring);
385 mmap_tx_ring(tx_sock, &tx_ring);
386 alloc_tx_ring_frames(&tx_ring);
387 bind_tx_ring(tx_sock, &tx_ring, ifindex);
389 dissector_init_all(mode->print_mode);
391 if (mode->cpu >= 0 && ifindex > 0) {
392 irq = device_irq_number(mode->device_out);
393 device_bind_irq_to_cpu(mode->cpu, irq);
394 printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq,
395 mode->cpu);
398 if (mode->kpull)
399 interval = mode->kpull;
401 itimer.it_interval.tv_sec = 0;
402 itimer.it_interval.tv_usec = interval;
403 itimer.it_value.tv_sec = 0;
404 itimer.it_value.tv_usec = interval;
405 setitimer(ITIMER_REAL, &itimer, NULL);
407 printf("BPF:\n");
408 bpf_dump_all(&bpf_ops);
409 printf("MD: TX %luus %s ", interval, pcap_ops[mode->pcap]->name);
410 if (mode->rfraw)
411 printf("802.11 raw via %s ", mode->device_out);
412 #ifdef _LARGEFILE64_SOURCE
413 printf("lf64 ");
414 #endif
415 ioprio_print();
416 printf("\n");
418 gettimeofday(&start, NULL);
420 while (likely(sigint == 0)) {
421 while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) {
422 struct pcap_pkthdr phdr;
423 hdr = tx_ring.frames[it].iov_base;
424 /* Kernel assumes: data = ph.raw + po->tp_hdrlen -
425 * sizeof(struct sockaddr_ll); */
426 out = ((uint8_t *) hdr) + TPACKET_HDRLEN -
427 sizeof(struct sockaddr_ll);
429 do {
430 memset(&phdr, 0, sizeof(phdr));
431 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
432 out, ring_frame_size(&tx_ring));
433 if (unlikely(ret <= 0))
434 goto out;
435 if (ring_frame_size(&tx_ring) < phdr.len) {
436 phdr.len = ring_frame_size(&tx_ring);
437 trunced++;
439 } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len));
440 pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h);
442 stats.tx_bytes += hdr->tp_h.tp_len;;
443 stats.tx_packets++;
445 show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS);
446 dissector_entry_point(out, hdr->tp_h.tp_snaplen,
447 mode->link_type, mode->print_mode);
449 kernel_may_pull_from_tx(&hdr->tp_h);
450 next_slot_prewr(&it, &tx_ring);
452 if (unlikely(sigint == 1))
453 break;
454 if (frame_cnt_max != 0 &&
455 stats.tx_packets >= frame_cnt_max) {
456 sigint = 1;
457 break;
461 out:
462 gettimeofday(&end, NULL);
463 diff = tv_subtract(end, start);
465 fflush(stdout);
466 printf("\n");
467 printf("\r%12lu frames outgoing\n", stats.tx_packets);
468 printf("\r%12lu frames truncated (larger than frame)\n", trunced);
469 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
470 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
472 bpf_release(&bpf_ops);
473 dissector_cleanup_all();
474 destroy_tx_ring(tx_sock, &tx_ring);
476 if (mode->rfraw)
477 leave_rfmon_mac80211(mode->device_trans, mode->device_out);
479 close(tx_sock);
480 if (pcap_ops[mode->pcap]->prepare_close_pcap)
481 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
482 close(fd);
485 static void enter_mode_rx_to_tx(struct mode *mode)
487 int rx_sock, ifindex_in, ifindex_out;
488 unsigned int size_in, size_out, it_in = 0, it_out = 0;
489 unsigned long fcnt = 0;
490 uint8_t *in, *out;
491 short ifflags = 0;
492 struct frame_map *hdr_in, *hdr_out;
493 struct ring tx_ring;
494 struct ring rx_ring;
495 struct pollfd rx_poll;
496 struct sock_fprog bpf_ops;
498 if (!strncmp(mode->device_in, mode->device_out,
499 strlen(mode->device_in)))
500 panic("Ingress/egress devices must be different!\n");
501 if (!device_up_and_running(mode->device_out))
502 panic("Egress device not up and running!\n");
503 if (!device_up_and_running(mode->device_in))
504 panic("Ingress device not up and running!\n");
506 rx_sock = pf_socket();
507 tx_sock = pf_socket();
509 fmemset(&tx_ring, 0, sizeof(tx_ring));
510 fmemset(&rx_ring, 0, sizeof(rx_ring));
511 fmemset(&rx_poll, 0, sizeof(rx_poll));
512 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
514 ifindex_in = device_ifindex(mode->device_in);
515 size_in = ring_size(mode->device_in, mode->reserve_size);
517 ifindex_out = device_ifindex(mode->device_out);
518 size_out = ring_size(mode->device_out, mode->reserve_size);
520 enable_kernel_bpf_jit_compiler();
521 bpf_parse_rules(mode->filter, &bpf_ops);
522 bpf_attach_to_sock(rx_sock, &bpf_ops);
524 setup_rx_ring_layout(rx_sock, &rx_ring, size_in, mode->jumbo_support);
525 create_rx_ring(rx_sock, &rx_ring);
526 mmap_rx_ring(rx_sock, &rx_ring);
527 alloc_rx_ring_frames(&rx_ring);
528 bind_rx_ring(rx_sock, &rx_ring, ifindex_in);
529 prepare_polling(rx_sock, &rx_poll);
531 set_packet_loss_discard(tx_sock);
532 setup_tx_ring_layout(tx_sock, &tx_ring, size_out, mode->jumbo_support);
533 create_tx_ring(tx_sock, &tx_ring);
534 mmap_tx_ring(tx_sock, &tx_ring);
535 alloc_tx_ring_frames(&tx_ring);
536 bind_tx_ring(tx_sock, &tx_ring, ifindex_out);
538 mt_init_by_seed_time();
539 dissector_init_all(mode->print_mode);
541 if (mode->promiscuous == true) {
542 ifflags = enter_promiscuous_mode(mode->device_in);
543 printf("PROMISC\n");
546 if (mode->kpull)
547 interval = mode->kpull;
549 itimer.it_interval.tv_sec = 0;
550 itimer.it_interval.tv_usec = interval;
551 itimer.it_value.tv_sec = 0;
552 itimer.it_value.tv_usec = interval;
553 setitimer(ITIMER_REAL, &itimer, NULL);
555 printf("BPF:\n");
556 bpf_dump_all(&bpf_ops);
557 printf("MD: RXTX %luus\n\n", interval);
558 printf("Running! Hang up with ^C!\n\n");
560 while (likely(sigint == 0)) {
561 while (user_may_pull_from_rx(rx_ring.frames[it_in].iov_base)) {
562 hdr_in = rx_ring.frames[it_in].iov_base;
563 in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac;
564 fcnt++;
565 if (mode->packet_type != PACKET_ALL)
566 if (mode->packet_type != hdr_in->s_ll.sll_pkttype)
567 goto next;
569 hdr_out = tx_ring.frames[it_out].iov_base;
570 out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN -
571 sizeof(struct sockaddr_ll);
573 for (; !user_may_pull_from_tx(tx_ring.frames[it_out].iov_base) &&
574 likely(!sigint);) {
575 if (mode->randomize)
576 next_rnd_slot(&it_out, &tx_ring);
577 else
578 next_slot(&it_out, &tx_ring);
579 hdr_out = tx_ring.frames[it_out].iov_base;
580 out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN -
581 sizeof(struct sockaddr_ll);
584 tpacket_hdr_clone(&hdr_out->tp_h, &hdr_in->tp_h);
585 fmemcpy(out, in, hdr_in->tp_h.tp_len);
587 kernel_may_pull_from_tx(&hdr_out->tp_h);
588 if (mode->randomize)
589 next_rnd_slot(&it_out, &tx_ring);
590 else
591 next_slot(&it_out, &tx_ring);
593 show_frame_hdr(hdr_in, mode->print_mode, RING_MODE_INGRESS);
594 dissector_entry_point(in, hdr_in->tp_h.tp_snaplen,
595 mode->link_type, mode->print_mode);
597 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
598 sigint = 1;
599 break;
601 next:
602 kernel_may_pull_from_rx(&hdr_in->tp_h);
603 next_slot(&it_in, &rx_ring);
605 if (unlikely(sigint == 1))
606 goto out;
609 poll(&rx_poll, 1, -1);
610 poll_error_maybe_die(rx_sock, &rx_poll);
612 out:
613 sock_print_net_stats(rx_sock, 0);
615 bpf_release(&bpf_ops);
616 dissector_cleanup_all();
617 destroy_tx_ring(tx_sock, &tx_ring);
618 destroy_rx_ring(rx_sock, &rx_ring);
620 if (mode->promiscuous == true)
621 leave_promiscuous_mode(mode->device_in, ifflags);
623 close(tx_sock);
624 close(rx_sock);
627 static void enter_mode_read_pcap(struct mode *mode)
629 int ret, fd, fdo = 0;
630 struct pcap_pkthdr phdr;
631 struct sock_fprog bpf_ops;
632 struct tx_stats stats;
633 struct frame_map fm;
634 uint8_t *out;
635 size_t out_len;
636 unsigned long trunced = 0;
637 struct timeval start, end, diff;
639 if (!pcap_ops[mode->pcap])
640 panic("pcap group not supported!\n");
641 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
642 ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type);
643 if (ret)
644 panic("error reading pcap header!\n");
645 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
646 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
647 if (ret)
648 panic("error prepare reading pcap!\n");
651 fmemset(&fm, 0, sizeof(fm));
652 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
653 fmemset(&stats, 0, sizeof(stats));
655 bpf_parse_rules(mode->filter, &bpf_ops);
656 dissector_init_all(mode->print_mode);
658 out_len = 64 * 1024;
659 out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE);
661 printf("BPF:\n");
662 bpf_dump_all(&bpf_ops);
663 printf("MD: RD %s ", pcap_ops[mode->pcap]->name);
664 #ifdef _LARGEFILE64_SOURCE
665 printf("lf64 ");
666 #endif
667 ioprio_print();
668 printf("\n");
670 if (mode->device_out) {
671 fdo = open_or_die_m(mode->device_out, O_RDWR | O_CREAT |
672 O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR);
675 gettimeofday(&start, NULL);
677 while (likely(sigint == 0)) {
678 do {
679 memset(&phdr, 0, sizeof(phdr));
680 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
681 out, out_len);
682 if (unlikely(ret < 0))
683 goto out;
684 if (unlikely(phdr.len == 0)) {
685 trunced++;
686 continue;
688 if (unlikely(phdr.len > out_len)) {
689 phdr.len = out_len;
690 trunced++;
692 } while (mode->filter &&
693 !bpf_run_filter(&bpf_ops, out, phdr.len));
695 pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h);
697 stats.tx_bytes += fm.tp_h.tp_len;
698 stats.tx_packets++;
700 show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS);
701 dissector_entry_point(out, fm.tp_h.tp_snaplen,
702 mode->link_type, mode->print_mode);
704 if (mode->device_out) {
705 int i = 0;
706 char bout[80];
707 slprintf(bout, sizeof(bout), "{\n ");
708 write_or_die(fdo, bout, strlen(bout));
710 while (i < fm.tp_h.tp_snaplen) {
711 slprintf(bout, sizeof(bout), "0x%02x, ", out[i]);
712 write_or_die(fdo, bout, strlen(bout));
713 i++;
714 if (i % 10 == 0) {
715 slprintf(bout, sizeof(bout), "\n", out[i]);
716 write_or_die(fdo, bout, strlen(bout));
717 if (i < fm.tp_h.tp_snaplen) {
718 slprintf(bout, sizeof(bout), " ", out[i]);
719 write_or_die(fdo, bout, strlen(bout));
723 if (i % 10 != 0) {
724 slprintf(bout, sizeof(bout), "\n");
725 write_or_die(fdo, bout, strlen(bout));
727 slprintf(bout, sizeof(bout), "}\n\n");
728 write_or_die(fdo, bout, strlen(bout));
731 if (frame_cnt_max != 0 &&
732 stats.tx_packets >= frame_cnt_max) {
733 sigint = 1;
734 break;
737 out:
738 gettimeofday(&end, NULL);
739 diff = tv_subtract(end, start);
741 fflush(stdout);
742 printf("\n");
743 printf("\r%12lu frames outgoing\n", stats.tx_packets);
744 printf("\r%12lu frames truncated (larger than mtu)\n", trunced);
745 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
746 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
748 xfree(out);
750 bpf_release(&bpf_ops);
751 dissector_cleanup_all();
752 if (pcap_ops[mode->pcap]->prepare_close_pcap)
753 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
754 close(fd);
756 if (mode->device_out)
757 close(fdo);
760 static void finish_multi_pcap_file(struct mode *mode, int fd)
762 pcap_ops[mode->pcap]->fsync_pcap(fd);
763 if (pcap_ops[mode->pcap]->prepare_close_pcap)
764 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
765 close(fd);
767 fmemset(&itimer, 0, sizeof(itimer));
768 setitimer(ITIMER_REAL, &itimer, NULL);
771 static int next_multi_pcap_file(struct mode *mode, int fd)
773 int ret;
774 char tmp[512];
776 pcap_ops[mode->pcap]->fsync_pcap(fd);
777 if (pcap_ops[mode->pcap]->prepare_close_pcap)
778 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
779 close(fd);
781 slprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
783 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
784 S_IRUSR | S_IWUSR);
785 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
786 if (ret)
787 panic("error writing pcap header!\n");
788 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
789 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
790 if (ret)
791 panic("error prepare writing pcap!\n");
794 return fd;
797 static int begin_multi_pcap_file(struct mode *mode)
799 int fd, ret;
800 char tmp[512];
802 if (!pcap_ops[mode->pcap])
803 panic("pcap group not supported!\n");
804 if (mode->device_out[strlen(mode->device_out) - 1] == '/')
805 mode->device_out[strlen(mode->device_out) - 1] = 0;
807 slprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
809 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
810 S_IRUSR | S_IWUSR);
811 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
812 if (ret)
813 panic("error writing pcap header!\n");
814 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
815 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
816 if (ret)
817 panic("error prepare writing pcap!\n");
820 interval = mode->dump_interval;
821 itimer.it_interval.tv_sec = interval;
822 itimer.it_interval.tv_usec = 0;
823 itimer.it_value.tv_sec = interval;
824 itimer.it_value.tv_usec = 0;
825 setitimer(ITIMER_REAL, &itimer, NULL);
827 return fd;
830 static void finish_single_pcap_file(struct mode *mode, int fd)
832 pcap_ops[mode->pcap]->fsync_pcap(fd);
833 if (pcap_ops[mode->pcap]->prepare_close_pcap)
834 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
835 close(fd);
838 static int begin_single_pcap_file(struct mode *mode)
840 int fd, ret;
842 if (!pcap_ops[mode->pcap])
843 panic("pcap group not supported!\n");
844 fd = open_or_die_m(mode->device_out,
845 O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
846 S_IRUSR | S_IWUSR);
847 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
848 if (ret)
849 panic("error writing pcap header!\n");
850 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
851 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
852 if (ret)
853 panic("error prepare writing pcap!\n");
856 return fd;
859 static void enter_mode_rx_only_or_dump(struct mode *mode)
861 int sock, irq, ifindex, fd = 0, ret;
862 unsigned int size, it = 0;
863 unsigned long fcnt = 0, skipped = 0;
864 short ifflags = 0;
865 uint8_t *packet;
866 struct ring rx_ring;
867 struct pollfd rx_poll;
868 struct frame_map *hdr;
869 struct sock_fprog bpf_ops;
870 struct timeval start, end, diff;
872 if (!device_up_and_running(mode->device_in))
873 panic("Device not up and running!\n");
875 sock = pf_socket();
877 if (mode->rfraw) {
878 mode->device_trans = xstrdup(mode->device_in);
879 xfree(mode->device_in);
881 enter_rfmon_mac80211(mode->device_trans, &mode->device_in);
882 mode->link_type = LINKTYPE_IEEE802_11;
885 if (mode->dump) {
886 struct stat tmp;
887 fmemset(&tmp, 0, sizeof(tmp));
888 ret = stat(mode->device_out, &tmp);
889 if (ret < 0) {
890 mode->dump_dir = 0;
891 goto try_file;
893 mode->dump_dir = !!S_ISDIR(tmp.st_mode);
894 if (mode->dump_dir) {
895 fd = begin_multi_pcap_file(mode);
896 } else {
897 try_file:
898 fd = begin_single_pcap_file(mode);
902 fmemset(&rx_ring, 0, sizeof(rx_ring));
903 fmemset(&rx_poll, 0, sizeof(rx_poll));
904 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
906 ifindex = device_ifindex(mode->device_in);
907 size = ring_size(mode->device_in, mode->reserve_size);
909 enable_kernel_bpf_jit_compiler();
910 bpf_parse_rules(mode->filter, &bpf_ops);
911 bpf_attach_to_sock(sock, &bpf_ops);
913 set_sockopt_hwtimestamp(sock, mode->device_in);
914 setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support);
915 create_rx_ring(sock, &rx_ring);
916 mmap_rx_ring(sock, &rx_ring);
917 alloc_rx_ring_frames(&rx_ring);
918 bind_rx_ring(sock, &rx_ring, ifindex);
920 prepare_polling(sock, &rx_poll);
921 dissector_init_all(mode->print_mode);
923 if (mode->cpu >= 0 && ifindex > 0) {
924 irq = device_irq_number(mode->device_in);
925 device_bind_irq_to_cpu(mode->cpu, irq);
926 printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq,
927 mode->cpu);
930 if (mode->promiscuous == true) {
931 ifflags = enter_promiscuous_mode(mode->device_in);
932 printf("PROMISC\n");
935 printf("BPF:\n");
936 bpf_dump_all(&bpf_ops);
937 printf("MD: RX %s ", mode->dump ? pcap_ops[mode->pcap]->name : "");
938 if (mode->rfraw)
939 printf("802.11 raw via %s ", mode->device_in);
940 #ifdef _LARGEFILE64_SOURCE
941 printf("lf64 ");
942 #endif
943 ioprio_print();
944 printf("\n");
946 gettimeofday(&start, NULL);
948 while (likely(sigint == 0)) {
949 while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
950 hdr = rx_ring.frames[it].iov_base;
951 packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
952 fcnt++;
954 if (mode->packet_type != PACKET_ALL)
955 if (mode->packet_type != hdr->s_ll.sll_pkttype)
956 goto next;
957 if (unlikely(ring_frame_size(&rx_ring) <
958 hdr->tp_h.tp_snaplen)) {
959 skipped++;
960 goto next;
962 if (mode->dump) {
963 struct pcap_pkthdr phdr;
964 tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr);
965 ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr,
966 packet, phdr.len);
967 if (unlikely(ret != sizeof(phdr) + phdr.len))
968 panic("Write error to pcap!\n");
971 show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS);
972 dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
973 mode->link_type, mode->print_mode);
975 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
976 sigint = 1;
977 break;
979 next:
980 kernel_may_pull_from_rx(&hdr->tp_h);
981 next_slot_prerd(&it, &rx_ring);
983 if (unlikely(sigint == 1))
984 break;
985 if (mode->dump && next_dump) {
986 struct tpacket_stats kstats;
987 socklen_t slen = sizeof(kstats);
988 fmemset(&kstats, 0, sizeof(kstats));
989 getsockopt(sock, SOL_PACKET, PACKET_STATISTICS,
990 &kstats, &slen);
991 fd = next_multi_pcap_file(mode, fd);
992 next_dump = false;
993 if (mode->print_mode == FNTTYPE_PRINT_NONE) {
994 printf(".(+%lu/-%lu)",
995 1UL * kstats.tp_packets -
996 kstats.tp_drops -
997 skipped, 1UL * kstats.tp_drops +
998 skipped);
999 fflush(stdout);
1004 poll(&rx_poll, 1, -1);
1005 poll_error_maybe_die(sock, &rx_poll);
1008 gettimeofday(&end, NULL);
1009 diff = tv_subtract(end, start);
1011 if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) {
1012 sock_print_net_stats(sock, skipped);
1013 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec,
1014 diff.tv_usec);
1015 } else {
1016 printf("\n\n");
1017 fflush(stdout);
1020 bpf_release(&bpf_ops);
1021 dissector_cleanup_all();
1022 destroy_rx_ring(sock, &rx_ring);
1024 if (mode->promiscuous == true)
1025 leave_promiscuous_mode(mode->device_in, ifflags);
1027 if (mode->rfraw)
1028 leave_rfmon_mac80211(mode->device_trans, mode->device_in);
1030 close(sock);
1032 if (mode->dump) {
1033 if (mode->dump_dir)
1034 finish_multi_pcap_file(mode, fd);
1035 else
1036 finish_single_pcap_file(mode, fd);
1040 static void help(void)
1042 printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING,
1043 VERSION_STRING);
1044 printf("http://www.netsniff-ng.org\n\n");
1045 printf("Usage: netsniff-ng [options]\n");
1046 printf("Options:\n");
1047 printf(" -i|-d|--dev|--in <dev|pcap> Input source as netdev or pcap\n");
1048 printf(" -o|--out <dev|pcap|dir|txf> Output sink as netdev, pcap, directory, txf file\n");
1049 printf(" -f|--filter <bpf-file> Use BPF filter file from bpfc\n");
1050 printf(" -t|--type <type> Only handle packets of defined type:\n");
1051 printf(" host|broadcast|multicast|others|outgoing\n");
1052 printf(" -F|--interval <uint> Dump interval in sec if -o is a directory where\n");
1053 printf(" pcap files should be stored (default: 60)\n");
1054 printf(" -J|--jumbo-support Support for 64KB Super Jumbo Frames\n");
1055 printf(" Default RX/TX slot: 2048Byte\n");
1056 printf(" -R|--rfraw Capture or inject raw 802.11 frames\n");
1057 printf(" -n|--num <uint> Number of packets until exit\n");
1058 printf(" `-- 0 Loop until interrupted (default)\n");
1059 printf(" `- n Send n packets and done\n");
1060 printf("Options for printing:\n");
1061 printf(" -s|--silent Do not print captured packets\n");
1062 printf(" -q|--less Print less-verbose packet information\n");
1063 printf(" -X|--hex Print packet data in hex format\n");
1064 printf(" -l|--ascii Print human-readable packet data\n");
1065 printf("Options, advanced:\n");
1066 printf(" -r|--rand Randomize packet forwarding order\n");
1067 printf(" -M|--no-promisc No promiscuous mode for netdev\n");
1068 printf(" -m|--mmap Mmap pcap file i.e., for replaying\n");
1069 printf(" -g|--sg Scatter/gather pcap file I/O\n");
1070 printf(" -c|--clrw Use slower read(2)/write(2) I/O\n");
1071 printf(" -S|--ring-size <size> Manually set ring size to <size>:\n");
1072 printf(" mmap space in KB/MB/GB, e.g. \'10MB\'\n");
1073 printf(" -k|--kernel-pull <uint> Kernel pull from user interval in us\n");
1074 printf(" Default is 10us where the TX_RING\n");
1075 printf(" is populated with payload from uspace\n");
1076 printf(" -b|--bind-cpu <cpu> Bind to specific CPU (or CPU-range)\n");
1077 printf(" -B|--unbind-cpu <cpu> Forbid to use specific CPU (or CPU-range)\n");
1078 printf(" -H|--prio-high Make this high priority process\n");
1079 printf(" -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n");
1080 printf(" -v|--version Show version\n");
1081 printf(" -h|--help Guess what?!\n");
1082 printf("\n");
1083 printf("Examples:\n");
1084 printf(" netsniff-ng --in eth0 --out dump.pcap --silent --bind-cpu 0\n");
1085 printf(" netsniff-ng --in wlan0 --rfraw --out dump.pcap --silent --bind-cpu 0\n");
1086 printf(" netsniff-ng --in dump.pcap --mmap --out eth0 --silent --bind-cpu 0\n");
1087 printf(" netsniff-ng --in dump.pcap --out dump.txf --silent --bind-cpu 0\n");
1088 printf(" netsniff-ng --in eth0 --out eth1 --silent --bind-cpu 0 --type host\n");
1089 printf(" netsniff-ng --in eth1 --out /opt/probe1/ -s -m -J --interval 30 -b 0\n");
1090 printf(" netsniff-ng --in any --filter http.bpf --jumbo-support --ascii\n");
1091 printf("\n");
1092 printf("Note:\n");
1093 printf(" This tool is targeted for network developers! You should\n");
1094 printf(" be aware of what you are doing and what these options above\n");
1095 printf(" mean! Use netsniff-ng's bpfc compiler for generating filter files.\n");
1096 printf(" Further, netsniff-ng automatically enables the kernel BPF JIT\n");
1097 printf(" if present. Txf file output is only possible if the input source\n");
1098 printf(" is a pcap file.\n");
1099 printf("\n");
1100 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
1101 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
1102 printf("Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n");
1103 printf("License: GNU GPL version 2\n");
1104 printf("This is free software: you are free to change and redistribute it.\n");
1105 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
1106 die();
1109 static void version(void)
1111 printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING,
1112 VERSION_STRING);
1113 printf("http://www.netsniff-ng.org\n\n");
1114 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
1115 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
1116 printf("Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n");
1117 printf("License: GNU GPL version 2\n");
1118 printf("This is free software: you are free to change and redistribute it.\n");
1119 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
1120 die();
1123 static void header(void)
1125 printf("%s%s%s\n", colorize_start(bold), PROGNAME_STRING " "
1126 VERSION_STRING, colorize_end());
1129 int main(int argc, char **argv)
1131 int c, i, j, opt_index, ops_touched = 0;
1132 char *ptr;
1133 bool prio_high = false;
1134 struct mode mode;
1135 void (*enter_mode)(struct mode *mode) = NULL;
1137 check_for_root_maybe_die();
1139 fmemset(&mode, 0, sizeof(mode));
1140 mode.link_type = LINKTYPE_EN10MB;
1141 mode.print_mode = FNTTYPE_PRINT_NORM;
1142 mode.cpu = CPU_UNKNOWN;
1143 mode.packet_type = PACKET_ALL;
1144 mode.promiscuous = true;
1145 mode.randomize = false;
1146 mode.pcap = PCAP_OPS_SG;
1147 mode.dump_interval = DUMP_INTERVAL;
1149 while ((c = getopt_long(argc, argv, short_options, long_options,
1150 &opt_index)) != EOF) {
1151 switch (c) {
1152 case 'd':
1153 case 'i':
1154 mode.device_in = xstrdup(optarg);
1155 break;
1156 case 'o':
1157 mode.device_out = xstrdup(optarg);
1158 break;
1159 case 'R':
1160 mode.link_type = LINKTYPE_IEEE802_11;
1161 mode.rfraw = 1;
1162 break;
1163 case 'r':
1164 mode.randomize = true;
1165 break;
1166 case 'J':
1167 mode.jumbo_support = 1;
1168 break;
1169 case 'f':
1170 mode.filter = xstrdup(optarg);
1171 break;
1172 case 'M':
1173 mode.promiscuous = false;
1174 break;
1175 case 't':
1176 if (!strncmp(optarg, "host", strlen("host")))
1177 mode.packet_type = PACKET_HOST;
1178 else if (!strncmp(optarg, "broadcast", strlen("broadcast")))
1179 mode.packet_type = PACKET_BROADCAST;
1180 else if (!strncmp(optarg, "multicast", strlen("multicast")))
1181 mode.packet_type = PACKET_MULTICAST;
1182 else if (!strncmp(optarg, "others", strlen("others")))
1183 mode.packet_type = PACKET_OTHERHOST;
1184 else if (!strncmp(optarg, "outgoing", strlen("outgoing")))
1185 mode.packet_type = PACKET_OUTGOING;
1186 else
1187 mode.packet_type = PACKET_ALL;
1188 break;
1189 case 'S':
1190 ptr = optarg;
1191 mode.reserve_size = 0;
1193 for (j = i = strlen(optarg); i > 0; --i) {
1194 if (!isdigit(optarg[j - i]))
1195 break;
1196 ptr++;
1199 if (!strncmp(ptr, "KB", strlen("KB")))
1200 mode.reserve_size = 1 << 10;
1201 else if (!strncmp(ptr, "MB", strlen("MB")))
1202 mode.reserve_size = 1 << 20;
1203 else if (!strncmp(ptr, "GB", strlen("GB")))
1204 mode.reserve_size = 1 << 30;
1205 else
1206 panic("Syntax error in ring size param!\n");
1208 *ptr = 0;
1209 mode.reserve_size *= atoi(optarg);
1210 break;
1211 case 'b':
1212 set_cpu_affinity(optarg, 0);
1213 if (mode.cpu != CPU_NOTOUCH)
1214 mode.cpu = atoi(optarg);
1215 break;
1216 case 'B':
1217 set_cpu_affinity(optarg, 1);
1218 break;
1219 case 'H':
1220 prio_high = true;
1221 break;
1222 case 'c':
1223 mode.pcap = PCAP_OPS_RW;
1224 ops_touched = 1;
1225 break;
1226 case 'm':
1227 mode.pcap = PCAP_OPS_MMAP;
1228 ops_touched = 1;
1229 break;
1230 case 'g':
1231 mode.pcap = PCAP_OPS_SG;
1232 ops_touched = 1;
1233 break;
1234 case 'Q':
1235 mode.cpu = CPU_NOTOUCH;
1236 break;
1237 case 's':
1238 mode.print_mode = FNTTYPE_PRINT_NONE;
1239 break;
1240 case 'q':
1241 mode.print_mode = FNTTYPE_PRINT_LESS;
1242 break;
1243 case 'X':
1244 mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_ASCII) ?
1245 FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_HEX;
1246 break;
1247 case 'l':
1248 mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_HEX) ?
1249 FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_ASCII;
1250 break;
1251 case 'k':
1252 mode.kpull = (unsigned long) atol(optarg);
1253 break;
1254 case 'n':
1255 frame_cnt_max = (unsigned long) atol(optarg);
1256 break;
1257 case 'F':
1258 mode.dump_interval = (unsigned long) atol(optarg);
1259 break;
1260 case 'v':
1261 version();
1262 break;
1263 case 'h':
1264 help();
1265 break;
1266 case '?':
1267 switch (optopt) {
1268 case 'd':
1269 case 'i':
1270 case 'o':
1271 case 'f':
1272 case 't':
1273 case 'F':
1274 case 'n':
1275 case 'S':
1276 case 'b':
1277 case 'k':
1278 case 'B':
1279 case 'e':
1280 panic("Option -%c requires an argument!\n",
1281 optopt);
1282 default:
1283 if (isprint(optopt))
1284 whine("Unknown option character "
1285 "`0x%X\'!\n", optopt);
1286 die();
1288 default:
1289 break;
1293 if (!mode.device_in)
1294 mode.device_in = xstrdup("any");
1296 register_signal(SIGINT, signal_handler);
1297 register_signal(SIGHUP, signal_handler);
1299 init_pcap(mode.jumbo_support);
1300 tprintf_init();
1301 header();
1303 if (prio_high == true) {
1304 set_proc_prio(get_default_proc_prio());
1305 set_sched_status(get_default_sched_policy(),
1306 get_default_sched_prio());
1309 if (mode.device_in && (device_mtu(mode.device_in) ||
1310 !strncmp("any", mode.device_in, strlen(mode.device_in)))) {
1311 if (!mode.device_out) {
1312 mode.dump = 0;
1313 enter_mode = enter_mode_rx_only_or_dump;
1314 } else if (device_mtu(mode.device_out)) {
1315 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1316 enter_mode = enter_mode_rx_to_tx;
1317 } else {
1318 mode.dump = 1;
1319 register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO);
1320 enter_mode = enter_mode_rx_only_or_dump;
1321 if (!ops_touched)
1322 mode.pcap = PCAP_OPS_SG;
1324 } else {
1325 if (mode.device_out && device_mtu(mode.device_out)) {
1326 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1327 enter_mode = enter_mode_pcap_to_tx;
1328 if (!ops_touched)
1329 mode.pcap = PCAP_OPS_MMAP;
1330 } else {
1331 enter_mode = enter_mode_read_pcap;
1332 if (!ops_touched)
1333 mode.pcap = PCAP_OPS_SG;
1337 if (!enter_mode)
1338 panic("Selection not supported!\n");
1339 enter_mode(&mode);
1341 tprintf_cleanup();
1342 cleanup_pcap();
1344 if (mode.device_in)
1345 xfree(mode.device_in);
1346 if (mode.device_out)
1347 xfree(mode.device_out);
1348 if (mode.device_trans)
1349 xfree(mode.device_trans);
1351 return 0;