flowtop: make function nested
[netsniff-ng.git] / src / netsniff-ng.c
blob0e2a68b0b0ae08a9ae2b198bb47416e2ae914f3c
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'.
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <getopt.h>
28 #include <ctype.h>
29 #include <time.h>
30 #include <string.h>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36 #include <stdbool.h>
37 #include <pthread.h>
38 #include <fcntl.h>
40 #include "ring_rx.h"
41 #include "ring_tx.h"
42 #include "mac80211.h"
43 #include "xutils.h"
44 #include "built_in.h"
45 #include "pcap.h"
46 #include "bpf.h"
47 #include "xio.h"
48 #include "die.h"
49 #include "tprintf.h"
50 #include "dissector.h"
51 #include "xmalloc.h"
52 #include "mtrand.h"
54 #define DUMP_INTERVAL_DEF 60
55 enum dump_mode {
56 DUMP_INTERVAL_TIME,
57 DUMP_INTERVAL_SIZE,
60 struct mode {
61 char *device_in, *device_out, *device_trans, *filter, *prefix;
62 #define CPU_UNKNOWN -1
63 #define CPU_NOTOUCH -2
64 int cpu, rfraw, dump, print_mode, dump_dir, jumbo_support;
65 #define PACKET_ALL -1
66 int packet_type;
67 uint32_t link_type;
68 bool randomize, promiscuous;
69 enum pcap_ops_groups pcap;
70 unsigned long kpull, dump_interval, reserve_size;
71 enum dump_mode dump_mode;
74 struct tx_stats {
75 unsigned long tx_bytes;
76 unsigned long tx_packets;
79 volatile sig_atomic_t sigint = 0;
80 static int tx_sock;
81 static unsigned long frame_cnt_max = 0, interval = TX_KERNEL_PULL_INT;
82 static struct itimerval itimer;
83 static volatile bool next_dump = false;
85 static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:B:HQmcsqXlvhF:RgAP:";
86 static const struct option long_options[] = {
87 {"dev", required_argument, NULL, 'd'},
88 {"in", required_argument, NULL, 'i'},
89 {"out", required_argument, NULL, 'o'},
90 {"filter", required_argument, NULL, 'f'},
91 {"num", required_argument, NULL, 'n'},
92 {"type", required_argument, NULL, 't'},
93 {"interval", required_argument, NULL, 'F'},
94 {"ring-size", required_argument, NULL, 'S'},
95 {"kernel-pull", required_argument, NULL, 'k'},
96 {"bind-cpu", required_argument, NULL, 'b'},
97 {"unbind-cpu", required_argument, NULL, 'B'},
98 {"prefix", required_argument, NULL, 'P'},
99 {"rand", no_argument, NULL, 'r'},
100 {"rfraw", no_argument, NULL, 'R'},
101 {"mmap", no_argument, NULL, 'm'},
102 {"sg", no_argument, NULL, 'g'},
103 {"clrw", no_argument, NULL, 'c'},
104 {"jumbo-support", no_argument, NULL, 'J'},
105 {"no-promisc", no_argument, NULL, 'M'},
106 {"prio-high", no_argument, NULL, 'H'},
107 {"notouch-irq", no_argument, NULL, 'Q'},
108 {"silent", no_argument, NULL, 's'},
109 {"less", no_argument, NULL, 'q'},
110 {"hex", no_argument, NULL, 'X'},
111 {"ascii", no_argument, NULL, 'l'},
112 {"no-sock-mem", no_argument, NULL, 'A'},
113 {"version", no_argument, NULL, 'v'},
114 {"help", no_argument, NULL, 'h'},
115 {NULL, 0, NULL, 0}
118 static void signal_handler(int number)
120 switch (number) {
121 case SIGINT:
122 sigint = 1;
123 break;
124 case SIGHUP:
125 break;
126 default:
127 break;
131 static void timer_elapsed(int number)
133 itimer.it_interval.tv_sec = 0;
134 itimer.it_interval.tv_usec = interval;
135 itimer.it_value.tv_sec = 0;
136 itimer.it_value.tv_usec = interval;
138 pull_and_flush_tx_ring(tx_sock);
139 setitimer(ITIMER_REAL, &itimer, NULL);
142 static void timer_next_dump(int number)
144 itimer.it_interval.tv_sec = interval;
145 itimer.it_interval.tv_usec = 0;
146 itimer.it_value.tv_sec = interval;
147 itimer.it_value.tv_usec = 0;
149 next_dump = true;
150 setitimer(ITIMER_REAL, &itimer, NULL);
153 static void enter_mode_pcap_to_tx(struct mode *mode)
155 __label__ out;
156 int irq, ifindex, fd = 0, ret;
157 unsigned int size, it = 0;
158 struct ring tx_ring;
159 struct frame_map *hdr;
160 struct sock_fprog bpf_ops;
161 struct tx_stats stats;
162 uint8_t *out = NULL;
163 unsigned long trunced = 0;
164 struct timeval start, end, diff;
166 if (!device_up_and_running(mode->device_out) &&
167 !mode->rfraw)
168 panic("Device not up and running!\n");
170 tx_sock = pf_socket();
172 if (!pcap_ops[mode->pcap])
173 panic("pcap group not supported!\n");
174 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
175 ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type);
176 if (ret)
177 panic("error reading pcap header!\n");
178 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
179 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
180 if (ret)
181 panic("error prepare reading pcap!\n");
184 fmemset(&tx_ring, 0, sizeof(tx_ring));
185 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
186 fmemset(&stats, 0, sizeof(stats));
188 if (mode->rfraw) {
189 mode->device_trans = xstrdup(mode->device_out);
190 xfree(mode->device_out);
192 enter_rfmon_mac80211(mode->device_trans, &mode->device_out);
193 if (mode->link_type != LINKTYPE_IEEE802_11)
194 panic("Wrong linktype of pcap!\n");
197 ifindex = device_ifindex(mode->device_out);
198 size = ring_size(mode->device_out, mode->reserve_size);
200 bpf_parse_rules(mode->filter, &bpf_ops);
202 set_packet_loss_discard(tx_sock);
203 set_sockopt_hwtimestamp(tx_sock, mode->device_out);
204 setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support);
205 create_tx_ring(tx_sock, &tx_ring);
206 mmap_tx_ring(tx_sock, &tx_ring);
207 alloc_tx_ring_frames(&tx_ring);
208 bind_tx_ring(tx_sock, &tx_ring, ifindex);
210 dissector_init_all(mode->print_mode);
212 if (mode->cpu >= 0 && ifindex > 0) {
213 irq = device_irq_number(mode->device_out);
214 device_bind_irq_to_cpu(mode->cpu, irq);
215 printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq,
216 mode->cpu);
219 if (mode->kpull)
220 interval = mode->kpull;
222 itimer.it_interval.tv_sec = 0;
223 itimer.it_interval.tv_usec = interval;
224 itimer.it_value.tv_sec = 0;
225 itimer.it_value.tv_usec = interval;
226 setitimer(ITIMER_REAL, &itimer, NULL);
228 printf("BPF:\n");
229 bpf_dump_all(&bpf_ops);
230 printf("MD: TX %luus %s ", interval, pcap_ops[mode->pcap]->name);
231 if (mode->rfraw)
232 printf("802.11 raw via %s ", mode->device_out);
233 #ifdef _LARGEFILE64_SOURCE
234 printf("lf64 ");
235 #endif
236 ioprio_print();
237 printf("\n");
239 bug_on(gettimeofday(&start, NULL));
241 while (likely(sigint == 0)) {
242 while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) {
243 struct pcap_pkthdr phdr;
244 hdr = tx_ring.frames[it].iov_base;
245 /* Kernel assumes: data = ph.raw + po->tp_hdrlen -
246 * sizeof(struct sockaddr_ll); */
247 out = ((uint8_t *) hdr) + TPACKET2_HDRLEN -
248 sizeof(struct sockaddr_ll);
250 do {
251 memset(&phdr, 0, sizeof(phdr));
252 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
253 out, ring_frame_size(&tx_ring));
254 if (unlikely(ret <= 0))
255 goto out;
256 if (ring_frame_size(&tx_ring) < phdr.len) {
257 phdr.len = ring_frame_size(&tx_ring);
258 trunced++;
260 } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len));
261 pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h);
263 stats.tx_bytes += hdr->tp_h.tp_len;;
264 stats.tx_packets++;
266 show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS);
267 dissector_entry_point(out, hdr->tp_h.tp_snaplen,
268 mode->link_type, mode->print_mode);
270 kernel_may_pull_from_tx(&hdr->tp_h);
271 next_slot(&it, &tx_ring);
273 if (unlikely(sigint == 1))
274 break;
275 if (frame_cnt_max != 0 &&
276 stats.tx_packets >= frame_cnt_max) {
277 sigint = 1;
278 break;
283 out:
285 bug_on(gettimeofday(&end, NULL));
286 diff = tv_subtract(end, start);
288 fflush(stdout);
289 printf("\n");
290 printf("\r%12lu frames outgoing\n", stats.tx_packets);
291 printf("\r%12lu frames truncated (larger than frame)\n", trunced);
292 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
293 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
295 bpf_release(&bpf_ops);
296 dissector_cleanup_all();
297 destroy_tx_ring(tx_sock, &tx_ring);
299 if (mode->rfraw)
300 leave_rfmon_mac80211(mode->device_trans, mode->device_out);
302 close(tx_sock);
303 if (pcap_ops[mode->pcap]->prepare_close_pcap)
304 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
305 close(fd);
308 static void enter_mode_rx_to_tx(struct mode *mode)
310 int rx_sock, ifindex_in, ifindex_out;
311 unsigned int size_in, size_out, it_in = 0, it_out = 0;
312 unsigned long fcnt = 0;
313 uint8_t *in, *out;
314 short ifflags = 0;
315 struct frame_map *hdr_in, *hdr_out;
316 struct ring tx_ring;
317 struct ring rx_ring;
318 struct pollfd rx_poll;
319 struct sock_fprog bpf_ops;
321 if (!strncmp(mode->device_in, mode->device_out,
322 strlen(mode->device_in)))
323 panic("Ingress/egress devices must be different!\n");
324 if (!device_up_and_running(mode->device_out))
325 panic("Egress device not up and running!\n");
326 if (!device_up_and_running(mode->device_in))
327 panic("Ingress device not up and running!\n");
329 rx_sock = pf_socket();
330 tx_sock = pf_socket();
332 fmemset(&tx_ring, 0, sizeof(tx_ring));
333 fmemset(&rx_ring, 0, sizeof(rx_ring));
334 fmemset(&rx_poll, 0, sizeof(rx_poll));
335 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
337 ifindex_in = device_ifindex(mode->device_in);
338 size_in = ring_size(mode->device_in, mode->reserve_size);
340 ifindex_out = device_ifindex(mode->device_out);
341 size_out = ring_size(mode->device_out, mode->reserve_size);
343 enable_kernel_bpf_jit_compiler();
344 bpf_parse_rules(mode->filter, &bpf_ops);
345 bpf_attach_to_sock(rx_sock, &bpf_ops);
347 setup_rx_ring_layout(rx_sock, &rx_ring, size_in, mode->jumbo_support);
348 create_rx_ring(rx_sock, &rx_ring);
349 mmap_rx_ring(rx_sock, &rx_ring);
350 alloc_rx_ring_frames(&rx_ring);
351 bind_rx_ring(rx_sock, &rx_ring, ifindex_in);
352 prepare_polling(rx_sock, &rx_poll);
354 set_packet_loss_discard(tx_sock);
355 setup_tx_ring_layout(tx_sock, &tx_ring, size_out, mode->jumbo_support);
356 create_tx_ring(tx_sock, &tx_ring);
357 mmap_tx_ring(tx_sock, &tx_ring);
358 alloc_tx_ring_frames(&tx_ring);
359 bind_tx_ring(tx_sock, &tx_ring, ifindex_out);
361 mt_init_by_seed_time();
362 dissector_init_all(mode->print_mode);
364 if (mode->promiscuous == true) {
365 ifflags = enter_promiscuous_mode(mode->device_in);
366 printf("PROMISC\n");
369 if (mode->kpull)
370 interval = mode->kpull;
372 itimer.it_interval.tv_sec = 0;
373 itimer.it_interval.tv_usec = interval;
374 itimer.it_value.tv_sec = 0;
375 itimer.it_value.tv_usec = interval;
376 setitimer(ITIMER_REAL, &itimer, NULL);
378 printf("BPF:\n");
379 bpf_dump_all(&bpf_ops);
380 printf("MD: RXTX %luus\n\n", interval);
381 printf("Running! Hang up with ^C!\n\n");
383 while (likely(sigint == 0)) {
384 while (user_may_pull_from_rx(rx_ring.frames[it_in].iov_base)) {
385 __label__ next;
386 hdr_in = rx_ring.frames[it_in].iov_base;
387 in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac;
388 fcnt++;
389 if (mode->packet_type != PACKET_ALL)
390 if (mode->packet_type != hdr_in->s_ll.sll_pkttype)
391 goto next;
393 hdr_out = tx_ring.frames[it_out].iov_base;
394 out = ((uint8_t *) hdr_out) + TPACKET2_HDRLEN -
395 sizeof(struct sockaddr_ll);
397 for (; !user_may_pull_from_tx(tx_ring.frames[it_out].iov_base) &&
398 likely(!sigint);) {
399 if (mode->randomize)
400 next_rnd_slot(&it_out, &tx_ring);
401 else
402 next_slot(&it_out, &tx_ring);
403 hdr_out = tx_ring.frames[it_out].iov_base;
404 out = ((uint8_t *) hdr_out) + TPACKET2_HDRLEN -
405 sizeof(struct sockaddr_ll);
408 tpacket_hdr_clone(&hdr_out->tp_h, &hdr_in->tp_h);
409 fmemcpy(out, in, hdr_in->tp_h.tp_len);
411 kernel_may_pull_from_tx(&hdr_out->tp_h);
412 if (mode->randomize)
413 next_rnd_slot(&it_out, &tx_ring);
414 else
415 next_slot(&it_out, &tx_ring);
417 show_frame_hdr(hdr_in, mode->print_mode, RING_MODE_INGRESS);
418 dissector_entry_point(in, hdr_in->tp_h.tp_snaplen,
419 mode->link_type, mode->print_mode);
421 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
422 sigint = 1;
423 break;
426 next:
428 kernel_may_pull_from_rx(&hdr_in->tp_h);
429 next_slot(&it_in, &rx_ring);
431 if (unlikely(sigint == 1))
432 goto out;
435 poll(&rx_poll, 1, -1);
436 poll_error_maybe_die(rx_sock, &rx_poll);
439 out:
441 sock_print_net_stats(rx_sock, 0);
443 bpf_release(&bpf_ops);
444 dissector_cleanup_all();
445 destroy_tx_ring(tx_sock, &tx_ring);
446 destroy_rx_ring(rx_sock, &rx_ring);
448 if (mode->promiscuous == true)
449 leave_promiscuous_mode(mode->device_in, ifflags);
451 close(tx_sock);
452 close(rx_sock);
455 static void enter_mode_read_pcap(struct mode *mode)
457 __label__ out;
458 int ret, fd, fdo = 0;
459 struct pcap_pkthdr phdr;
460 struct sock_fprog bpf_ops;
461 struct tx_stats stats;
462 struct frame_map fm;
463 uint8_t *out;
464 size_t out_len;
465 unsigned long trunced = 0;
466 struct timeval start, end, diff;
468 if (!pcap_ops[mode->pcap])
469 panic("pcap group not supported!\n");
470 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
471 ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type);
472 if (ret)
473 panic("error reading pcap header!\n");
474 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
475 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
476 if (ret)
477 panic("error prepare reading pcap!\n");
480 fmemset(&fm, 0, sizeof(fm));
481 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
482 fmemset(&stats, 0, sizeof(stats));
484 bpf_parse_rules(mode->filter, &bpf_ops);
485 dissector_init_all(mode->print_mode);
487 out_len = 64 * 1024;
488 out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE);
490 printf("BPF:\n");
491 bpf_dump_all(&bpf_ops);
492 printf("MD: RD %s ", pcap_ops[mode->pcap]->name);
493 #ifdef _LARGEFILE64_SOURCE
494 printf("lf64 ");
495 #endif
496 ioprio_print();
497 printf("\n");
499 if (mode->device_out) {
500 fdo = open_or_die_m(mode->device_out, O_RDWR | O_CREAT |
501 O_TRUNC | O_LARGEFILE, DEFFILEMODE);
504 bug_on(gettimeofday(&start, NULL));
506 while (likely(sigint == 0)) {
507 do {
508 memset(&phdr, 0, sizeof(phdr));
509 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
510 out, out_len);
511 if (unlikely(ret < 0))
512 goto out;
513 if (unlikely(phdr.len == 0)) {
514 trunced++;
515 continue;
517 if (unlikely(phdr.len > out_len)) {
518 phdr.len = out_len;
519 trunced++;
521 } while (mode->filter &&
522 !bpf_run_filter(&bpf_ops, out, phdr.len));
524 pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h);
526 stats.tx_bytes += fm.tp_h.tp_len;
527 stats.tx_packets++;
529 show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS);
530 dissector_entry_point(out, fm.tp_h.tp_snaplen,
531 mode->link_type, mode->print_mode);
533 if (mode->device_out) {
534 int i = 0;
535 char bout[80];
536 slprintf(bout, sizeof(bout), "{\n ");
537 write_or_die(fdo, bout, strlen(bout));
539 while (i < fm.tp_h.tp_snaplen) {
540 slprintf(bout, sizeof(bout), "0x%02x, ", out[i]);
541 write_or_die(fdo, bout, strlen(bout));
542 i++;
543 if (i % 10 == 0) {
544 slprintf(bout, sizeof(bout), "\n", out[i]);
545 write_or_die(fdo, bout, strlen(bout));
546 if (i < fm.tp_h.tp_snaplen) {
547 slprintf(bout, sizeof(bout), " ", out[i]);
548 write_or_die(fdo, bout, strlen(bout));
552 if (i % 10 != 0) {
553 slprintf(bout, sizeof(bout), "\n");
554 write_or_die(fdo, bout, strlen(bout));
556 slprintf(bout, sizeof(bout), "}\n\n");
557 write_or_die(fdo, bout, strlen(bout));
560 if (frame_cnt_max != 0 &&
561 stats.tx_packets >= frame_cnt_max) {
562 sigint = 1;
563 break;
567 out:
569 bug_on(gettimeofday(&end, NULL));
570 diff = tv_subtract(end, start);
572 fflush(stdout);
573 printf("\n");
574 printf("\r%12lu frames outgoing\n", stats.tx_packets);
575 printf("\r%12lu frames truncated (larger than mtu)\n", trunced);
576 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
577 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
579 xfree(out);
581 bpf_release(&bpf_ops);
582 dissector_cleanup_all();
583 if (pcap_ops[mode->pcap]->prepare_close_pcap)
584 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
585 close(fd);
587 if (mode->device_out)
588 close(fdo);
591 static void finish_multi_pcap_file(struct mode *mode, int fd)
593 pcap_ops[mode->pcap]->fsync_pcap(fd);
594 if (pcap_ops[mode->pcap]->prepare_close_pcap)
595 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
596 close(fd);
598 fmemset(&itimer, 0, sizeof(itimer));
599 setitimer(ITIMER_REAL, &itimer, NULL);
602 static int next_multi_pcap_file(struct mode *mode, int fd)
604 int ret;
605 char tmp[512];
607 pcap_ops[mode->pcap]->fsync_pcap(fd);
608 if (pcap_ops[mode->pcap]->prepare_close_pcap)
609 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
610 close(fd);
612 slprintf(tmp, sizeof(tmp), "%s/%s%lu.pcap",
613 mode->device_out, mode->prefix ? : "dump-", time(0));
615 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
616 DEFFILEMODE);
617 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
618 if (ret)
619 panic("error writing pcap header!\n");
620 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
621 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
622 if (ret)
623 panic("error prepare writing pcap!\n");
626 return fd;
629 static int begin_multi_pcap_file(struct mode *mode)
631 int fd, ret;
632 char tmp[512];
634 if (!pcap_ops[mode->pcap])
635 panic("pcap group not supported!\n");
636 if (mode->device_out[strlen(mode->device_out) - 1] == '/')
637 mode->device_out[strlen(mode->device_out) - 1] = 0;
639 slprintf(tmp, sizeof(tmp), "%s/%s%lu.pcap",
640 mode->device_out, mode->prefix ? : "dump-", time(0));
642 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
643 DEFFILEMODE);
644 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
645 if (ret)
646 panic("error writing pcap header!\n");
647 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
648 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
649 if (ret)
650 panic("error prepare writing pcap!\n");
653 if (mode->dump_mode == DUMP_INTERVAL_TIME) {
654 interval = mode->dump_interval;
656 itimer.it_interval.tv_sec = interval;
657 itimer.it_interval.tv_usec = 0;
658 itimer.it_value.tv_sec = interval;
659 itimer.it_value.tv_usec = 0;
661 setitimer(ITIMER_REAL, &itimer, NULL);
662 } else {
663 interval = 0;
666 return fd;
669 static void finish_single_pcap_file(struct mode *mode, int fd)
671 pcap_ops[mode->pcap]->fsync_pcap(fd);
672 if (pcap_ops[mode->pcap]->prepare_close_pcap)
673 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
674 close(fd);
677 static int begin_single_pcap_file(struct mode *mode)
679 int fd, ret;
681 if (!pcap_ops[mode->pcap])
682 panic("pcap group not supported!\n");
683 fd = open_or_die_m(mode->device_out,
684 O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
685 DEFFILEMODE);
686 ret = pcap_ops[mode->pcap]->push_file_header(fd, mode->link_type);
687 if (ret)
688 panic("error writing pcap header!\n");
689 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
690 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
691 if (ret)
692 panic("error prepare writing pcap!\n");
695 return fd;
698 static void enter_mode_rx_only_or_dump(struct mode *mode)
700 int sock, irq, ifindex, fd = 0, ret;
701 unsigned int size, it = 0;
702 unsigned long fcnt = 0, skipped = 0;
703 short ifflags = 0;
704 uint8_t *packet;
705 struct ring rx_ring;
706 struct pollfd rx_poll;
707 struct frame_map *hdr;
708 struct sock_fprog bpf_ops;
709 struct timeval start, end, diff;
711 if (!device_up_and_running(mode->device_in) &&
712 !mode->rfraw)
713 panic("Device not up and running!\n");
715 sock = pf_socket();
717 if (mode->rfraw) {
718 mode->device_trans = xstrdup(mode->device_in);
719 xfree(mode->device_in);
721 enter_rfmon_mac80211(mode->device_trans, &mode->device_in);
722 mode->link_type = LINKTYPE_IEEE802_11;
725 if (mode->dump) {
726 __label__ try_file;
727 struct stat tmp;
729 fmemset(&tmp, 0, sizeof(tmp));
730 ret = stat(mode->device_out, &tmp);
731 if (ret < 0) {
732 mode->dump_dir = 0;
733 goto try_file;
735 mode->dump_dir = !!S_ISDIR(tmp.st_mode);
736 if (mode->dump_dir) {
737 fd = begin_multi_pcap_file(mode);
738 } else {
739 try_file:
740 fd = begin_single_pcap_file(mode);
744 fmemset(&rx_ring, 0, sizeof(rx_ring));
745 fmemset(&rx_poll, 0, sizeof(rx_poll));
746 fmemset(&bpf_ops, 0, sizeof(bpf_ops));
748 ifindex = device_ifindex(mode->device_in);
749 size = ring_size(mode->device_in, mode->reserve_size);
751 enable_kernel_bpf_jit_compiler();
752 bpf_parse_rules(mode->filter, &bpf_ops);
753 bpf_attach_to_sock(sock, &bpf_ops);
755 set_sockopt_hwtimestamp(sock, mode->device_in);
756 setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support);
757 create_rx_ring(sock, &rx_ring);
758 mmap_rx_ring(sock, &rx_ring);
759 alloc_rx_ring_frames(&rx_ring);
760 bind_rx_ring(sock, &rx_ring, ifindex);
762 prepare_polling(sock, &rx_poll);
763 dissector_init_all(mode->print_mode);
765 if (mode->cpu >= 0 && ifindex > 0) {
766 irq = device_irq_number(mode->device_in);
767 device_bind_irq_to_cpu(mode->cpu, irq);
768 printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq,
769 mode->cpu);
772 if (mode->promiscuous == true) {
773 ifflags = enter_promiscuous_mode(mode->device_in);
774 printf("PROMISC\n");
777 printf("BPF:\n");
778 bpf_dump_all(&bpf_ops);
779 printf("MD: RX %s ", mode->dump ? pcap_ops[mode->pcap]->name : "");
780 if (mode->rfraw)
781 printf("802.11 raw via %s ", mode->device_in);
782 #ifdef _LARGEFILE64_SOURCE
783 printf("lf64 ");
784 #endif
785 ioprio_print();
786 printf("\n");
788 bug_on(gettimeofday(&start, NULL));
790 while (likely(sigint == 0)) {
791 while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
792 __label__ next;
794 hdr = rx_ring.frames[it].iov_base;
795 packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
796 fcnt++;
798 if (mode->packet_type != PACKET_ALL)
799 if (mode->packet_type != hdr->s_ll.sll_pkttype)
800 goto next;
801 if (unlikely(ring_frame_size(&rx_ring) <
802 hdr->tp_h.tp_snaplen)) {
803 skipped++;
804 goto next;
806 if (mode->dump) {
807 struct pcap_pkthdr phdr;
808 tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr);
809 ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr,
810 packet, phdr.len);
811 if (unlikely(ret != sizeof(phdr) + phdr.len))
812 panic("Write error to pcap!\n");
815 show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS);
816 dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
817 mode->link_type, mode->print_mode);
819 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
820 sigint = 1;
821 break;
824 next:
826 kernel_may_pull_from_rx(&hdr->tp_h);
827 next_slot(&it, &rx_ring);
829 if (unlikely(sigint == 1))
830 break;
832 if (mode->dump) {
833 if (mode->dump_mode == DUMP_INTERVAL_SIZE) {
834 interval += hdr->tp_h.tp_snaplen;
835 if (interval > mode->dump_interval) {
836 next_dump = true;
837 interval = 0;
841 if (next_dump) {
842 struct tpacket_stats kstats;
843 socklen_t slen = sizeof(kstats);
845 fmemset(&kstats, 0, sizeof(kstats));
846 getsockopt(sock, SOL_PACKET, PACKET_STATISTICS,
847 &kstats, &slen);
849 fd = next_multi_pcap_file(mode, fd);
850 next_dump = false;
852 if (mode->print_mode == FNTTYPE_PRINT_NONE) {
853 printf(".(+%lu/-%lu)",
854 1UL * kstats.tp_packets -
855 kstats.tp_drops -
856 skipped, 1UL * kstats.tp_drops +
857 skipped);
858 fflush(stdout);
864 poll(&rx_poll, 1, -1);
865 poll_error_maybe_die(sock, &rx_poll);
868 bug_on(gettimeofday(&end, NULL));
869 diff = tv_subtract(end, start);
871 if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) {
872 sock_print_net_stats(sock, skipped);
873 printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec,
874 diff.tv_usec);
875 } else {
876 printf("\n\n");
877 fflush(stdout);
880 bpf_release(&bpf_ops);
881 dissector_cleanup_all();
882 destroy_rx_ring(sock, &rx_ring);
884 if (mode->promiscuous == true)
885 leave_promiscuous_mode(mode->device_in, ifflags);
887 if (mode->rfraw)
888 leave_rfmon_mac80211(mode->device_trans, mode->device_in);
890 close(sock);
892 if (mode->dump) {
893 if (mode->dump_dir)
894 finish_multi_pcap_file(mode, fd);
895 else
896 finish_single_pcap_file(mode, fd);
900 static void help(void)
902 printf("\nnetsniff-ng %s, the packet sniffing beast\n", VERSION_STRING);
903 puts("http://www.netsniff-ng.org\n\n"
904 "Usage: netsniff-ng [options]\n"
905 "Options:\n"
906 " -i|-d|--dev|--in <dev|pcap> Input source as netdev or pcap\n"
907 " -o|--out <dev|pcap|dir|txf> Output sink as netdev, pcap, directory, txf file\n"
908 " -f|--filter <bpf-file> Use BPF filter file from bpfc\n"
909 " -t|--type <type> Only handle packets of defined type:\n"
910 " host|broadcast|multicast|others|outgoing\n"
911 " -F|--interval <size/time> Dump interval in time or size if -o is a directory\n"
912 " pcap swap spec: <num>KiB/MiB/GiB/s/sec/min/hrs\n"
913 " -J|--jumbo-support Support for 64KB Super Jumbo Frames\n"
914 " Default RX/TX slot: 2048Byte\n"
915 " -R|--rfraw Capture or inject raw 802.11 frames\n"
916 " -n|--num <uint> Number of packets until exit\n"
917 " `-- 0 Loop until interrupted (default)\n"
918 " `- n Send n packets and done\n"
919 "Options for printing:\n"
920 " -s|--silent Do not print captured packets\n"
921 " -q|--less Print less-verbose packet information\n"
922 " -X|--hex Print packet data in hex format\n"
923 " -l|--ascii Print human-readable packet data\n"
924 "Options, advanced:\n"
925 " -P|--prefix <name> Prefix for pcaps stored in directory\n"
926 " -r|--rand Randomize packet forwarding order\n"
927 " -M|--no-promisc No promiscuous mode for netdev\n"
928 " -A|--no-sock-mem Don't tune core socket memory\n"
929 " -m|--mmap Mmap pcap file i.e., for replaying\n"
930 " -g|--sg Scatter/gather pcap file I/O\n"
931 " -c|--clrw Use slower read(2)/write(2) I/O\n"
932 " -S|--ring-size <size> Manually set ring size to <size>:\n"
933 " mmap space in KiB/MiB/GiB, e.g. \'10MiB\'\n"
934 " -k|--kernel-pull <uint> Kernel pull from user interval in us\n"
935 " Default is 10us where the TX_RING\n"
936 " is populated with payload from uspace\n"
937 " -b|--bind-cpu <cpu> Bind to specific CPU (or CPU-range)\n"
938 " -B|--unbind-cpu <cpu> Forbid to use specific CPU (or CPU-range)\n"
939 " -H|--prio-high Make this high priority process\n"
940 " -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n"
941 " -v|--version Show version\n"
942 " -h|--help Guess what?!\n\n"
943 "Examples:\n"
944 " netsniff-ng --in eth0 --out dump.pcap --silent --bind-cpu 0\n"
945 " netsniff-ng --in wlan0 --rfraw --out dump.pcap --silent --bind-cpu 0\n"
946 " netsniff-ng --in dump.pcap --mmap --out eth0 --silent --bind-cpu 0\n"
947 " netsniff-ng --in dump.pcap --out dump.txf --silent --bind-cpu 0\n"
948 " netsniff-ng --in eth0 --out eth1 --silent --bind-cpu 0 --type host\n"
949 " netsniff-ng --in eth1 --out /opt/probe/ -s -m -J --interval 100MiB -b 0\n"
950 " netsniff-ng --in any --filter http.bpf --jumbo-support --ascii\n\n"
951 "Note:\n"
952 " This tool is targeted for network developers! You should\n"
953 " be aware of what you are doing and what these options above\n"
954 " mean! Use netsniff-ng's bpfc compiler for generating filter files.\n"
955 " Further, netsniff-ng automatically enables the kernel BPF JIT\n"
956 " if present. Txf file output is only possible if the input source\n"
957 " is a pcap file.\n\n"
958 "Please report bugs to <bugs@netsniff-ng.org>\n"
959 "Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n"
960 "Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n"
961 "Copyright (C) 2012 Markus Amend <markus@netsniff-ng.org>\n"
962 "License: GNU GPL version 2.0\n"
963 "This is free software: you are free to change and redistribute it.\n"
964 "There is NO WARRANTY, to the extent permitted by law.\n");
965 die();
968 static void version(void)
970 printf("\nnetsniff-ng %s, the packet sniffing beast\n", VERSION_STRING);
971 puts("http://www.netsniff-ng.org\n\n"
972 "Please report bugs to <bugs@netsniff-ng.org>\n"
973 "Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n"
974 "Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n"
975 "Copyright (C) 2012 Markus Amend <markus@netsniff-ng.org>\n"
976 "License: GNU GPL version 2.0\n"
977 "This is free software: you are free to change and redistribute it.\n"
978 "There is NO WARRANTY, to the extent permitted by law.\n");
979 die();
982 static void header(void)
984 printf("%s%s%s\n",
985 colorize_start(bold),
986 "netsniff-ng " VERSION_STRING,
987 colorize_end());
990 int main(int argc, char **argv)
992 int c, i, j, opt_index, ops_touched = 0;
993 int vals[4] = {0};
994 char *ptr;
995 bool prio_high = false;
996 bool setsockmem = true;
997 struct mode mode;
998 void (*enter_mode)(struct mode *mode) = NULL;
1000 fmemset(&mode, 0, sizeof(mode));
1001 mode.link_type = LINKTYPE_EN10MB;
1002 mode.print_mode = FNTTYPE_PRINT_NORM;
1003 mode.cpu = CPU_UNKNOWN;
1004 mode.packet_type = PACKET_ALL;
1005 mode.promiscuous = true;
1006 mode.randomize = false;
1007 mode.pcap = PCAP_OPS_SG;
1008 mode.dump_interval = DUMP_INTERVAL_DEF;
1009 mode.dump_mode = DUMP_INTERVAL_TIME;
1011 while ((c = getopt_long(argc, argv, short_options, long_options,
1012 &opt_index)) != EOF) {
1013 switch (c) {
1014 case 'd':
1015 case 'i':
1016 mode.device_in = xstrdup(optarg);
1017 break;
1018 case 'o':
1019 mode.device_out = xstrdup(optarg);
1020 break;
1021 case 'P':
1022 mode.prefix = xstrdup(optarg);
1023 break;
1024 case 'R':
1025 mode.link_type = LINKTYPE_IEEE802_11;
1026 mode.rfraw = 1;
1027 break;
1028 case 'r':
1029 mode.randomize = true;
1030 break;
1031 case 'J':
1032 mode.jumbo_support = 1;
1033 break;
1034 case 'f':
1035 mode.filter = xstrdup(optarg);
1036 break;
1037 case 'M':
1038 mode.promiscuous = false;
1039 break;
1040 case 'A':
1041 setsockmem = false;
1042 break;
1043 case 't':
1044 if (!strncmp(optarg, "host", strlen("host")))
1045 mode.packet_type = PACKET_HOST;
1046 else if (!strncmp(optarg, "broadcast", strlen("broadcast")))
1047 mode.packet_type = PACKET_BROADCAST;
1048 else if (!strncmp(optarg, "multicast", strlen("multicast")))
1049 mode.packet_type = PACKET_MULTICAST;
1050 else if (!strncmp(optarg, "others", strlen("others")))
1051 mode.packet_type = PACKET_OTHERHOST;
1052 else if (!strncmp(optarg, "outgoing", strlen("outgoing")))
1053 mode.packet_type = PACKET_OUTGOING;
1054 else
1055 mode.packet_type = PACKET_ALL;
1056 break;
1057 case 'S':
1058 ptr = optarg;
1059 mode.reserve_size = 0;
1061 for (j = i = strlen(optarg); i > 0; --i) {
1062 if (!isdigit(optarg[j - i]))
1063 break;
1064 ptr++;
1067 if (!strncmp(ptr, "KiB", strlen("KiB")))
1068 mode.reserve_size = 1 << 10;
1069 else if (!strncmp(ptr, "MiB", strlen("MiB")))
1070 mode.reserve_size = 1 << 20;
1071 else if (!strncmp(ptr, "GiB", strlen("GiB")))
1072 mode.reserve_size = 1 << 30;
1073 else
1074 panic("Syntax error in ring size param!\n");
1076 *ptr = 0;
1077 mode.reserve_size *= atoi(optarg);
1078 break;
1079 case 'b':
1080 set_cpu_affinity(optarg, 0);
1081 if (mode.cpu != CPU_NOTOUCH)
1082 mode.cpu = atoi(optarg);
1083 break;
1084 case 'B':
1085 set_cpu_affinity(optarg, 1);
1086 break;
1087 case 'H':
1088 prio_high = true;
1089 break;
1090 case 'c':
1091 mode.pcap = PCAP_OPS_RW;
1092 ops_touched = 1;
1093 break;
1094 case 'm':
1095 mode.pcap = PCAP_OPS_MMAP;
1096 ops_touched = 1;
1097 break;
1098 case 'g':
1099 mode.pcap = PCAP_OPS_SG;
1100 ops_touched = 1;
1101 break;
1102 case 'Q':
1103 mode.cpu = CPU_NOTOUCH;
1104 break;
1105 case 's':
1106 mode.print_mode = FNTTYPE_PRINT_NONE;
1107 break;
1108 case 'q':
1109 mode.print_mode = FNTTYPE_PRINT_LESS;
1110 break;
1111 case 'X':
1112 mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_ASCII) ?
1113 FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_HEX;
1114 break;
1115 case 'l':
1116 mode.print_mode = (mode.print_mode == FNTTYPE_PRINT_HEX) ?
1117 FNTTYPE_PRINT_HEX_ASCII : FNTTYPE_PRINT_ASCII;
1118 break;
1119 case 'k':
1120 mode.kpull = (unsigned long) atol(optarg);
1121 break;
1122 case 'n':
1123 frame_cnt_max = (unsigned long) atol(optarg);
1124 break;
1125 case 'F':
1126 ptr = optarg;
1127 mode.dump_interval = 0;
1129 for (j = i = strlen(optarg); i > 0; --i) {
1130 if (!isdigit(optarg[j - i]))
1131 break;
1132 ptr++;
1135 if (!strncmp(ptr, "KiB", strlen("KiB"))) {
1136 mode.dump_interval = 1 << 10;
1137 mode.dump_mode = DUMP_INTERVAL_SIZE;
1138 } else if (!strncmp(ptr, "MiB", strlen("MiB"))) {
1139 mode.dump_interval = 1 << 20;
1140 mode.dump_mode = DUMP_INTERVAL_SIZE;
1141 } else if (!strncmp(ptr, "GiB", strlen("GiB"))) {
1142 mode.dump_interval = 1 << 30;
1143 mode.dump_mode = DUMP_INTERVAL_SIZE;
1144 } else if (!strncmp(ptr, "sec", strlen("sec"))) {
1145 mode.dump_interval = 1;
1146 mode.dump_mode = DUMP_INTERVAL_TIME;
1147 } else if (!strncmp(ptr, "min", strlen("min"))) {
1148 mode.dump_interval = 60;
1149 mode.dump_mode = DUMP_INTERVAL_TIME;
1150 } else if (!strncmp(ptr, "hrs", strlen("hrs"))) {
1151 mode.dump_interval = 60 * 60;
1152 mode.dump_mode = DUMP_INTERVAL_TIME;
1153 } else if (!strncmp(ptr, "s", strlen("s"))) {
1154 mode.dump_interval = 1;
1155 mode.dump_mode = DUMP_INTERVAL_TIME;
1156 } else {
1157 panic("Syntax error in time/size param!\n");
1160 *ptr = 0;
1161 mode.dump_interval *= (unsigned long) atoi(optarg);
1162 break;
1163 case 'v':
1164 version();
1165 break;
1166 case 'h':
1167 help();
1168 break;
1169 case '?':
1170 switch (optopt) {
1171 case 'd':
1172 case 'i':
1173 case 'o':
1174 case 'f':
1175 case 't':
1176 case 'P':
1177 case 'F':
1178 case 'n':
1179 case 'S':
1180 case 'b':
1181 case 'k':
1182 case 'B':
1183 case 'e':
1184 panic("Option -%c requires an argument!\n",
1185 optopt);
1186 default:
1187 if (isprint(optopt))
1188 whine("Unknown option character "
1189 "`0x%X\'!\n", optopt);
1190 die();
1192 default:
1193 break;
1197 if (!mode.device_in)
1198 mode.device_in = xstrdup("any");
1200 register_signal(SIGINT, signal_handler);
1201 register_signal(SIGHUP, signal_handler);
1203 init_pcap(mode.jumbo_support);
1204 tprintf_init();
1205 header();
1207 if (prio_high == true) {
1208 set_proc_prio(get_default_proc_prio());
1209 set_sched_status(get_default_sched_policy(),
1210 get_default_sched_prio());
1213 if (setsockmem == true) {
1214 if ((vals[0] = get_system_socket_mem(sock_rmem_max)) < SMEM_SUG_MAX)
1215 set_system_socket_mem(sock_rmem_max, SMEM_SUG_MAX);
1216 if ((vals[1] = get_system_socket_mem(sock_rmem_def)) < SMEM_SUG_DEF)
1217 set_system_socket_mem(sock_rmem_def, SMEM_SUG_DEF);
1218 if ((vals[2] = get_system_socket_mem(sock_wmem_max)) < SMEM_SUG_MAX)
1219 set_system_socket_mem(sock_wmem_max, SMEM_SUG_MAX);
1220 if ((vals[3] = get_system_socket_mem(sock_wmem_def)) < SMEM_SUG_DEF)
1221 set_system_socket_mem(sock_wmem_def, SMEM_SUG_DEF);
1224 if (mode.device_in && (device_mtu(mode.device_in) ||
1225 !strncmp("any", mode.device_in, strlen(mode.device_in)))) {
1226 if (!mode.device_out) {
1227 mode.dump = 0;
1228 enter_mode = enter_mode_rx_only_or_dump;
1229 } else if (device_mtu(mode.device_out)) {
1230 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1231 enter_mode = enter_mode_rx_to_tx;
1232 } else {
1233 mode.dump = 1;
1234 register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO);
1235 enter_mode = enter_mode_rx_only_or_dump;
1236 if (!ops_touched)
1237 mode.pcap = PCAP_OPS_SG;
1239 } else {
1240 if (mode.device_out && device_mtu(mode.device_out)) {
1241 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1242 enter_mode = enter_mode_pcap_to_tx;
1243 if (!ops_touched)
1244 mode.pcap = PCAP_OPS_MMAP;
1245 } else {
1246 enter_mode = enter_mode_read_pcap;
1247 if (!ops_touched)
1248 mode.pcap = PCAP_OPS_SG;
1252 if (!enter_mode)
1253 panic("Selection not supported!\n");
1254 enter_mode(&mode);
1256 tprintf_cleanup();
1257 cleanup_pcap();
1259 if (setsockmem == true) {
1260 set_system_socket_mem(sock_rmem_max, vals[0]);
1261 set_system_socket_mem(sock_rmem_def, vals[1]);
1262 set_system_socket_mem(sock_wmem_max, vals[2]);
1263 set_system_socket_mem(sock_wmem_def, vals[3]);
1266 free(mode.device_in);
1267 free(mode.device_out);
1268 free(mode.device_trans);
1269 free(mode.prefix);
1271 return 0;