xsys: included psched routines into xsys
[netsniff-ng.git] / src / netsniff-ng.c
blob35f8f051b9bd3ed250560abb8da1300126067cf1
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 "xsys.h"
43 #include "compiler.h"
44 #include "pcap.h"
45 #include "bpf.h"
46 #include "xio.h"
47 #include "die.h"
48 #include "opt_memcpy.h"
49 #include "tprintf.h"
50 #include "dissector.h"
51 #include "xmalloc.h"
52 #include "mtrand.h"
54 #define CPU_UNKNOWN -1
55 #define CPU_NOTOUCH -2
56 #define PACKET_ALL -1
57 #define DUMP_INTERVAL 60
59 struct mode {
60 char *device_in;
61 char *device_out;
62 char *filter;
63 int cpu;
64 int dump;
65 int link_type;
66 int print_mode;
67 unsigned int reserve_size;
68 int packet_type;
69 bool randomize;
70 bool promiscuous;
71 enum pcap_ops_groups pcap;
72 unsigned long kpull;
73 int jumbo_support;
74 int dump_dir;
75 unsigned long dump_interval;
78 struct tx_stats {
79 unsigned long tx_bytes;
80 unsigned long tx_packets;
83 sig_atomic_t sigint = 0;
85 static int tx_sock;
86 static unsigned long frame_cnt_max = 0;
87 static unsigned long interval = TX_KERNEL_PULL_INT;
88 static struct itimerval itimer;
89 static volatile bool next_dump = false;
91 static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:B:HQmcsqlxCXNvhF:";
93 static struct option long_options[] = {
94 {"dev", required_argument, 0, 'd'},
95 {"in", required_argument, 0, 'i'},
96 {"out", required_argument, 0, 'o'},
97 {"rand", no_argument, 0, 'r'},
98 {"mmap", no_argument, 0, 'm'},
99 {"clrw", no_argument, 0, 'c'},
100 {"jumbo-support", no_argument, 0, 'J'},
101 {"filter", required_argument, 0, 'f'},
102 {"no-promisc", no_argument, 0, 'M'},
103 {"num", required_argument, 0, 'n'},
104 {"type", required_argument, 0, 't'},
105 {"interval", required_argument, 0, 'F'},
106 {"ring-size", required_argument, 0, 'S'},
107 {"kernel-pull", required_argument, 0, 'k'},
108 {"bind-cpu", required_argument, 0, 'b'},
109 {"unbind-cpu", required_argument, 0, 'B'},
110 {"prio-high", no_argument, 0, 'H'},
111 {"notouch-irq", no_argument, 0, 'Q'},
112 {"silent", no_argument, 0, 's'},
113 {"less", no_argument, 0, 'q'},
114 {"payload", no_argument, 0, 'l'},
115 {"payload-hex", no_argument, 0, 'x'},
116 {"c-style", no_argument, 0, 'C'},
117 {"all-hex", no_argument, 0, 'X'},
118 {"no-payload", no_argument, 0, 'N'},
119 {"version", no_argument, 0, 'v'},
120 {"help", no_argument, 0, 'h'},
121 {0, 0, 0, 0}
124 static void signal_handler(int number)
126 switch (number) {
127 case SIGINT:
128 sigint = 1;
129 break;
130 case SIGHUP:
131 break;
132 default:
133 break;
137 static void timer_elapsed(int number)
139 itimer.it_interval.tv_sec = 0;
140 itimer.it_interval.tv_usec = interval;
141 itimer.it_value.tv_sec = 0;
142 itimer.it_value.tv_usec = interval;
144 pull_and_flush_tx_ring(tx_sock);
145 setitimer(ITIMER_REAL, &itimer, NULL);
148 static void timer_next_dump(int number)
150 itimer.it_interval.tv_sec = interval;
151 itimer.it_interval.tv_usec = 0;
152 itimer.it_value.tv_sec = interval;
153 itimer.it_value.tv_usec = 0;
155 next_dump = true;
156 setitimer(ITIMER_REAL, &itimer, NULL);
159 static void enter_mode_pcap_to_tx(struct mode *mode)
161 int irq, ifindex, fd = 0, ret;
162 unsigned int size, it = 0;
163 struct ring tx_ring;
164 struct frame_map *hdr;
165 struct sock_fprog bpf_ops;
166 struct tx_stats stats;
167 uint8_t *out = NULL;
169 if (!device_up_and_running(mode->device_out))
170 panic("Device not up and running!\n");
172 set_memcpy();
173 tx_sock = pf_socket();
175 if (!pcap_ops[mode->pcap])
176 panic("pcap group not supported!\n");
177 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
178 ret = pcap_ops[mode->pcap]->pull_file_header(fd);
179 if (ret)
180 panic("error reading pcap header!\n");
181 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
182 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
183 if (ret)
184 panic("error prepare reading pcap!\n");
187 memset(&tx_ring, 0, sizeof(tx_ring));
188 memset(&bpf_ops, 0, sizeof(bpf_ops));
189 memset(&stats, 0, sizeof(stats));
191 ifindex = device_ifindex(mode->device_out);
192 size = ring_size(mode->device_out, mode->reserve_size);
194 bpf_parse_rules(mode->filter, &bpf_ops);
196 set_packet_loss_discard(tx_sock);
197 setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support);
198 create_tx_ring(tx_sock, &tx_ring);
199 mmap_tx_ring(tx_sock, &tx_ring);
200 alloc_tx_ring_frames(&tx_ring);
201 bind_tx_ring(tx_sock, &tx_ring, ifindex);
203 dissector_init_all(mode->print_mode);
205 if (mode->cpu >= 0 && ifindex > 0) {
206 irq = device_irq_number(mode->device_out);
207 device_bind_irq_to_cpu(mode->cpu, irq);
208 printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq,
209 mode->cpu);
212 if (mode->kpull)
213 interval = mode->kpull;
215 itimer.it_interval.tv_sec = 0;
216 itimer.it_interval.tv_usec = interval;
217 itimer.it_value.tv_sec = 0;
218 itimer.it_value.tv_usec = interval;
219 setitimer(ITIMER_REAL, &itimer, NULL);
221 printf("BPF:\n");
222 bpf_dump_all(&bpf_ops);
223 printf("MD: TX %luus %s\n\n", interval, pcap_ops[mode->pcap]->name);
225 while (likely(sigint == 0)) {
226 while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) {
227 struct pcap_pkthdr phdr;
228 hdr = tx_ring.frames[it].iov_base;
229 /* Kernel assumes: data = ph.raw + po->tp_hdrlen -
230 * sizeof(struct sockaddr_ll); */
231 out = ((uint8_t *) hdr) + TPACKET_HDRLEN -
232 sizeof(struct sockaddr_ll);
234 do {
235 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
236 out, ring_frame_size(&tx_ring));
237 if (unlikely(ret <= 0))
238 goto out;
239 } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len));
240 pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h);
242 stats.tx_bytes += hdr->tp_h.tp_len;;
243 stats.tx_packets++;
245 show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS);
246 dissector_entry_point(out, hdr->tp_h.tp_snaplen,
247 mode->link_type);
249 kernel_may_pull_from_tx(&hdr->tp_h);
250 next_slot(&it, &tx_ring);
252 if (unlikely(sigint == 1))
253 break;
254 if (frame_cnt_max != 0 &&
255 stats.tx_packets >= frame_cnt_max) {
256 sigint = 1;
257 break;
261 out:
262 fflush(stdout);
263 printf("\n");
264 printf("\r%12lu frames outgoing\n", stats.tx_packets);
265 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
267 dissector_cleanup_all();
268 destroy_tx_ring(tx_sock, &tx_ring);
270 close(tx_sock);
271 if (pcap_ops[mode->pcap]->prepare_close_pcap)
272 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
273 close(fd);
276 /* If netsniff-ngs in device is on a tap, it can efficiently filter out
277 * some interesting packets and give them to the out device for testing
278 * or debugging for instance. */
279 static void enter_mode_rx_to_tx(struct mode *mode)
281 int rx_sock, ifindex_in, ifindex_out;
282 unsigned int size_in, size_out, it_in = 0, it_out = 0;
283 unsigned long fcnt = 0;
284 uint8_t *in, *out;
285 short ifflags = 0;
286 struct frame_map *hdr_in, *hdr_out;
287 struct ring tx_ring;
288 struct ring rx_ring;
289 struct pollfd rx_poll;
290 struct sock_fprog bpf_ops;
292 if (!strncmp(mode->device_in, mode->device_out,
293 strlen(mode->device_in)))
294 panic("Ingress/egress devices must be different!\n");
295 if (!device_up_and_running(mode->device_out))
296 panic("Egress device not up and running!\n");
297 if (!device_up_and_running(mode->device_in))
298 panic("Ingress device not up and running!\n");
300 set_memcpy();
301 rx_sock = pf_socket();
302 tx_sock = pf_socket();
304 memset(&tx_ring, 0, sizeof(tx_ring));
305 memset(&rx_ring, 0, sizeof(rx_ring));
306 memset(&rx_poll, 0, sizeof(rx_poll));
307 memset(&bpf_ops, 0, sizeof(bpf_ops));
309 ifindex_in = device_ifindex(mode->device_in);
310 size_in = ring_size(mode->device_in, mode->reserve_size);
312 ifindex_out = device_ifindex(mode->device_out);
313 size_out = ring_size(mode->device_out, mode->reserve_size);
315 enable_kernel_bpf_jit_compiler();
316 bpf_parse_rules(mode->filter, &bpf_ops);
317 bpf_attach_to_sock(rx_sock, &bpf_ops);
319 setup_rx_ring_layout(rx_sock, &rx_ring, size_in, mode->jumbo_support);
320 create_rx_ring(rx_sock, &rx_ring);
321 mmap_rx_ring(rx_sock, &rx_ring);
322 alloc_rx_ring_frames(&rx_ring);
323 bind_rx_ring(rx_sock, &rx_ring, ifindex_in);
324 prepare_polling(rx_sock, &rx_poll);
326 set_packet_loss_discard(tx_sock);
327 setup_tx_ring_layout(tx_sock, &tx_ring, size_out, mode->jumbo_support);
328 create_tx_ring(tx_sock, &tx_ring);
329 mmap_tx_ring(tx_sock, &tx_ring);
330 alloc_tx_ring_frames(&tx_ring);
331 bind_tx_ring(tx_sock, &tx_ring, ifindex_out);
333 mt_init_by_seed_time();
334 dissector_init_all(mode->print_mode);
336 if (mode->promiscuous == true) {
337 ifflags = enter_promiscuous_mode(mode->device_in);
338 printf("PROMISC\n");
341 if (mode->kpull)
342 interval = mode->kpull;
344 itimer.it_interval.tv_sec = 0;
345 itimer.it_interval.tv_usec = interval;
346 itimer.it_value.tv_sec = 0;
347 itimer.it_value.tv_usec = interval;
348 setitimer(ITIMER_REAL, &itimer, NULL);
350 printf("BPF:\n");
351 bpf_dump_all(&bpf_ops);
352 printf("MD: RXTX %luus\n\n", interval);
353 printf("Running! Hang up with ^C!\n\n");
355 while (likely(sigint == 0)) {
356 while (user_may_pull_from_rx(rx_ring.frames[it_in].iov_base)) {
357 hdr_in = rx_ring.frames[it_in].iov_base;
358 in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac;
359 fcnt++;
360 if (mode->packet_type != PACKET_ALL)
361 if (mode->packet_type != hdr_in->s_ll.sll_pkttype)
362 goto next;
364 hdr_out = tx_ring.frames[it_out].iov_base;
365 out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN -
366 sizeof(struct sockaddr_ll);
368 /* If we cannot pull, look for a different slot. */
369 for (; !user_may_pull_from_tx(tx_ring.frames[it_out].iov_base) &&
370 likely(!sigint);) {
371 if (mode->randomize)
372 next_rnd_slot(&it_out, &tx_ring);
373 else
374 next_slot(&it_out, &tx_ring);
375 hdr_out = tx_ring.frames[it_out].iov_base;
376 out = ((uint8_t *) hdr_out) + TPACKET_HDRLEN -
377 sizeof(struct sockaddr_ll);
380 tpacket_hdr_clone(&hdr_out->tp_h, &hdr_in->tp_h);
381 __memcpy(out, in, hdr_in->tp_h.tp_len);
383 kernel_may_pull_from_tx(&hdr_out->tp_h);
384 if (mode->randomize)
385 next_rnd_slot(&it_out, &tx_ring);
386 else
387 next_slot(&it_out, &tx_ring);
389 /* Should actually be avoided ... */
390 show_frame_hdr(hdr_in, mode->print_mode, RING_MODE_INGRESS);
391 dissector_entry_point(in, hdr_in->tp_h.tp_snaplen,
392 mode->link_type);
394 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
395 sigint = 1;
396 break;
398 next:
399 kernel_may_pull_from_rx(&hdr_in->tp_h);
400 next_slot(&it_in, &rx_ring);
402 if (unlikely(sigint == 1))
403 goto out;
406 poll(&rx_poll, 1, -1);
407 poll_error_maybe_die(rx_sock, &rx_poll);
409 out:
410 sock_print_net_stats(rx_sock);
412 dissector_cleanup_all();
413 destroy_tx_ring(tx_sock, &tx_ring);
414 destroy_rx_ring(rx_sock, &rx_ring);
416 if (mode->promiscuous == true)
417 leave_promiscuous_mode(mode->device_in, ifflags);
419 close(tx_sock);
420 close(rx_sock);
423 static void enter_mode_read_pcap(struct mode *mode)
425 int ret, fd;
426 struct pcap_pkthdr phdr;
427 struct sock_fprog bpf_ops;
428 struct tx_stats stats;
429 struct frame_map fm;
430 uint8_t *out;
431 size_t out_len;
433 if (!pcap_ops[mode->pcap])
434 panic("pcap group not supported!\n");
435 fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
436 ret = pcap_ops[mode->pcap]->pull_file_header(fd);
437 if (ret)
438 panic("error reading pcap header!\n");
439 if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
440 ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
441 if (ret)
442 panic("error prepare reading pcap!\n");
445 memset(&fm, 0, sizeof(fm));
446 memset(&bpf_ops, 0, sizeof(bpf_ops));
447 memset(&stats, 0, sizeof(stats));
449 bpf_parse_rules(mode->filter, &bpf_ops);
450 dissector_init_all(mode->print_mode);
452 out_len = device_mtu("lo");
453 out = xmalloc_aligned(out_len, 64);
455 printf("BPF:\n");
456 bpf_dump_all(&bpf_ops);
457 printf("MD: RD %s\n\n", pcap_ops[mode->pcap]->name);
459 while (likely(sigint == 0)) {
460 do {
461 ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
462 out, out_len);
463 if (unlikely(ret <= 0))
464 goto out;
465 } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len));
466 pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h);
468 stats.tx_bytes += fm.tp_h.tp_len;;
469 stats.tx_packets++;
471 show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS);
472 dissector_entry_point(out, fm.tp_h.tp_snaplen,
473 mode->link_type);
475 if (frame_cnt_max != 0 &&
476 stats.tx_packets >= frame_cnt_max) {
477 sigint = 1;
478 break;
481 out:
482 fflush(stdout);
483 printf("\n");
484 printf("\r%12lu frames outgoing\n", stats.tx_packets);
485 printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
487 xfree(out);
488 dissector_cleanup_all();
489 if (pcap_ops[mode->pcap]->prepare_close_pcap)
490 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
491 close(fd);
494 static void finish_multi_pcap_file(struct mode *mode, int fd)
496 pcap_ops[mode->pcap]->fsync_pcap(fd);
497 if (pcap_ops[mode->pcap]->prepare_close_pcap)
498 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
499 close(fd);
501 memset(&itimer, 0, sizeof(itimer));
502 setitimer(ITIMER_REAL, &itimer, NULL);
505 static int next_multi_pcap_file(struct mode *mode, int fd)
507 int ret;
508 char tmp[512];
510 pcap_ops[mode->pcap]->fsync_pcap(fd);
511 if (pcap_ops[mode->pcap]->prepare_close_pcap)
512 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
513 close(fd);
515 memset(&tmp, 0, sizeof(tmp));
516 snprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
517 tmp[sizeof(tmp) - 1] = 0;
519 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
520 S_IRUSR | S_IWUSR);
521 ret = pcap_ops[mode->pcap]->push_file_header(fd);
522 if (ret)
523 panic("error writing pcap header!\n");
524 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
525 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
526 if (ret)
527 panic("error prepare writing pcap!\n");
530 return fd;
533 static int begin_multi_pcap_file(struct mode *mode)
535 int fd, ret;
536 char tmp[512];
538 if (!pcap_ops[mode->pcap])
539 panic("pcap group not supported!\n");
540 if (mode->device_out[strlen(mode->device_out) - 1] == '/')
541 mode->device_out[strlen(mode->device_out) - 1] = 0;
543 memset(&tmp, 0, sizeof(tmp));
544 snprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
545 tmp[sizeof(tmp) - 1] = 0;
547 fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
548 S_IRUSR | S_IWUSR);
549 ret = pcap_ops[mode->pcap]->push_file_header(fd);
550 if (ret)
551 panic("error writing pcap header!\n");
552 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
553 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
554 if (ret)
555 panic("error prepare writing pcap!\n");
558 interval = mode->dump_interval;
559 itimer.it_interval.tv_sec = interval;
560 itimer.it_interval.tv_usec = 0;
561 itimer.it_value.tv_sec = interval;
562 itimer.it_value.tv_usec = 0;
563 setitimer(ITIMER_REAL, &itimer, NULL);
565 return fd;
568 static void finish_single_pcap_file(struct mode *mode, int fd)
570 pcap_ops[mode->pcap]->fsync_pcap(fd);
571 if (pcap_ops[mode->pcap]->prepare_close_pcap)
572 pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
573 close(fd);
576 static int begin_single_pcap_file(struct mode *mode)
578 int fd, ret;
580 if (!pcap_ops[mode->pcap])
581 panic("pcap group not supported!\n");
582 fd = open_or_die_m(mode->device_out,
583 O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
584 S_IRUSR | S_IWUSR);
585 ret = pcap_ops[mode->pcap]->push_file_header(fd);
586 if (ret)
587 panic("error writing pcap header!\n");
588 if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
589 ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
590 if (ret)
591 panic("error prepare writing pcap!\n");
594 return fd;
597 static void enter_mode_rx_only_or_dump(struct mode *mode)
599 int sock, irq, ifindex, fd = 0, ret;
600 unsigned int size, it = 0;
601 unsigned long fcnt = 0;
602 short ifflags = 0;
603 uint8_t *packet;
604 struct ring rx_ring;
605 struct pollfd rx_poll;
606 struct frame_map *hdr;
607 struct sock_fprog bpf_ops;
609 if (!device_up_and_running(mode->device_in))
610 panic("Device not up and running!\n");
612 set_memcpy();
613 sock = pf_socket();
615 if (mode->dump) {
616 struct stat tmp;
617 memset(&tmp, 0, sizeof(tmp));
618 ret = stat(mode->device_out, &tmp);
619 if (ret < 0) {
620 mode->dump_dir = 0;
621 goto try_file;
623 mode->dump_dir = !!S_ISDIR(tmp.st_mode);
624 if (mode->dump_dir) {
625 fd = begin_multi_pcap_file(mode);
626 } else {
627 try_file:
628 fd = begin_single_pcap_file(mode);
632 memset(&rx_ring, 0, sizeof(rx_ring));
633 memset(&rx_poll, 0, sizeof(rx_poll));
634 memset(&bpf_ops, 0, sizeof(bpf_ops));
636 ifindex = device_ifindex(mode->device_in);
637 size = ring_size(mode->device_in, mode->reserve_size);
639 enable_kernel_bpf_jit_compiler();
640 bpf_parse_rules(mode->filter, &bpf_ops);
641 bpf_attach_to_sock(sock, &bpf_ops);
643 setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support);
644 create_rx_ring(sock, &rx_ring);
645 mmap_rx_ring(sock, &rx_ring);
646 alloc_rx_ring_frames(&rx_ring);
647 bind_rx_ring(sock, &rx_ring, ifindex);
649 prepare_polling(sock, &rx_poll);
650 dissector_init_all(mode->print_mode);
652 if (mode->cpu >= 0 && ifindex > 0) {
653 irq = device_irq_number(mode->device_in);
654 device_bind_irq_to_cpu(mode->cpu, irq);
655 printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq,
656 mode->cpu);
659 if (mode->promiscuous == true) {
660 ifflags = enter_promiscuous_mode(mode->device_in);
661 printf("PROMISC\n");
664 printf("BPF:\n");
665 bpf_dump_all(&bpf_ops);
666 printf("MD: RX %s\n\n", mode->dump ? pcap_ops[mode->pcap]->name : "");
668 while (likely(sigint == 0)) {
669 while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
670 hdr = rx_ring.frames[it].iov_base;
671 packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
672 fcnt++;
674 if (mode->packet_type != PACKET_ALL)
675 if (mode->packet_type != hdr->s_ll.sll_pkttype)
676 goto next;
677 if (unlikely(rx_ring.layout.tp_frame_size <
678 hdr->tp_h.tp_snaplen)) {
679 fprintf(stderr, "Skipping too large packet! "
680 "No jumbo support selected?\n");
681 fflush(stderr);
682 goto next;
684 if (mode->dump) {
685 struct pcap_pkthdr phdr;
686 tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr);
687 ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr,
688 packet, phdr.len);
689 if (unlikely(ret != sizeof(phdr) + phdr.len))
690 panic("Write error to pcap!\n");
693 show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS);
694 dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
695 mode->link_type);
697 if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) {
698 sigint = 1;
699 break;
701 next:
702 kernel_may_pull_from_rx(&hdr->tp_h);
703 next_slot(&it, &rx_ring);
705 if (unlikely(sigint == 1))
706 break;
707 if (mode->dump && next_dump) {
708 struct tpacket_stats kstats;
709 socklen_t slen = sizeof(kstats);
710 memset(&kstats, 0, sizeof(kstats));
711 getsockopt(sock, SOL_PACKET, PACKET_STATISTICS,
712 &kstats, &slen);
713 fd = next_multi_pcap_file(mode, fd);
714 next_dump = false;
715 if (mode->print_mode == FNTTYPE_PRINT_NONE) {
716 printf(".(+%u/-%u)", kstats.tp_packets - kstats.tp_drops,
717 kstats.tp_drops);
718 fflush(stdout);
723 poll(&rx_poll, 1, -1);
724 poll_error_maybe_die(sock, &rx_poll);
727 if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE))
728 sock_print_net_stats(sock);
729 else {
730 printf("\n\n");
731 fflush(stdout);
733 dissector_cleanup_all();
734 destroy_rx_ring(sock, &rx_ring);
735 if (mode->promiscuous == true)
736 leave_promiscuous_mode(mode->device_in, ifflags);
737 close(sock);
738 if (mode->dump) {
739 if (mode->dump_dir)
740 finish_multi_pcap_file(mode, fd);
741 else
742 finish_single_pcap_file(mode, fd);
746 static void help(void)
748 printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING,
749 VERSION_STRING);
750 printf("http://www.netsniff-ng.org\n\n");
751 printf("Usage: netsniff-ng [options]\n");
752 printf("Options:\n");
753 printf(" -i|-d|--dev|--in <dev|pcap> Input source as netdev or pcap\n");
754 printf(" -o|--out <dev|pcap|dir> Output sink as netdev or pcap or directory\n");
755 printf(" -f|--filter <bpf-file> Use BPF filter file from bpfc\n");
756 printf(" -t|--type <type> Only handle packets of defined type:\n");
757 printf(" host|broadcast|multicast|others|outgoing\n");
758 printf(" -F|--interval <int> Dump interval in sec if -o is a directory where\n");
759 printf(" pcap files should be stored (default: 60)\n");
760 printf(" -s|--silent Do not print captured packets\n");
761 printf(" -J|--jumbo-support Support for 64KB Super Jumbo Frames\n");
762 printf(" Default RX/TX slot: 2048Byte\n");
763 printf(" -n|--num <uint> Number of packets until exit\n");
764 printf(" `-- 0 Loop until interrupt (default)\n");
765 printf(" `- n Send n packets and done\n");
766 printf(" -r|--rand Randomize packet forwarding order\n");
767 printf(" -M|--no-promisc No promiscuous mode for netdev\n");
768 printf(" -m|--mmap Mmap pcap file i.e., for replaying\n");
769 printf(" Default: scatter/gather I/O\n");
770 printf(" -c|--clrw Instead s/g I/O use slower read/write I/O\n");
771 printf(" -S|--ring-size <size> Manually set ring size to <size>:\n");
772 printf(" mmap space in KB/MB/GB, e.g. \'10MB\'\n");
773 printf(" -k|--kernel-pull <int> Kernel pull from user interval in us\n");
774 printf(" Default is 10us where the TX_RING\n");
775 printf(" is populated with payload from uspace\n");
776 printf(" -b|--bind-cpu <cpu> Bind to specific CPU (or CPU-range)\n");
777 printf(" -B|--unbind-cpu <cpu> Forbid to use specific CPU (or CPU-range)\n");
778 printf(" -H|--prio-high Make this high priority process\n");
779 printf(" -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n");
780 printf(" -q|--less Print less-verbose packet information\n");
781 printf(" -l|--payload Only print human-readable payload\n");
782 printf(" -x|--payload-hex Only print payload in hex format\n");
783 printf(" -C|--c-style Print full packet in trafgen/C style hex format\n");
784 printf(" -X|--all-hex Print packets in hex format\n");
785 printf(" -N|--no-payload Only print packet header\n");
786 printf(" -v|--version Show version\n");
787 printf(" -h|--help Guess what?!\n");
788 printf("\n");
789 printf("Examples:\n");
790 printf(" netsniff-ng --in eth0 --out dump.pcap --silent --bind-cpu 0\n");
791 printf(" netsniff-ng --in dump.pcap --mmap --out eth0 --silent --bind-cpu 0\n");
792 printf(" netsniff-ng --in any --filter icmp.bpf --all-hex\n");
793 printf(" netsniff-ng --in eth0 --out eth1 --silent --bind-cpu 0 --type host --filter http.bpf\n");
794 printf(" netsniff-ng --in any --filter http.bpf --payload\n");
795 printf(" netsniff-ng --in wlan0 --out /opt/probe1/ --silent --interval 30 --bind-cpu 0 --jumbo-support\n");
796 printf("\n");
797 printf("Note:\n");
798 printf(" This tool is targeted for network developers! You should\n");
799 printf(" be aware of what you are doing and what these options above\n");
800 printf(" mean! Use netsniff-ng's bpfc compiler for generating filter files.\n");
801 printf(" Further, netsniff-ng automatically enables the kernel BPF JIT\n");
802 printf(" if present.\n");
803 printf("\n");
804 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
805 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
806 printf("Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n");
807 printf("License: GNU GPL version 2\n");
808 printf("This is free software: you are free to change and redistribute it.\n");
809 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
810 die();
813 static void version(void)
815 printf("\n%s %s, the packet sniffing beast\n", PROGNAME_STRING,
816 VERSION_STRING);
817 printf("http://www.netsniff-ng.org\n\n");
818 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
819 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
820 printf("Copyright (C) 2009-2012 Emmanuel Roullit <emmanuel@netsniff-ng.org>\n");
821 printf("License: GNU GPL version 2\n");
822 printf("This is free software: you are free to change and redistribute it.\n");
823 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
824 die();
827 static void header(void)
829 printf("%s%s%s\n", colorize_start(bold), PROGNAME_STRING " "
830 VERSION_STRING, colorize_end());
833 int main(int argc, char **argv)
835 int c, i, j, opt_index;
836 char *ptr;
837 bool prio_high = false;
838 struct mode mode;
839 void (*enter_mode)(struct mode *mode) = NULL;
841 check_for_root_maybe_die();
843 memset(&mode, 0, sizeof(mode));
844 mode.link_type = LINKTYPE_EN10MB;
845 mode.print_mode = FNTTYPE_PRINT_NORM;
846 mode.cpu = CPU_UNKNOWN;
847 mode.packet_type = PACKET_ALL;
848 mode.promiscuous = true;
849 mode.randomize = false;
850 mode.pcap = PCAP_OPS_SG;
851 mode.dump_interval = DUMP_INTERVAL;
853 while ((c = getopt_long(argc, argv, short_options, long_options,
854 &opt_index)) != EOF) {
855 switch (c) {
856 case 'd':
857 case 'i':
858 mode.device_in = xstrdup(optarg);
859 break;
860 case 'o':
861 mode.device_out = xstrdup(optarg);
862 break;
863 case 'r':
864 mode.randomize = true;
865 break;
866 case 'J':
867 mode.jumbo_support = 1;
868 break;
869 case 'f':
870 mode.filter = xstrdup(optarg);
871 break;
872 case 'M':
873 mode.promiscuous = false;
874 break;
875 case 't':
876 if (!strncmp(optarg, "host", strlen("host")))
877 mode.packet_type = PACKET_HOST;
878 else if (!strncmp(optarg, "broadcast", strlen("broadcast")))
879 mode.packet_type = PACKET_BROADCAST;
880 else if (!strncmp(optarg, "multicast", strlen("multicast")))
881 mode.packet_type = PACKET_MULTICAST;
882 else if (!strncmp(optarg, "others", strlen("others")))
883 mode.packet_type = PACKET_OTHERHOST;
884 else if (!strncmp(optarg, "outgoing", strlen("outgoing")))
885 mode.packet_type = PACKET_OUTGOING;
886 else
887 mode.packet_type = PACKET_ALL;
888 break;
889 case 'S':
890 ptr = optarg;
891 mode.reserve_size = 0;
893 for (j = i = strlen(optarg); i > 0; --i) {
894 if (!isdigit(optarg[j - i]))
895 break;
896 ptr++;
899 if (!strncmp(ptr, "KB", strlen("KB")))
900 mode.reserve_size = 1 << 10;
901 else if (!strncmp(ptr, "MB", strlen("MB")))
902 mode.reserve_size = 1 << 20;
903 else if (!strncmp(ptr, "GB", strlen("GB")))
904 mode.reserve_size = 1 << 30;
905 else
906 panic("Syntax error in ring size param!\n");
908 *ptr = 0;
909 mode.reserve_size *= atoi(optarg);
910 break;
911 case 'b':
912 set_cpu_affinity(optarg, 0);
913 if (mode.cpu != CPU_NOTOUCH)
914 mode.cpu = atoi(optarg);
915 break;
916 case 'B':
917 set_cpu_affinity(optarg, 1);
918 break;
919 case 'H':
920 prio_high = true;
921 break;
922 case 'c':
923 mode.pcap = PCAP_OPS_RW;
924 break;
925 case 'm':
926 mode.pcap = PCAP_OPS_MMAP;
927 break;
928 case 'Q':
929 mode.cpu = CPU_NOTOUCH;
930 break;
931 case 's':
932 mode.print_mode = FNTTYPE_PRINT_NONE;
933 break;
934 case 'q':
935 mode.print_mode = FNTTYPE_PRINT_LESS;
936 break;
937 case 'l':
938 mode.print_mode = FNTTYPE_PRINT_CHR1;
939 break;
940 case 'x':
941 mode.print_mode = FNTTYPE_PRINT_HEX1;
942 break;
943 case 'C':
944 mode.print_mode = FNTTYPE_PRINT_PAAC;
945 break;
946 case 'X':
947 mode.print_mode = FNTTYPE_PRINT_HEX2;
948 break;
949 case 'N':
950 mode.print_mode = FNTTYPE_PRINT_NOPA;
951 break;
952 case 'k':
953 mode.kpull = (unsigned long) atol(optarg);
954 break;
955 case 'n':
956 frame_cnt_max = (unsigned long) atol(optarg);
957 break;
958 case 'F':
959 mode.dump_interval = (unsigned long) atol(optarg);
960 break;
961 case 'v':
962 version();
963 break;
964 case 'h':
965 help();
966 break;
967 case '?':
968 switch (optopt) {
969 case 'd':
970 case 'i':
971 case 'o':
972 case 'f':
973 case 't':
974 case 'F':
975 case 'n':
976 case 'S':
977 case 'b':
978 case 'k':
979 case 'B':
980 case 'e':
981 panic("Option -%c requires an argument!\n",
982 optopt);
983 default:
984 if (isprint(optopt))
985 whine("Unknown option character "
986 "`0x%X\'!\n", optopt);
987 die();
989 default:
990 break;
994 if (!mode.device_in)
995 mode.device_in = xstrdup("any");
997 register_signal(SIGINT, signal_handler);
998 register_signal(SIGHUP, signal_handler);
1000 init_pcap(mode.jumbo_support);
1001 tprintf_init();
1002 header();
1004 if (prio_high == true) {
1005 set_proc_prio(get_default_proc_prio());
1006 set_sched_status(get_default_sched_policy(),
1007 get_default_sched_prio());
1010 if (mode.device_in && (device_mtu(mode.device_in) ||
1011 !strncmp("any", mode.device_in, strlen(mode.device_in)))) {
1012 if (!mode.device_out) {
1013 mode.dump = 0;
1014 enter_mode = enter_mode_rx_only_or_dump;
1015 } else if (device_mtu(mode.device_out)) {
1016 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1017 enter_mode = enter_mode_rx_to_tx;
1018 } else {
1019 mode.dump = 1;
1020 register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO);
1021 enter_mode = enter_mode_rx_only_or_dump;
1023 } else {
1024 if (mode.device_out && device_mtu(mode.device_out)) {
1025 register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
1026 enter_mode = enter_mode_pcap_to_tx;
1027 } else {
1028 enter_mode = enter_mode_read_pcap;
1032 if (!enter_mode)
1033 panic("Selection not supported!\n");
1034 enter_mode(&mode);
1036 tprintf_cleanup();
1037 cleanup_pcap();
1039 if (mode.device_in)
1040 xfree(mode.device_in);
1041 if (mode.device_out)
1042 xfree(mode.device_out);
1043 return 0;