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>
127 #include "built_in.h"
130 * TODO: Cleanups, this got quite a hack over time.
133 #define TERM_MODE_NORMAL 1
134 #define TERM_MODE_CSV 2
135 #define TERM_MODE_CSV_HDR 4
137 #define USER_HZ sysconf(_SC_CLK_TCK)
140 unsigned long rx_bytes
;
141 unsigned long rx_packets
;
142 unsigned long rx_drops
;
143 unsigned long rx_errors
;
144 unsigned long rx_fifo
;
145 unsigned long rx_frame
;
146 unsigned long rx_multi
;
147 unsigned long tx_bytes
;
148 unsigned long tx_packets
;
149 unsigned long tx_drops
;
150 unsigned long tx_errors
;
151 unsigned long tx_fifo
;
152 unsigned long tx_colls
;
153 unsigned long tx_carrier
;
154 unsigned long irq_nr
;
156 unsigned long *irqs_srx
;
157 unsigned long *irqs_stx
;
158 unsigned long *cpu_user
;
159 unsigned long *cpu_nice
;
160 unsigned long *cpu_sys
;
161 unsigned long *cpu_idle
;
162 unsigned long *cpu_iow
;
165 unsigned long procs_run
;
166 unsigned long procs_iow
;
171 int wifi_link_qual_max
;
172 int wifi_signal_level
;
173 int wifi_noise_level
;
179 volatile sig_atomic_t sigint
= 0;
181 static const char *short_options
= "d:t:vhcCHlp";
183 static struct option long_options
[] = {
184 {"dev", required_argument
, 0, 'd'},
185 {"interval", required_argument
, 0, 't'},
186 {"loop", no_argument
, 0, 'l'},
187 {"term", no_argument
, 0, 'c'},
188 {"promisc", no_argument
, 0, 'p'},
189 {"csv", no_argument
, 0, 'C'},
190 {"csv-tablehead", no_argument
, 0, 'H'},
191 {"version", no_argument
, 0, 'v'},
192 {"help", no_argument
, 0, 'h'},
196 static void signal_handler(int number
)
209 static int rxtx_stats(const char *ifname
, struct ifstat
*s
)
215 FILE *fp
= fopen("/proc/net/dev", "r");
217 whine("Cannot open /proc/net/dev!\n");
222 ptr
= fgets(buf
, sizeof(buf
), fp
);
223 ptr
= fgets(buf
, sizeof(buf
), fp
);
225 memset(buf
, 0, sizeof(buf
));
226 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
227 buf
[sizeof(buf
) -1] = 0;
229 if (strstr(buf
, ifname
) == NULL
)
237 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu%lu%lu%*u%lu%lu%lu%lu%lu%lu%lu",
238 &s
->rx_bytes
, &s
->rx_packets
, &s
->rx_errors
,
239 &s
->rx_drops
, &s
->rx_fifo
, &s
->rx_frame
,
241 &s
->tx_bytes
, &s
->tx_packets
, &s
->tx_errors
,
242 &s
->tx_drops
, &s
->tx_fifo
, &s
->tx_colls
,
249 memset(buf
, 0, sizeof(buf
));
257 static int wifi_stats(const char *ifname
, struct ifstat
*s
)
260 struct iw_statistics ws
;
262 ret
= wireless_sigqual(ifname
, &ws
);
264 /* We don't want to trouble in case of eth* */
269 s
->wifi_bitrate
= wireless_bitrate(ifname
);
270 s
->wifi_signal_level
= adjust_dbm_level(ws
.qual
.updated
& IW_QUAL_DBM
,
272 s
->wifi_noise_level
= adjust_dbm_level(ws
.qual
.updated
& IW_QUAL_DBM
,
274 s
->wifi_link_qual
= ws
.qual
.qual
;
275 s
->wifi_link_qual_max
= wireless_rangemax_sigqual(ifname
);
280 static void stats_check_alloc(struct ifstat
*s
)
282 int cpus
= get_number_cpus();
284 if (s
->irqs_len
!= get_number_cpus()) {
285 if (s
->irqs
) xfree(s
->irqs
);
286 if (s
->irqs_srx
) xfree(s
->irqs_srx
);
287 if (s
->irqs_stx
) xfree(s
->irqs_stx
);
288 if (s
->cpu_user
) xfree(s
->cpu_user
);
289 if (s
->cpu_nice
) xfree(s
->cpu_nice
);
290 if (s
->cpu_sys
) xfree(s
->cpu_sys
);
291 if (s
->cpu_idle
) xfree(s
->cpu_idle
);
292 if (s
->cpu_iow
) xfree(s
->cpu_iow
);
294 s
->irqs_srx
= xzmalloc(sizeof(*(s
->irqs_srx
)) * cpus
);
295 s
->irqs_stx
= xzmalloc(sizeof(*(s
->irqs_stx
)) * cpus
);
296 s
->irqs
= xzmalloc(sizeof(*(s
->irqs
)) * cpus
);
297 s
->cpu_user
= xzmalloc(sizeof(*(s
->cpu_user
)) * cpus
);
298 s
->cpu_nice
= xzmalloc(sizeof(*(s
->cpu_nice
)) * cpus
);
299 s
->cpu_sys
= xzmalloc(sizeof(*(s
->cpu_sys
)) * cpus
);
300 s
->cpu_idle
= xzmalloc(sizeof(*(s
->cpu_idle
)) * cpus
);
301 s
->cpu_iow
= xzmalloc(sizeof(*(s
->cpu_iow
)) * cpus
);
306 static int irq_sstats(struct ifstat
*s
)
312 FILE *fp
= fopen("/proc/softirqs", "r");
314 whine("Cannot open /proc/softirqs!\n");
318 stats_check_alloc(s
);
320 memset(buff
, 0, sizeof(buff
));
321 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
322 buff
[sizeof(buff
) - 1] = 0;
324 if ((ptr
= strstr(buff
, "NET_TX:")) == NULL
) {
325 ptr
= strstr(buff
, "NET_RX:");
334 ptr
+= strlen("NET_TX:");
336 for (i
= 0; i
< s
->irqs_len
; ++i
) {
341 while (*ptr
!= ' ' && *ptr
!= 0)
345 s
->irqs_srx
[i
] = atoi(ptr2
);
347 s
->irqs_stx
[i
] = atoi(ptr2
);
350 memset(buff
, 0, sizeof(buff
));
358 static int mem_stats(struct ifstat
*s
)
361 unsigned long total
, free
;
365 FILE *fp
= fopen("/proc/meminfo", "r");
367 whine("Cannot open /proc/meminfo!\n");
371 memset(buff
, 0, sizeof(buff
));
372 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
373 buff
[sizeof(buff
) - 1] = 0;
375 if ((ptr
= strstr(buff
, "MemTotal:")) != NULL
) {
376 ptr
+= strlen("MemTotal:");
382 ret
= sscanf(ptr
, "%lu", &total
);
385 } else if ((ptr
= strstr(buff
, "MemFree:")) != NULL
) {
386 ptr
+= strlen("MemFree:");
392 ret
= sscanf(ptr
, "%lu", &free
);
397 memset(buff
, 0, sizeof(buff
));
401 s
->mem_used
= 100.f
* (total
- free
) / total
;
410 static int sys_stats(struct ifstat
*s
)
416 FILE *fp
= fopen("/proc/stat", "r");
418 whine("Cannot open /proc/stat!\n");
422 stats_check_alloc(s
);
424 memset(buff
, 0, sizeof(buff
));
425 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
426 buff
[sizeof(buff
) - 1] = 0;
428 if ((ptr
= strstr(buff
, "cpu")) != NULL
) {
429 ptr
+= strlen("cpu");
434 while (*ptr
!= ' ' && *ptr
!= 0)
439 if (cpu
< 0 || cpu
>= s
->irqs_len
)
443 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu", &s
->cpu_user
[cpu
],
444 &s
->cpu_nice
[cpu
], &s
->cpu_sys
[cpu
],
445 &s
->cpu_idle
[cpu
], &s
->cpu_iow
[cpu
]);
448 } else if ((ptr
= strstr(buff
, "ctxt")) != NULL
) {
449 ptr
+= strlen("ctxt");
455 ret
= sscanf(ptr
, "%lu", &s
->ctxt
);
458 } else if ((ptr
= strstr(buff
, "processes")) != NULL
) {
459 ptr
+= strlen("processes");
465 ret
= sscanf(ptr
, "%lu", &s
->forks
);
468 } else if ((ptr
= strstr(buff
, "procs_running")) != NULL
) {
469 ptr
+= strlen("procs_running");
475 ret
= sscanf(ptr
, "%lu", &s
->procs_run
);
478 } else if ((ptr
= strstr(buff
, "procs_blocked")) != NULL
) {
479 ptr
+= strlen("procs_blocked");
485 ret
= sscanf(ptr
, "%lu", &s
->procs_iow
);
490 memset(buff
, 0, sizeof(buff
));
498 static int irq_stats(const char *ifname
, struct ifstat
*s
)
505 if (!strncmp("lo", ifname
, strlen("lo")))
508 FILE *fp
= fopen("/proc/interrupts", "r");
510 whine("Cannot open /proc/interrupts!\n");
514 stats_check_alloc(s
);
516 memset(buff
, 0, sizeof(buff
));
517 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
518 buff
[sizeof(buff
) - 1] = 0;
520 if (strstr(buff
, ifname
) == NULL
)
527 s
->irq_nr
= atoi(buff
);
529 bug_on(s
->irq_nr
== 0);
531 for (i
= 0; i
< s
->irqs_len
; ++i
) {
536 while (*ptr
!= ' ' && *ptr
!= 0)
539 s
->irqs
[i
] = atoi(ptr2
);
542 memset(buff
, 0, sizeof(buff
));
550 static void diff_stats(struct ifstat
*old
, struct ifstat
*new,
555 if(old
->irqs_len
!= new->irqs_len
)
556 return; /* Refetch stats and take old diff! */
558 diff
->rx_bytes
= new->rx_bytes
- old
->rx_bytes
;
559 diff
->rx_packets
= new->rx_packets
- old
->rx_packets
;
560 diff
->rx_drops
= new->rx_drops
- old
->rx_drops
;
561 diff
->rx_errors
= new->rx_errors
- old
->rx_errors
;
562 diff
->rx_fifo
= new->rx_fifo
- old
->rx_fifo
;
563 diff
->rx_frame
= new->rx_frame
- old
->rx_frame
;
564 diff
->rx_multi
= new->rx_multi
- old
->rx_multi
;
565 diff
->tx_bytes
= new->tx_bytes
- old
->tx_bytes
;
566 diff
->tx_packets
= new->tx_packets
- old
->tx_packets
;
567 diff
->tx_drops
= new->tx_drops
- old
->tx_drops
;
568 diff
->tx_errors
= new->tx_errors
- old
->tx_errors
;
569 diff
->tx_fifo
= new->tx_fifo
- old
->tx_fifo
;
570 diff
->tx_colls
= new->tx_colls
- old
->tx_colls
;
571 diff
->tx_carrier
= new->tx_carrier
- old
->tx_carrier
;
572 diff
->wifi_signal_level
= new->wifi_signal_level
- old
->wifi_signal_level
;
573 diff
->wifi_noise_level
= new->wifi_noise_level
- old
->wifi_noise_level
;
574 diff
->wifi_link_qual
= new->wifi_link_qual
- old
->wifi_link_qual
;
575 diff
->ctxt
= new->ctxt
- old
->ctxt
;
576 diff
->forks
= new->forks
- old
->forks
;
577 diff
->procs_run
= new->procs_run
- old
->procs_run
;
578 diff
->procs_iow
= new->procs_iow
- old
->procs_iow
;
580 stats_check_alloc(diff
);
582 diff
->irq_nr
= new->irq_nr
;
584 for (i
= 0; i
< diff
->irqs_len
; ++i
) {
585 diff
->irqs
[i
] = new->irqs
[i
] - old
->irqs
[i
];
586 diff
->irqs_srx
[i
] = new->irqs_srx
[i
] - old
->irqs_srx
[i
];
587 diff
->irqs_stx
[i
] = new->irqs_stx
[i
] - old
->irqs_stx
[i
];
588 diff
->cpu_user
[i
] = new->cpu_user
[i
] - old
->cpu_user
[i
];
589 diff
->cpu_nice
[i
] = new->cpu_nice
[i
] - old
->cpu_nice
[i
];
590 diff
->cpu_sys
[i
] = new->cpu_sys
[i
] - old
->cpu_sys
[i
];
591 diff
->cpu_idle
[i
] = new->cpu_idle
[i
] - old
->cpu_idle
[i
];
592 diff
->cpu_iow
[i
] = new->cpu_iow
[i
] - old
->cpu_iow
[i
];
596 static char *snr_to_str(int level
)
600 return "very good signal";
601 if (level
> 25 && level
<= 40)
602 return "good signal";
603 if (level
> 15 && level
<= 25)
604 return "poor signal";
605 if (level
> 10 && level
<= 15)
606 return "very poor signal";
613 static void screen_init(WINDOW
**screen
)
615 (*screen
) = initscr();
618 nodelay((*screen
), TRUE
);
623 static void screen_update(WINDOW
*screen
, const char *ifname
,
624 struct ifstat
*s
, struct ifstat
*t
,
625 int *first
, double interval
)
630 mvwprintw(screen
, 1, 2, "Kernel net/sys statistics for %s, t=%.2lfs",
633 mvwprintw(screen
, 3, 0,
634 " RX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
635 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
637 mvwprintw(screen
, 4, 0,
638 " TX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
639 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
642 mvwprintw(screen
, 6, 2,
643 "RX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
644 1.f
* t
->rx_bytes
/ (1 << 20), t
->rx_packets
, t
->rx_drops
,
646 mvwprintw(screen
, 7, 2,
647 "TX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
648 1.f
* t
->tx_bytes
/ (1 << 20), t
->tx_packets
, t
->tx_drops
,
651 mvwprintw(screen
, j
++, 2, "SYS: %14ld cs/t %10.1f%% mem "
652 "%13ld running %10ld iowait",
653 s
->ctxt
, t
->mem_used
, t
->procs_run
, t
->procs_iow
);
655 if (s
->irq_nr
!= 0) {
656 for(i
= 0; i
< s
->irqs_len
; ++i
) {
657 unsigned long all
= s
->cpu_user
[i
] + s
->cpu_nice
[i
] +
658 s
->cpu_sys
[i
] + s
->cpu_idle
[i
] +
660 mvwprintw(screen
, j
++, 2, "CPU%d: %13.1f%% usr/t "
661 "%9.1f%% sys/t %10.1f%% idl/t %11.1f%% iow/t ",
663 100.f
* (s
->cpu_user
[i
] + s
->cpu_nice
[i
]) / all
,
664 100.f
* s
->cpu_sys
[i
] / all
,
665 100.f
* s
->cpu_idle
[i
] /all
,
666 100.f
* s
->cpu_iow
[i
] / all
);
669 for(i
= 0; i
< s
->irqs_len
; ++i
)
670 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs/t "
671 "%15ld soirq RX/t %15ld soirq TX/t ",
672 i
, s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
674 for(i
= 0; i
< s
->irqs_len
; ++i
)
675 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs",
679 if (t
->wifi_bitrate
> 0) {
680 mvwprintw(screen
, j
++, 2, "LinkQual: %7d/%d (%d/t) ",
681 t
->wifi_link_qual
, t
->wifi_link_qual_max
,
683 mvwprintw(screen
, j
++, 2, "Signal: %8d dBm (%d dBm/t) ",
684 t
->wifi_signal_level
, s
->wifi_signal_level
);
685 mvwprintw(screen
, j
++, 2, "Noise: %8d dBm (%d dBm/t) ",
686 t
->wifi_noise_level
, s
->wifi_noise_level
);
687 mvwprintw(screen
, j
++, 2, "SNR: %8d dBm (%s) ",
688 t
->wifi_signal_level
- t
->wifi_noise_level
,
689 snr_to_str(t
->wifi_signal_level
- t
->wifi_noise_level
));
693 mvwprintw(screen
, 2, 2, "Collecting data ...");
696 mvwprintw(screen
, 2, 2, " ");
702 static void screen_end(void)
707 static void print_update(const char *ifname
, struct ifstat
*s
,
708 struct ifstat
*t
, double interval
)
712 printf("RX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
713 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
715 printf("TX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
716 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
719 for(i
= 0; i
< s
->irqs_len
; ++i
)
720 printf("CPU%d: %10ld IRQs/t "
722 "%10ld SoIRQ TX/t\n", i
,
723 s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
724 if (t
->wifi_bitrate
> 0) {
725 printf("LinkQual: %6d/%d (%d/t)\n", t
->wifi_link_qual
,
726 t
->wifi_link_qual_max
, s
->wifi_link_qual
);
727 printf("Signal: %8d dBm (%d dBm/t)\n", t
->wifi_signal_level
,
728 s
->wifi_signal_level
);
729 printf("Noise: %8d dBm (%d dBm/t)\n", t
->wifi_noise_level
,
730 s
->wifi_noise_level
);
734 static void print_update_csv(const char *ifname
, struct ifstat
*s
,
735 struct ifstat
*t
, double interval
)
739 printf("%ld,%lu,%lu,%lu,%lu,", time(0), s
->rx_bytes
, s
->rx_packets
,
740 s
->rx_drops
, s
->rx_errors
);
741 printf("%lu,%lu,%lu,%lu", s
->tx_bytes
, s
->tx_packets
, s
->tx_drops
,
744 for(i
= 0; i
< s
->irqs_len
; ++i
)
745 printf(",%ld,%ld,%ld", s
->irqs
[i
], s
->irqs_srx
[i
],
747 if (t
->wifi_bitrate
> 0) {
748 printf(",%d,%d", t
->wifi_link_qual
, t
->wifi_link_qual_max
);
749 printf(",%d", t
->wifi_signal_level
);
750 printf(",%d", t
->wifi_noise_level
);
755 static void print_update_csv_hdr(const char *ifname
, struct ifstat
*s
,
756 struct ifstat
*t
, double interval
)
760 printf("Unixtime,RX Byte/t,RX Pkts/t,RX Drops/t,RX Errors/t,");
761 printf("TX Byte/t,TX Pkts/t,TX Drops/t,TX Errors/t");
763 for(i
= 0; i
< s
->irqs_len
; ++i
)
764 printf(",CPU%d IRQs/t,CPU%d SoIRQ RX/t,"
765 "CPU%d SoIRQ TX/t", i
, i
, i
);
766 if (t
->wifi_bitrate
> 0)
767 printf(",LinkQual,LinkQualMax,Signal Level,Noise Level");
771 static inline int do_stats(const char *ifname
, struct ifstat
*s
)
775 ret
+= rxtx_stats(ifname
, s
);
776 ret
+= irq_stats(ifname
, s
);
777 ret
+= irq_sstats(s
);
780 ret
+= wifi_stats(ifname
, s
);
785 static int screen_loop(const char *ifname
, uint32_t interval
)
787 int ret
= 0, first
= 1;
788 struct ifstat old
, new, curr
;
789 WINDOW
*screen
= NULL
;
791 memset(&old
, 0, sizeof(old
));
792 memset(&new, 0, sizeof(new));
793 memset(&curr
, 0, sizeof(curr
));
795 screen_init(&screen
);
801 screen_update(screen
, ifname
, &curr
, &new, &first
, interval
);
803 ret
= do_stats(ifname
, &old
);
809 ret
= do_stats(ifname
, &new);
813 diff_stats(&old
, &new, &curr
);
819 whine("Error fetching stats!\n");
830 static int print_loop(const char *ifname
, uint32_t interval
)
833 struct ifstat old
, new, curr
;
835 memset(&old
, 0, sizeof(old
));
836 memset(&new, 0, sizeof(new));
837 memset(&curr
, 0, sizeof(curr
));
839 ret
= do_stats(ifname
, &old
);
845 ret
= do_stats(ifname
, &new);
849 diff_stats(&old
, &new, &curr
);
851 if (first
&& (mode
& TERM_MODE_CSV_HDR
) ==
853 print_update_csv_hdr(ifname
, &curr
, &new, interval
);
857 if ((mode
& TERM_MODE_CSV
) == TERM_MODE_CSV
)
858 print_update_csv(ifname
, &curr
, &new, interval
);
859 else if ((mode
& TERM_MODE_NORMAL
) == TERM_MODE_NORMAL
)
860 print_update(ifname
, &curr
, &new, interval
);
861 } while (loop
&& !sigint
);
864 whine("Error fetching stats!\n");
875 static void help(void)
877 printf("\nifpps %s, kernel networking and system statistics\n",
879 printf("http://www.netsniff-ng.org\n\n");
880 printf("Usage: ifpps [options] || ifpps <netdev>\n");
881 printf("Options:\n");
882 printf(" -d|--dev <netdev> Device to fetch statistics for i.e., eth0\n");
883 printf(" -p|--promisc Promiscuous mode\n");
884 printf(" -t|--interval <time> Refresh time in sec (default 1 s)\n");
885 printf(" -c|--term Output to terminal\n");
886 printf(" -C|--csv Output to terminal as CSV\n");
887 printf(" E.g. post-processing with Gnuplot et al.\n");
888 printf(" -H|--csv-tablehead Print CSV table head\n");
889 printf(" -l|--loop Loop terminal output\n");
890 printf(" -v|--version Print version\n");
891 printf(" -h|--help Print this help\n");
893 printf("Examples:\n");
894 printf(" ifpps --dev eth0\n");
895 printf(" ifpps --dev eth0 --interval 60 --csv\n\n");
896 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
897 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
898 printf("License: GNU GPL version 2\n");
899 printf("This is free software: you are free to change and redistribute it.\n");
900 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
904 static void version(void)
906 printf("\nifpps %s, kernel networking statistics per sec\n",
908 printf("http://www.netsniff-ng.org\n\n");
909 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
910 printf("Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n");
911 printf("License: GNU GPL version 2\n");
912 printf("This is free software: you are free to change and redistribute it.\n");
913 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
917 int main(int argc
, char **argv
)
920 int c
, opt_index
, ret
;
921 unsigned int promisc
= 0;
923 uint32_t interval
= 1;
924 int (*main_loop
)(const char *ifname
, uint32_t interval
) = screen_loop
;
926 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
927 &opt_index
)) != EOF
) {
936 ifname
= xstrndup(optarg
, IFNAMSIZ
);
939 interval
= atoi(optarg
);
942 mode
|= TERM_MODE_NORMAL
;
943 main_loop
= print_loop
;
952 mode
|= TERM_MODE_CSV
;
953 main_loop
= print_loop
;
956 mode
|= TERM_MODE_CSV_HDR
;
957 main_loop
= print_loop
;
963 panic("Option -%c requires an argument!\n",
967 whine("Unknown option character "
968 "`0x%X\'!\n", optopt
);
979 ifname
= xstrndup(argv
[1], IFNAMSIZ
);
981 panic("No networking device given!\n");
982 if (!strncmp("lo", ifname
, IFNAMSIZ
))
983 panic("lo is not supported!\n");
984 if (device_mtu(ifname
) == 0)
985 panic("This is no networking device!\n");
986 register_signal(SIGINT
, signal_handler
);
987 register_signal(SIGHUP
, signal_handler
);
989 check_for_root_maybe_die();
990 ifflags
= enter_promiscuous_mode(ifname
);
992 ret
= main_loop(ifname
, interval
);
994 leave_promiscuous_mode(ifname
, ifflags
);