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'.
27 #include <sys/socket.h>
40 * TODO: Cleanups, this got quite a hack over time.
43 #define TERM_MODE_NORMAL 1
44 #define TERM_MODE_CSV 2
45 #define TERM_MODE_CSV_HDR 4
47 #define USER_HZ sysconf(_SC_CLK_TCK)
50 unsigned long rx_bytes
;
51 unsigned long rx_packets
;
52 unsigned long rx_drops
;
53 unsigned long rx_errors
;
54 unsigned long rx_fifo
;
55 unsigned long rx_frame
;
56 unsigned long rx_multi
;
57 unsigned long tx_bytes
;
58 unsigned long tx_packets
;
59 unsigned long tx_drops
;
60 unsigned long tx_errors
;
61 unsigned long tx_fifo
;
62 unsigned long tx_colls
;
63 unsigned long tx_carrier
;
66 unsigned long *irqs_srx
;
67 unsigned long *irqs_stx
;
68 unsigned long *cpu_user
;
69 unsigned long *cpu_nice
;
70 unsigned long *cpu_sys
;
71 unsigned long *cpu_idle
;
72 unsigned long *cpu_iow
;
75 unsigned long procs_run
;
76 unsigned long procs_iow
;
81 int wifi_link_qual_max
;
82 int wifi_signal_level
;
89 volatile sig_atomic_t sigint
= 0;
91 static const char *short_options
= "d:t:vhcCHlp";
92 static const struct option long_options
[] = {
93 {"dev", required_argument
, NULL
, 'd'},
94 {"interval", required_argument
, NULL
, 't'},
95 {"loop", no_argument
, NULL
, 'l'},
96 {"term", no_argument
, NULL
, 'c'},
97 {"promisc", no_argument
, NULL
, 'p'},
98 {"csv", no_argument
, NULL
, 'C'},
99 {"csv-tablehead", no_argument
, NULL
, 'H'},
100 {"version", no_argument
, NULL
, 'v'},
101 {"help", no_argument
, NULL
, 'h'},
105 static void signal_handler(int number
)
118 static int rxtx_stats(const char *ifname
, struct ifstat
*s
)
124 FILE *fp
= fopen("/proc/net/dev", "r");
126 whine("Cannot open /proc/net/dev!\n");
131 ptr
= fgets(buf
, sizeof(buf
), fp
);
132 ptr
= fgets(buf
, sizeof(buf
), fp
);
134 memset(buf
, 0, sizeof(buf
));
135 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
136 buf
[sizeof(buf
) -1] = 0;
138 if (strstr(buf
, ifname
) == NULL
)
146 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu%lu%lu%*u%lu%lu%lu%lu%lu%lu%lu",
147 &s
->rx_bytes
, &s
->rx_packets
, &s
->rx_errors
,
148 &s
->rx_drops
, &s
->rx_fifo
, &s
->rx_frame
,
150 &s
->tx_bytes
, &s
->tx_packets
, &s
->tx_errors
,
151 &s
->tx_drops
, &s
->tx_fifo
, &s
->tx_colls
,
158 memset(buf
, 0, sizeof(buf
));
166 static int wifi_stats(const char *ifname
, struct ifstat
*s
)
169 struct iw_statistics ws
;
171 ret
= wireless_sigqual(ifname
, &ws
);
173 /* We don't want to trouble in case of eth* */
178 s
->wifi_bitrate
= wireless_bitrate(ifname
);
179 s
->wifi_signal_level
= adjust_dbm_level(ws
.qual
.updated
& IW_QUAL_DBM
,
181 s
->wifi_noise_level
= adjust_dbm_level(ws
.qual
.updated
& IW_QUAL_DBM
,
183 s
->wifi_link_qual
= ws
.qual
.qual
;
184 s
->wifi_link_qual_max
= wireless_rangemax_sigqual(ifname
);
189 static void stats_check_alloc(struct ifstat
*s
)
191 int cpus
= get_number_cpus();
193 if (s
->irqs_len
!= get_number_cpus()) {
194 if (s
->irqs
) xfree(s
->irqs
);
195 if (s
->irqs_srx
) xfree(s
->irqs_srx
);
196 if (s
->irqs_stx
) xfree(s
->irqs_stx
);
197 if (s
->cpu_user
) xfree(s
->cpu_user
);
198 if (s
->cpu_nice
) xfree(s
->cpu_nice
);
199 if (s
->cpu_sys
) xfree(s
->cpu_sys
);
200 if (s
->cpu_idle
) xfree(s
->cpu_idle
);
201 if (s
->cpu_iow
) xfree(s
->cpu_iow
);
203 s
->irqs_srx
= xzmalloc(sizeof(*(s
->irqs_srx
)) * cpus
);
204 s
->irqs_stx
= xzmalloc(sizeof(*(s
->irqs_stx
)) * cpus
);
205 s
->irqs
= xzmalloc(sizeof(*(s
->irqs
)) * cpus
);
206 s
->cpu_user
= xzmalloc(sizeof(*(s
->cpu_user
)) * cpus
);
207 s
->cpu_nice
= xzmalloc(sizeof(*(s
->cpu_nice
)) * cpus
);
208 s
->cpu_sys
= xzmalloc(sizeof(*(s
->cpu_sys
)) * cpus
);
209 s
->cpu_idle
= xzmalloc(sizeof(*(s
->cpu_idle
)) * cpus
);
210 s
->cpu_iow
= xzmalloc(sizeof(*(s
->cpu_iow
)) * cpus
);
215 static int irq_sstats(struct ifstat
*s
)
221 FILE *fp
= fopen("/proc/softirqs", "r");
223 whine("Cannot open /proc/softirqs!\n");
227 stats_check_alloc(s
);
229 memset(buff
, 0, sizeof(buff
));
230 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
231 buff
[sizeof(buff
) - 1] = 0;
233 if ((ptr
= strstr(buff
, "NET_TX:")) == NULL
) {
234 ptr
= strstr(buff
, "NET_RX:");
243 ptr
+= strlen("NET_TX:");
245 for (i
= 0; i
< s
->irqs_len
; ++i
) {
250 while (*ptr
!= ' ' && *ptr
!= 0)
254 s
->irqs_srx
[i
] = atoi(ptr2
);
256 s
->irqs_stx
[i
] = atoi(ptr2
);
259 memset(buff
, 0, sizeof(buff
));
267 static int mem_stats(struct ifstat
*s
)
270 unsigned long total
, free
;
274 FILE *fp
= fopen("/proc/meminfo", "r");
276 whine("Cannot open /proc/meminfo!\n");
280 memset(buff
, 0, sizeof(buff
));
281 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
282 buff
[sizeof(buff
) - 1] = 0;
284 if ((ptr
= strstr(buff
, "MemTotal:")) != NULL
) {
285 ptr
+= strlen("MemTotal:");
291 ret
= sscanf(ptr
, "%lu", &total
);
294 } else if ((ptr
= strstr(buff
, "MemFree:")) != NULL
) {
295 ptr
+= strlen("MemFree:");
301 ret
= sscanf(ptr
, "%lu", &free
);
306 memset(buff
, 0, sizeof(buff
));
310 s
->mem_used
= 100.f
* (total
- free
) / total
;
319 static int sys_stats(struct ifstat
*s
)
325 FILE *fp
= fopen("/proc/stat", "r");
327 whine("Cannot open /proc/stat!\n");
331 stats_check_alloc(s
);
333 memset(buff
, 0, sizeof(buff
));
334 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
335 buff
[sizeof(buff
) - 1] = 0;
337 if ((ptr
= strstr(buff
, "cpu")) != NULL
) {
338 ptr
+= strlen("cpu");
343 while (*ptr
!= ' ' && *ptr
!= 0)
348 if (cpu
< 0 || cpu
>= s
->irqs_len
)
352 ret
= sscanf(ptr
, "%lu%lu%lu%lu%lu", &s
->cpu_user
[cpu
],
353 &s
->cpu_nice
[cpu
], &s
->cpu_sys
[cpu
],
354 &s
->cpu_idle
[cpu
], &s
->cpu_iow
[cpu
]);
357 } else if ((ptr
= strstr(buff
, "ctxt")) != NULL
) {
358 ptr
+= strlen("ctxt");
364 ret
= sscanf(ptr
, "%lu", &s
->ctxt
);
367 } else if ((ptr
= strstr(buff
, "processes")) != NULL
) {
368 ptr
+= strlen("processes");
374 ret
= sscanf(ptr
, "%lu", &s
->forks
);
377 } else if ((ptr
= strstr(buff
, "procs_running")) != NULL
) {
378 ptr
+= strlen("procs_running");
384 ret
= sscanf(ptr
, "%lu", &s
->procs_run
);
387 } else if ((ptr
= strstr(buff
, "procs_blocked")) != NULL
) {
388 ptr
+= strlen("procs_blocked");
394 ret
= sscanf(ptr
, "%lu", &s
->procs_iow
);
399 memset(buff
, 0, sizeof(buff
));
407 static int irq_stats(const char *ifname
, struct ifstat
*s
)
415 if (!strncmp("lo", ifname
, strlen("lo")))
418 fp
= fopen("/proc/interrupts", "r");
420 whine("Cannot open /proc/interrupts!\n");
424 stats_check_alloc(s
);
426 memset(buff
, 0, sizeof(buff
));
427 while (fgets(buff
, sizeof(buff
), fp
) != NULL
) {
428 buff
[sizeof(buff
) - 1] = 0;
430 if (strstr(buff
, ifname
) == NULL
)
437 s
->irq_nr
= atoi(buff
);
439 bug_on(s
->irq_nr
== 0);
441 for (i
= 0; i
< s
->irqs_len
; ++i
) {
446 while (*ptr
!= ' ' && *ptr
!= 0)
449 s
->irqs
[i
] = atoi(ptr2
);
452 memset(buff
, 0, sizeof(buff
));
460 static void diff_stats(struct ifstat
*old
, struct ifstat
*new,
465 if(old
->irqs_len
!= new->irqs_len
)
466 return; /* Refetch stats and take old diff! */
468 diff
->rx_bytes
= new->rx_bytes
- old
->rx_bytes
;
469 diff
->rx_packets
= new->rx_packets
- old
->rx_packets
;
470 diff
->rx_drops
= new->rx_drops
- old
->rx_drops
;
471 diff
->rx_errors
= new->rx_errors
- old
->rx_errors
;
472 diff
->rx_fifo
= new->rx_fifo
- old
->rx_fifo
;
473 diff
->rx_frame
= new->rx_frame
- old
->rx_frame
;
474 diff
->rx_multi
= new->rx_multi
- old
->rx_multi
;
475 diff
->tx_bytes
= new->tx_bytes
- old
->tx_bytes
;
476 diff
->tx_packets
= new->tx_packets
- old
->tx_packets
;
477 diff
->tx_drops
= new->tx_drops
- old
->tx_drops
;
478 diff
->tx_errors
= new->tx_errors
- old
->tx_errors
;
479 diff
->tx_fifo
= new->tx_fifo
- old
->tx_fifo
;
480 diff
->tx_colls
= new->tx_colls
- old
->tx_colls
;
481 diff
->tx_carrier
= new->tx_carrier
- old
->tx_carrier
;
482 diff
->wifi_signal_level
= new->wifi_signal_level
- old
->wifi_signal_level
;
483 diff
->wifi_noise_level
= new->wifi_noise_level
- old
->wifi_noise_level
;
484 diff
->wifi_link_qual
= new->wifi_link_qual
- old
->wifi_link_qual
;
485 diff
->ctxt
= new->ctxt
- old
->ctxt
;
486 diff
->forks
= new->forks
- old
->forks
;
487 diff
->procs_run
= new->procs_run
- old
->procs_run
;
488 diff
->procs_iow
= new->procs_iow
- old
->procs_iow
;
490 stats_check_alloc(diff
);
492 diff
->irq_nr
= new->irq_nr
;
494 for (i
= 0; i
< diff
->irqs_len
; ++i
) {
495 diff
->irqs
[i
] = new->irqs
[i
] - old
->irqs
[i
];
496 diff
->irqs_srx
[i
] = new->irqs_srx
[i
] - old
->irqs_srx
[i
];
497 diff
->irqs_stx
[i
] = new->irqs_stx
[i
] - old
->irqs_stx
[i
];
498 diff
->cpu_user
[i
] = new->cpu_user
[i
] - old
->cpu_user
[i
];
499 diff
->cpu_nice
[i
] = new->cpu_nice
[i
] - old
->cpu_nice
[i
];
500 diff
->cpu_sys
[i
] = new->cpu_sys
[i
] - old
->cpu_sys
[i
];
501 diff
->cpu_idle
[i
] = new->cpu_idle
[i
] - old
->cpu_idle
[i
];
502 diff
->cpu_iow
[i
] = new->cpu_iow
[i
] - old
->cpu_iow
[i
];
506 static char *snr_to_str(int level
)
510 return "very good signal";
511 if (level
> 25 && level
<= 40)
512 return "good signal";
513 if (level
> 15 && level
<= 25)
514 return "poor signal";
515 if (level
> 10 && level
<= 15)
516 return "very poor signal";
523 static void screen_init(WINDOW
**screen
)
525 (*screen
) = initscr();
528 nodelay((*screen
), TRUE
);
533 static void screen_update(WINDOW
*screen
, const char *ifname
,
534 struct ifstat
*s
, struct ifstat
*t
,
535 int *first
, double interval
)
540 mvwprintw(screen
, 1, 2, "Kernel net/sys statistics for %s, t=%.2lfs",
543 mvwprintw(screen
, 3, 0,
544 " RX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
545 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
547 mvwprintw(screen
, 4, 0,
548 " TX: %16.3f MiB/t %10lu pkts/t %10lu drops/t %10lu errors/t ",
549 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
552 mvwprintw(screen
, 6, 2,
553 "RX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
554 1.f
* t
->rx_bytes
/ (1 << 20), t
->rx_packets
, t
->rx_drops
,
556 mvwprintw(screen
, 7, 2,
557 "TX: %16.3f MiB %10lu pkts %10lu drops %10lu errors",
558 1.f
* t
->tx_bytes
/ (1 << 20), t
->tx_packets
, t
->tx_drops
,
561 mvwprintw(screen
, j
++, 2, "SYS: %14ld cs/t %10.1f%% mem "
562 "%13ld running %10ld iowait",
563 s
->ctxt
, t
->mem_used
, t
->procs_run
, t
->procs_iow
);
565 if (s
->irq_nr
!= 0) {
566 for(i
= 0; i
< s
->irqs_len
; ++i
) {
567 unsigned long all
= s
->cpu_user
[i
] + s
->cpu_nice
[i
] +
568 s
->cpu_sys
[i
] + s
->cpu_idle
[i
] +
570 mvwprintw(screen
, j
++, 2, "CPU%d: %13.1f%% usr/t "
571 "%9.1f%% sys/t %10.1f%% idl/t %11.1f%% iow/t ",
573 100.f
* (s
->cpu_user
[i
] + s
->cpu_nice
[i
]) / all
,
574 100.f
* s
->cpu_sys
[i
] / all
,
575 100.f
* s
->cpu_idle
[i
] /all
,
576 100.f
* s
->cpu_iow
[i
] / all
);
579 for(i
= 0; i
< s
->irqs_len
; ++i
)
580 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs/t "
581 "%15ld soirq RX/t %15ld soirq TX/t ",
582 i
, s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
584 for(i
= 0; i
< s
->irqs_len
; ++i
)
585 mvwprintw(screen
, j
++, 2, "CPU%d: %14ld irqs",
589 if (t
->wifi_bitrate
> 0) {
590 mvwprintw(screen
, j
++, 2, "LinkQual: %7d/%d (%d/t) ",
591 t
->wifi_link_qual
, t
->wifi_link_qual_max
,
593 mvwprintw(screen
, j
++, 2, "Signal: %8d dBm (%d dBm/t) ",
594 t
->wifi_signal_level
, s
->wifi_signal_level
);
595 mvwprintw(screen
, j
++, 2, "Noise: %8d dBm (%d dBm/t) ",
596 t
->wifi_noise_level
, s
->wifi_noise_level
);
597 mvwprintw(screen
, j
++, 2, "SNR: %8d dBm (%s) ",
598 t
->wifi_signal_level
- t
->wifi_noise_level
,
599 snr_to_str(t
->wifi_signal_level
- t
->wifi_noise_level
));
603 mvwprintw(screen
, 2, 2, "Collecting data ...");
606 mvwprintw(screen
, 2, 2, " ");
612 static void screen_end(void)
617 static void print_update(const char *ifname
, struct ifstat
*s
,
618 struct ifstat
*t
, double interval
)
622 printf("RX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
623 1.f
* s
->rx_bytes
/ (1 << 20), s
->rx_packets
, s
->rx_drops
,
625 printf("TX: %16.3f MiB/t %10lu Pkts/t %10lu Drops/t %10lu Errors/t\n",
626 1.f
* s
->tx_bytes
/ (1 << 20), s
->tx_packets
, s
->tx_drops
,
629 for(i
= 0; i
< s
->irqs_len
; ++i
)
630 printf("CPU%d: %10ld IRQs/t "
632 "%10ld SoIRQ TX/t\n", i
,
633 s
->irqs
[i
], s
->irqs_srx
[i
], s
->irqs_stx
[i
]);
634 if (t
->wifi_bitrate
> 0) {
635 printf("LinkQual: %6d/%d (%d/t)\n", t
->wifi_link_qual
,
636 t
->wifi_link_qual_max
, s
->wifi_link_qual
);
637 printf("Signal: %8d dBm (%d dBm/t)\n", t
->wifi_signal_level
,
638 s
->wifi_signal_level
);
639 printf("Noise: %8d dBm (%d dBm/t)\n", t
->wifi_noise_level
,
640 s
->wifi_noise_level
);
644 static void print_update_csv(const char *ifname
, struct ifstat
*s
,
645 struct ifstat
*t
, double interval
)
649 printf("%ld,%lu,%lu,%lu,%lu,", time(0), s
->rx_bytes
, s
->rx_packets
,
650 s
->rx_drops
, s
->rx_errors
);
651 printf("%lu,%lu,%lu,%lu", s
->tx_bytes
, s
->tx_packets
, s
->tx_drops
,
654 for(i
= 0; i
< s
->irqs_len
; ++i
)
655 printf(",%ld,%ld,%ld", s
->irqs
[i
], s
->irqs_srx
[i
],
657 if (t
->wifi_bitrate
> 0) {
658 printf(",%d,%d", t
->wifi_link_qual
, t
->wifi_link_qual_max
);
659 printf(",%d", t
->wifi_signal_level
);
660 printf(",%d", t
->wifi_noise_level
);
665 static void print_update_csv_hdr(const char *ifname
, struct ifstat
*s
,
666 struct ifstat
*t
, double interval
)
670 printf("Unixtime,RX Byte/t,RX Pkts/t,RX Drops/t,RX Errors/t,");
671 printf("TX Byte/t,TX Pkts/t,TX Drops/t,TX Errors/t");
673 for(i
= 0; i
< s
->irqs_len
; ++i
)
674 printf(",CPU%d IRQs/t,CPU%d SoIRQ RX/t,"
675 "CPU%d SoIRQ TX/t", i
, i
, i
);
676 if (t
->wifi_bitrate
> 0)
677 printf(",LinkQual,LinkQualMax,Signal Level,Noise Level");
681 static inline int do_stats(const char *ifname
, struct ifstat
*s
)
685 ret
+= rxtx_stats(ifname
, s
);
686 ret
+= irq_stats(ifname
, s
);
687 ret
+= irq_sstats(s
);
690 ret
+= wifi_stats(ifname
, s
);
695 static int screen_loop(const char *ifname
, uint32_t interval
)
697 int ret
= 0, first
= 1;
698 struct ifstat old
, new, curr
;
699 WINDOW
*screen
= NULL
;
701 memset(&old
, 0, sizeof(old
));
702 memset(&new, 0, sizeof(new));
703 memset(&curr
, 0, sizeof(curr
));
705 screen_init(&screen
);
711 screen_update(screen
, ifname
, &curr
, &new, &first
, interval
);
713 ret
= do_stats(ifname
, &old
);
719 ret
= do_stats(ifname
, &new);
723 diff_stats(&old
, &new, &curr
);
729 whine("Error fetching stats!\n");
740 static int print_loop(const char *ifname
, uint32_t interval
)
743 struct ifstat old
, new, curr
;
745 memset(&old
, 0, sizeof(old
));
746 memset(&new, 0, sizeof(new));
747 memset(&curr
, 0, sizeof(curr
));
749 ret
= do_stats(ifname
, &old
);
755 ret
= do_stats(ifname
, &new);
759 diff_stats(&old
, &new, &curr
);
761 if (first
&& (mode
& TERM_MODE_CSV_HDR
) ==
763 print_update_csv_hdr(ifname
, &curr
, &new, interval
);
767 if ((mode
& TERM_MODE_CSV
) == TERM_MODE_CSV
)
768 print_update_csv(ifname
, &curr
, &new, interval
);
769 else if ((mode
& TERM_MODE_NORMAL
) == TERM_MODE_NORMAL
)
770 print_update(ifname
, &curr
, &new, interval
);
771 } while (loop
&& !sigint
);
774 whine("Error fetching stats!\n");
785 static void help(void)
787 printf("\nifpps %s, top-like kernel networking and system statistics\n",
789 puts("http://www.netsniff-ng.org\n\n"
790 "Usage: ifpps [options] || ifpps <netdev>\n"
792 " -d|--dev <netdev> Device to fetch statistics for i.e., eth0\n"
793 " -p|--promisc Promiscuous mode\n"
794 " -t|--interval <time> Refresh time in sec (default 1 s)\n"
795 " -c|--term Output to terminal\n"
796 " -C|--csv Output to terminal as CSV\n"
797 " E.g. post-processing with Gnuplot et al.\n"
798 " -H|--csv-tablehead Print CSV table head\n"
799 " -l|--loop Loop terminal output\n"
800 " -v|--version Print version\n"
801 " -h|--help Print this help\n\n"
803 " ifpps --dev eth0\n"
804 " ifpps --dev eth0 --interval 60 --csv\n\n"
805 "Please report bugs to <bugs@netsniff-ng.org>\n"
806 "Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n"
807 "License: GNU GPL version 2.0\n"
808 "This is free software: you are free to change and redistribute it.\n"
809 "There is NO WARRANTY, to the extent permitted by law.\n");
813 static void version(void)
815 printf("\nifpps %s, top-like kernel networking statistics per sec\n",
817 puts("http://www.netsniff-ng.org\n\n"
818 "Please report bugs to <bugs@netsniff-ng.org>\n"
819 "Copyright (C) 2009-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n"
820 "License: GNU GPL version 2.0\n"
821 "This is free software: you are free to change and redistribute it.\n"
822 "There is NO WARRANTY, to the extent permitted by law.\n");
826 int main(int argc
, char **argv
)
829 int c
, opt_index
, ret
;
830 unsigned int promisc
= 0;
832 uint32_t interval
= 1;
833 int (*main_loop
)(const char *ifname
, uint32_t interval
) = screen_loop
;
835 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
836 &opt_index
)) != EOF
) {
845 ifname
= xstrndup(optarg
, IFNAMSIZ
);
848 interval
= atoi(optarg
);
851 mode
|= TERM_MODE_NORMAL
;
852 main_loop
= print_loop
;
861 mode
|= TERM_MODE_CSV
;
862 main_loop
= print_loop
;
865 mode
|= TERM_MODE_CSV_HDR
;
866 main_loop
= print_loop
;
872 panic("Option -%c requires an argument!\n",
876 whine("Unknown option character "
877 "`0x%X\'!\n", optopt
);
888 ifname
= xstrndup(argv
[1], IFNAMSIZ
);
890 panic("No networking device given!\n");
891 if (!strncmp("lo", ifname
, IFNAMSIZ
))
892 panic("lo is not supported!\n");
893 if (device_mtu(ifname
) == 0)
894 panic("This is no networking device!\n");
895 register_signal(SIGINT
, signal_handler
);
896 register_signal(SIGHUP
, signal_handler
);
899 ifflags
= enter_promiscuous_mode(ifname
);
900 ret
= main_loop(ifname
, interval
);
902 leave_promiscuous_mode(ifname
, ifflags
);