2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2009, 2010 Daniel Borkmann.
5 * Subject to the GPL, version 2.
7 * A tiny tool to provide top-like reliable networking statistics.
8 * Why? Well, some time ago I used iptraf to display network traffic
9 * statistics. During that time and probably also today, they are
10 * using libpcap to collect statistics. Well, bad idea since this
11 * will give you false statistics on high I/O load. Therefore, ifpps
12 * reads out the 'real' kernel statistics, so things your NIC sees
13 * and not some userland library.
15 * He had all the injured air of a liar suspected when for once he
16 * has told the truth, or part of it.
18 * -- The Lord of the Rings, On Gollum,
19 * Chapter 'The Black Gate is Closed'.
26 ifpps - fetch and format kernel network statistics
30 ifpps -d|--dev <netdev> [-t|--interval <sec>][-p|--promisc][-c|--term]
31 [-C|--csv][-H|--csv-tablehead][-l|--loop][-v|--version][-h|--help]
35 A tiny tool to provide top-like reliable networking statistics.
36 ifpps reads out the 'real' kernel statistics, so it does not give erroneous
37 statistics on high I/O load.
43 =item ifpps --dev eth0
45 Fetch eth0 interface statistics.
47 =item ifpps --dev eth0 --interval 60 --csv
49 Output eth0 interface statistics every minute in CSV format.
59 Print help text and lists all options.
65 =item -d|--dev <netdev>
67 Device to fetch statistics for i.e., eth0.
71 Put the device in promiscuous mode
73 =item -t|--interval <time>
75 Refresh time in sec (default 1 sec)
84 E.g. post-processing with Gnuplot et al.
86 =item -H|--csv-tablehead
98 Written by Daniel Borkmann <daniel@netsniff-ng.org>
102 Documentation by Emmanuel Roullit <emmanuel@netsniff-ng.org>
106 Please report bugs to <bugs@netsniff-ng.org>
117 #include <sys/socket.h>
129 * TODO: Cleanups, this got quite a hack over time.
132 #define TERM_MODE_NORMAL 1
133 #define TERM_MODE_CSV 2
134 #define TERM_MODE_CSV_HDR 4
136 #define USER_HZ sysconf(_SC_CLK_TCK)
139 unsigned long rx_bytes
;
140 unsigned long rx_packets
;
141 unsigned long rx_drops
;
142 unsigned long rx_errors
;
143 unsigned long rx_fifo
;
144 unsigned long rx_frame
;
145 unsigned long rx_multi
;
146 unsigned long tx_bytes
;
147 unsigned long tx_packets
;
148 unsigned long tx_drops
;
149 unsigned long tx_errors
;
150 unsigned long tx_fifo
;
151 unsigned long tx_colls
;
152 unsigned long tx_carrier
;
153 unsigned long irq_nr
;
155 unsigned long *irqs_srx
;
156 unsigned long *irqs_stx
;
157 unsigned long *cpu_user
;
158 unsigned long *cpu_nice
;
159 unsigned long *cpu_sys
;
160 unsigned long *cpu_idle
;
161 unsigned long *cpu_iow
;
164 unsigned long procs_run
;
165 unsigned long procs_iow
;
170 int wifi_link_qual_max
;
171 int wifi_signal_level
;
172 int wifi_noise_level
;
178 volatile sig_atomic_t sigint
= 0;
180 static const char *short_options
= "d:t:vhcCHlp";
182 static struct option long_options
[] = {
183 {"dev", required_argument
, 0, 'd'},
184 {"interval", required_argument
, 0, 't'},
185 {"loop", no_argument
, 0, 'l'},
186 {"term", no_argument
, 0, 'c'},
187 {"promisc", no_argument
, 0, 'p'},
188 {"csv", no_argument
, 0, 'C'},
189 {"csv-tablehead", no_argument
, 0, 'H'},
190 {"version", no_argument
, 0, 'v'},
191 {"help", no_argument
, 0, 'h'},
195 static void signal_handler(int number
)
208 static int rxtx_stats(const char *ifname
, struct ifstat
*s
)
214 FILE *fp
= fopen("/proc/net/dev", "r");
216 whine("Cannot open /proc/net/dev!\n");
219 ptr
= fgets(buf
, sizeof(buf
), fp
);
220 ptr
= fgets(buf
, sizeof(buf
), fp
);
221 memset(buf
, 0, sizeof(buf
));
222 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
223 buf
[sizeof(buf
) -1] = 0;
224 if (strstr(buf
, ifname
) == NULL
)
230 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu%lu%lu%*u%lu%lu%lu%lu%lu%lu%lu",
231 &s
->rx_bytes
, &s
->rx_packets
, &s
->rx_errors
,
232 &s
->rx_drops
, &s
->rx_fifo
, &s
->rx_frame
,
234 &s
->tx_bytes
, &s
->tx_packets
, &s
->tx_errors
,
235 &s
->tx_drops
, &s
->tx_fifo
, &s
->tx_colls
,
241 memset(buf
, 0, sizeof(buf
));
247 static int wifi_stats(const char *ifname
, struct ifstat
*s
)
250 struct iw_statistics ws
;
252 ret
= wireless_sigqual(ifname
, &ws
);
254 /* We don't want to trouble in case of eth* */
258 s
->wifi_bitrate
= wireless_bitrate(ifname
);
259 s
->wifi_signal_level
= adjust_dbm_level(ws
.qual
.level
);
260 s
->wifi_noise_level
= adjust_dbm_level(ws
.qual
.noise
);
261 s
->wifi_link_qual
= ws
.qual
.qual
;
262 s
->wifi_link_qual_max
= wireless_rangemax_sigqual(ifname
);
266 static void stats_check_alloc(struct ifstat
*s
)
268 int cpus
= get_number_cpus();
270 if (s
->irqs_len
!= get_number_cpus()) {
271 if (s
->irqs
) xfree(s
->irqs
);
272 if (s
->irqs_srx
) xfree(s
->irqs_srx
);
273 if (s
->irqs_stx
) xfree(s
->irqs_stx
);
274 if (s
->cpu_user
) xfree(s
->cpu_user
);
275 if (s
->cpu_nice
) xfree(s
->cpu_nice
);
276 if (s
->cpu_sys
) xfree(s
->cpu_sys
);
277 if (s
->cpu_idle
) xfree(s
->cpu_idle
);
278 if (s
->cpu_iow
) xfree(s
->cpu_iow
);
279 s
->irqs_srx
= xzmalloc(sizeof(*(s
->irqs_srx
)) * cpus
);
280 s
->irqs_stx
= xzmalloc(sizeof(*(s
->irqs_stx
)) * cpus
);
281 s
->irqs
= xzmalloc(sizeof(*(s
->irqs
)) * cpus
);
282 s
->cpu_user
= xzmalloc(sizeof(*(s
->cpu_user
)) * cpus
);
283 s
->cpu_nice
= xzmalloc(sizeof(*(s
->cpu_nice
)) * cpus
);
284 s
->cpu_sys
= xzmalloc(sizeof(*(s
->cpu_sys
)) * cpus
);
285 s
->cpu_idle
= xzmalloc(sizeof(*(s
->cpu_idle
)) * cpus
);
286 s
->cpu_iow
= xzmalloc(sizeof(*(s
->cpu_iow
)) * cpus
);
291 static int irq_sstats(struct ifstat
*s
)
297 FILE *fp
= fopen("/proc/softirqs", "r");
299 whine("Cannot open /proc/softirqs!\n");
302 stats_check_alloc(s
);
303 memset(buff
, 0, sizeof(buff
));
304 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
305 buff
[sizeof(buff
) - 1] = 0;
306 if ((ptr
= strstr(buff
, "NET_TX:")) == NULL
) {
307 ptr
= strstr(buff
, "NET_RX:");
313 ptr
+= strlen("NET_TX:");
314 for (i
= 0; i
< s
->irqs_len
; ++i
) {
319 while (*ptr
!= ' ' && *ptr
!= 0)
323 s
->irqs_srx
[i
] = atoi(ptr2
);
325 s
->irqs_stx
[i
] = atoi(ptr2
);
327 memset(buff
, 0, sizeof(buff
));
333 static int mem_stats(struct ifstat
*s
)
336 unsigned long total
, free
;
340 FILE *fp
= fopen("/proc/meminfo", "r");
342 whine("Cannot open /proc/meminfo!\n");
345 memset(buff
, 0, sizeof(buff
));
346 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
347 buff
[sizeof(buff
) - 1] = 0;
348 if ((ptr
= strstr(buff
, "MemTotal:")) != NULL
) {
349 ptr
+= strlen("MemTotal:");
353 ret
= sscanf(ptr
, "%lu", &total
);
356 } else if ((ptr
= strstr(buff
, "MemFree:")) != NULL
) {
357 ptr
+= strlen("MemFree:");
361 ret
= sscanf(ptr
, "%lu", &free
);
365 memset(buff
, 0, sizeof(buff
));
368 s
->mem_used
= 100.f
* (total
- free
) / total
;
375 static int sys_stats(struct ifstat
*s
)
381 FILE *fp
= fopen("/proc/stat", "r");
383 whine("Cannot open /proc/stat!\n");
386 stats_check_alloc(s
);
387 memset(buff
, 0, sizeof(buff
));
388 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
389 buff
[sizeof(buff
) - 1] = 0;
390 if ((ptr
= strstr(buff
, "cpu")) != NULL
) {
391 ptr
+= strlen("cpu");
395 while (*ptr
!= ' ' && *ptr
!= 0)
399 if (cpu
< 0 || cpu
>= s
->irqs_len
)
402 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu", &s
->cpu_user
[cpu
],
403 &s
->cpu_nice
[cpu
], &s
->cpu_sys
[cpu
],
404 &s
->cpu_idle
[cpu
], &s
->cpu_iow
[cpu
]);
407 } else if ((ptr
= strstr(buff
, "ctxt")) != NULL
) {
408 ptr
+= strlen("ctxt");
412 ret
= sscanf(ptr
, "%lu", &s
->ctxt
);
415 } else if ((ptr
= strstr(buff
, "processes")) != NULL
) {
416 ptr
+= strlen("processes");
420 ret
= sscanf(ptr
, "%lu", &s
->forks
);
423 } else if ((ptr
= strstr(buff
, "procs_running")) != NULL
) {
424 ptr
+= strlen("procs_running");
428 ret
= sscanf(ptr
, "%lu", &s
->procs_run
);
431 } else if ((ptr
= strstr(buff
, "procs_blocked")) != NULL
) {
432 ptr
+= strlen("procs_blocked");
436 ret
= sscanf(ptr
, "%lu", &s
->procs_iow
);
441 memset(buff
, 0, sizeof(buff
));
447 static int irq_stats(const char *ifname
, struct ifstat
*s
)
454 if (!strncmp("lo", ifname
, strlen("lo")))
456 FILE *fp
= fopen("/proc/interrupts", "r");
458 whine("Cannot open /proc/interrupts!\n");
461 stats_check_alloc(s
);
462 memset(buff
, 0, sizeof(buff
));
463 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
464 buff
[sizeof(buff
) - 1] = 0;
465 if (strstr(buff
, ifname
) == NULL
)
471 s
->irq_nr
= atoi(buff
);
472 assert(s
->irq_nr
!= 0);
473 for (i
= 0; i
< s
->irqs_len
; ++i
) {
478 while (*ptr
!= ' ' && *ptr
!= 0)
481 s
->irqs
[i
] = atoi(ptr2
);
483 memset(buff
, 0, sizeof(buff
));
489 static void diff_stats(struct ifstat
*old
, struct ifstat
*new,
493 if(old
->irqs_len
!= new->irqs_len
)
494 return; /* Refetch stats and take old diff! */
495 diff
->rx_bytes
= new->rx_bytes
- old
->rx_bytes
;
496 diff
->rx_packets
= new->rx_packets
- old
->rx_packets
;
497 diff
->rx_drops
= new->rx_drops
- old
->rx_drops
;
498 diff
->rx_errors
= new->rx_errors
- old
->rx_errors
;
499 diff
->rx_fifo
= new->rx_fifo
- old
->rx_fifo
;
500 diff
->rx_frame
= new->rx_frame
- old
->rx_frame
;
501 diff
->rx_multi
= new->rx_multi
- old
->rx_multi
;
502 diff
->tx_bytes
= new->tx_bytes
- old
->tx_bytes
;
503 diff
->tx_packets
= new->tx_packets
- old
->tx_packets
;
504 diff
->tx_drops
= new->tx_drops
- old
->tx_drops
;
505 diff
->tx_errors
= new->tx_errors
- old
->tx_errors
;
506 diff
->tx_fifo
= new->tx_fifo
- old
->tx_fifo
;
507 diff
->tx_colls
= new->tx_colls
- old
->tx_colls
;
508 diff
->tx_carrier
= new->tx_carrier
- old
->tx_carrier
;
509 diff
->wifi_signal_level
= new->wifi_signal_level
- old
->wifi_signal_level
;
510 diff
->wifi_noise_level
= new->wifi_noise_level
- old
->wifi_noise_level
;
511 diff
->wifi_link_qual
= new->wifi_link_qual
- old
->wifi_link_qual
;
512 diff
->ctxt
= new->ctxt
- old
->ctxt
;
513 diff
->forks
= new->forks
- old
->forks
;
514 diff
->procs_run
= new->procs_run
- old
->procs_run
;
515 diff
->procs_iow
= new->procs_iow
- old
->procs_iow
;
516 stats_check_alloc(diff
);
517 diff
->irq_nr
= new->irq_nr
;
518 for (i
= 0; i
< diff
->irqs_len
; ++i
) {
519 diff
->irqs
[i
] = new->irqs
[i
] - old
->irqs
[i
];
520 diff
->irqs_srx
[i
] = new->irqs_srx
[i
] - old
->irqs_srx
[i
];
521 diff
->irqs_stx
[i
] = new->irqs_stx
[i
] - old
->irqs_stx
[i
];
522 diff
->cpu_user
[i
] = new->cpu_user
[i
] - old
->cpu_user
[i
];
523 diff
->cpu_nice
[i
] = new->cpu_nice
[i
] - old
->cpu_nice
[i
];
524 diff
->cpu_sys
[i
] = new->cpu_sys
[i
] - old
->cpu_sys
[i
];
525 diff
->cpu_idle
[i
] = new->cpu_idle
[i
] - old
->cpu_idle
[i
];
526 diff
->cpu_iow
[i
] = new->cpu_iow
[i
] - old
->cpu_iow
[i
];
530 static void screen_init(WINDOW
**screen
)
532 (*screen
) = initscr();
535 nodelay((*screen
), TRUE
);
540 static void screen_update(WINDOW
*screen
, const char *ifname
,
541 struct ifstat
*s
, struct ifstat
*t
,
542 int *first
, double interval
)
547 mvwprintw(screen
, 1, 2, "Kernel net/sys statistics for %s, t=%.2lfs",
550 mvwprintw(screen
, 3, 0,
551 " RX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
552 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
554 mvwprintw(screen
, 4, 0,
555 " TX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
556 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
559 mvwprintw(screen
, 6, 2,
560 "RX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
561 1.f
* t
->rx_bytes
/ (1 << 20), t
->rx_packets
, t
->rx_drops
,
563 mvwprintw(screen
, 7, 2,
564 "TX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
565 1.f
* t
->tx_bytes
/ (1 << 20), t
->tx_packets
, t
->tx_drops
,
568 mvwprintw(screen
, j
++, 2, "SYS: %14ld cs/t %10.1f%% mem "
569 "%13ld running %10ld iowait",
570 s
->ctxt
, t
->mem_used
, t
->procs_run
, t
->procs_iow
);
572 if (s
->irq_nr
!= 0) {
573 for(i
= 0; i
< s
->irqs_len
; ++i
) {
574 unsigned long all
= s
->cpu_user
[i
] + s
->cpu_nice
[i
] +
575 s
->cpu_sys
[i
] + s
->cpu_idle
[i
] +
577 mvwprintw(screen
, j
++, 2, "CPU%d: %13.1f%% usr/t "
578 "%9.1f%% sys/t %10.1f%% idl/t %11.1f%% iow/t ",
580 100.f
* (s
->cpu_user
[i
] + s
->cpu_nice
[i
]) / all
,
581 100.f
* s
->cpu_sys
[i
] / all
,
582 100.f
* s
->cpu_idle
[i
] /all
,
583 100.f
* s
->cpu_iow
[i
] / all
);
586 for(i
= 0; i
< s
->irqs_len
; ++i
)
587 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs/t "
588 "%15ld soirq RX/t %15ld soirq TX/t ",
589 i
, s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
591 for(i
= 0; i
< s
->irqs_len
; ++i
)
592 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs",
596 if (t
->wifi_bitrate
> 0) {
597 mvwprintw(screen
, j
++, 2, "LinkQual: %7d/%d (%d/t) ",
598 t
->wifi_link_qual
, t
->wifi_link_qual_max
,
600 mvwprintw(screen
, j
++, 2, "Signal: %8d dBm (%d dBm/t) ",
601 t
->wifi_signal_level
, s
->wifi_signal_level
);
602 mvwprintw(screen
, j
++, 2, "Noise: %8d dBm (%d dBm/t) ",
603 t
->wifi_noise_level
, s
->wifi_noise_level
);
607 mvwprintw(screen
, 2, 2, "Collecting data ...");
610 mvwprintw(screen
, 2, 2, " ");
616 static void screen_end(void)
621 static void print_update(const char *ifname
, struct ifstat
*s
,
622 struct ifstat
*t
, double interval
)
625 printf("RX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
626 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
628 printf("TX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
629 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
632 for(i
= 0; i
< s
->irqs_len
; ++i
)
633 printf("CPU%d: %10ld IRQs/t "
635 "%10ld SoIRQ TX/t\n", i
,
636 s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
637 if (t
->wifi_bitrate
> 0) {
638 printf("LinkQual: %6d/%d (%d/t)\n", t
->wifi_link_qual
,
639 t
->wifi_link_qual_max
, s
->wifi_link_qual
);
640 printf("Signal: %8d dBm (%d dBm/t)\n", t
->wifi_signal_level
,
641 s
->wifi_signal_level
);
642 printf("Noise: %8d dBm (%d dBm/t)\n", t
->wifi_noise_level
,
643 s
->wifi_noise_level
);
647 static void print_update_csv(const char *ifname
, struct ifstat
*s
,
648 struct ifstat
*t
, double interval
)
652 printf("%lu,%lu,%lu,%lu,", s
->rx_bytes
, s
->rx_packets
, s
->rx_drops
,
654 printf("%lu,%lu,%lu,%lu", s
->tx_bytes
, s
->tx_packets
, s
->tx_drops
,
657 for(i
= 0; i
< s
->irqs_len
; ++i
)
658 printf(",%ld,%ld,%ld", s
->irqs
[i
], s
->irqs_srx
[i
],
660 if (t
->wifi_bitrate
> 0) {
661 printf(",%d,%d", t
->wifi_link_qual
, t
->wifi_link_qual_max
);
662 printf(",%d", t
->wifi_signal_level
);
663 printf(",%d", t
->wifi_noise_level
);
668 static void print_update_csv_hdr(const char *ifname
, struct ifstat
*s
,
669 struct ifstat
*t
, double interval
)
673 printf("RX Byte/t,RX Pkts/t,RX Drops/t,RX Errors/t,");
674 printf("TX Byte/t,TX Pkts/t,TX Drops/t,TX Errors/t");
676 for(i
= 0; i
< s
->irqs_len
; ++i
)
677 printf(",CPU%d IRQs/t,CPU%d SoIRQ RX/t,"
678 "CPU%d SoIRQ TX/t", i
, i
, i
);
679 if (t
->wifi_bitrate
> 0)
680 printf(",LinkQual,LinkQualMax,Signal Level,Noise Level");
684 static inline int do_stats(const char *ifname
, struct ifstat
*s
)
687 ret
+= rxtx_stats(ifname
, s
);
688 ret
+= irq_stats(ifname
, s
);
689 ret
+= irq_sstats(s
);
692 ret
+= wifi_stats(ifname
, s
);
696 static int screen_loop(const char *ifname
, uint32_t interval
)
698 int ret
= 0, first
= 1;
699 struct ifstat old
, new, curr
;
700 WINDOW
*screen
= NULL
;
702 memset(&old
, 0, sizeof(old
));
703 memset(&new, 0, sizeof(new));
704 memset(&curr
, 0, sizeof(curr
));
705 screen_init(&screen
);
709 screen_update(screen
, ifname
, &curr
, &new, &first
, interval
);
710 ret
= do_stats(ifname
, &old
);
714 ret
= do_stats(ifname
, &new);
717 diff_stats(&old
, &new, &curr
);
722 whine("Error fetching stats!\n");
732 static int print_loop(const char *ifname
, uint32_t interval
)
735 struct ifstat old
, new, curr
;
737 memset(&old
, 0, sizeof(old
));
738 memset(&new, 0, sizeof(new));
739 memset(&curr
, 0, sizeof(curr
));
741 ret
= do_stats(ifname
, &old
);
745 ret
= do_stats(ifname
, &new);
748 diff_stats(&old
, &new, &curr
);
749 if (first
&& (mode
& TERM_MODE_CSV_HDR
) ==
751 print_update_csv_hdr(ifname
, &curr
, &new, interval
);
754 if ((mode
& TERM_MODE_CSV
) == TERM_MODE_CSV
)
755 print_update_csv(ifname
, &curr
, &new, interval
);
756 else if ((mode
& TERM_MODE_NORMAL
) == TERM_MODE_NORMAL
)
757 print_update(ifname
, &curr
, &new, interval
);
758 } while (loop
&& !sigint
);
761 whine("Error fetching stats!\n");
771 static void help(void)
773 printf("\nifpps %s, kernel networking and system statistics\n",
775 printf("http://www.netsniff-ng.org\n\n");
776 printf("Usage: ifpps [options] || ifpps <netdev>\n");
777 printf("Options:\n");
778 printf(" -d|--dev <netdev> Device to fetch statistics for i.e., eth0\n");
779 printf(" -p|--promisc Promiscuous mode\n");
780 printf(" -t|--interval <time> Refresh time in sec (default 1 s)\n");
781 printf(" -c|--term Output to terminal\n");
782 printf(" -C|--csv Output to terminal as CSV\n");
783 printf(" E.g. post-processing with Gnuplot et al.\n");
784 printf(" -H|--csv-tablehead Print CSV table head\n");
785 printf(" -l|--loop Loop terminal output\n");
786 printf(" -v|--version Print version\n");
787 printf(" -h|--help Print this help\n");
789 printf("Examples:\n");
790 printf(" ifpps --dev eth0\n");
791 printf(" ifpps --dev eth0 --interval 60 --csv\n\n");
792 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
793 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
794 printf("License: GNU GPL version 2\n");
795 printf("This is free software: you are free to change and redistribute it.\n");
796 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
800 static void version(void)
802 printf("\nifpps %s, kernel networking statistics per sec\n",
804 printf("http://www.netsniff-ng.org\n\n");
805 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
806 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@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");
813 int main(int argc
, char **argv
)
816 int c
, opt_index
, ret
;
817 unsigned int promisc
= 0;
819 uint32_t interval
= 1;
820 int (*main_loop
)(const char *ifname
, uint32_t interval
) = screen_loop
;
822 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
823 &opt_index
)) != EOF
) {
832 ifname
= xstrndup(optarg
, IFNAMSIZ
);
835 interval
= atoi(optarg
);
838 mode
|= TERM_MODE_NORMAL
;
839 main_loop
= print_loop
;
848 mode
|= TERM_MODE_CSV
;
849 main_loop
= print_loop
;
852 mode
|= TERM_MODE_CSV_HDR
;
853 main_loop
= print_loop
;
859 panic("Option -%c requires an argument!\n",
863 whine("Unknown option character "
864 "`0x%X\'!\n", optopt
);
875 ifname
= xstrndup(argv
[1], IFNAMSIZ
);
877 panic("No networking device given!\n");
878 if (!strncmp("lo", ifname
, IFNAMSIZ
))
879 panic("lo is not supported!\n");
880 if (device_mtu(ifname
) == 0)
881 panic("This is no networking device!\n");
882 register_signal(SIGINT
, signal_handler
);
883 register_signal(SIGHUP
, signal_handler
);
885 check_for_root_maybe_die();
886 ifflags
= enter_promiscuous_mode(ifname
);
888 ret
= main_loop(ifname
, interval
);
890 leave_promiscuous_mode(ifname
, ifflags
);