From fred at fperrin.net Thu Apr 23 11:09:55 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:09:55 +0000 Subject: [Iftop-users] [PATCH 1/4] Silence a warning In-Reply-To: <1429783797-28903-1-git-send-email-fred@fperrin.net> References: <1429783797-28903-1-git-send-email-fred@fperrin.net> Message-ID: <1429783797-28903-2-git-send-email-fred@fperrin.net> From: Fr?d?ric Perrin --- ui_common.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui_common.c b/ui_common.c index 8cb1e22..a4d4ba0 100644 --- a/ui_common.c +++ b/ui_common.c @@ -263,9 +263,6 @@ void analyse_data() { } u_screen_line = { &screen_line }; addr_pair ap; int i; - int tsent, trecv; - tsent = trecv = 0; - ap = *(addr_pair*)n->key; -- 2.3.5 From fred at fperrin.net Thu Apr 23 11:09:54 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:09:54 +0000 Subject: [Iftop-users] Add traffic accounting in PPS; drop short packets Message-ID: <1429783797-28903-1-git-send-email-fred@fperrin.net> Hi list, I'm sending the following patches. The first is a one-liner gcc was complaining about; the second add a new feature to do traffic accounting in packet per second rather than bit/s; the third is a fix to handle_ip_packet() which was reading past the end of certain malformed packets. [PATCH 1/4] Silence a warning [PATCH 2/4] Do traffic accounting in pps [PATCH 3/4] Drop packets shorter than sizeof (struct iphdr) From fred at fperrin.net Thu Apr 23 11:09:57 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:09:57 +0000 Subject: [Iftop-users] [PATCH 3/4] Drop packets shorter than sizeof (struct iphdr) In-Reply-To: <1429783797-28903-1-git-send-email-fred@fperrin.net> References: <1429783797-28903-1-git-send-email-fred@fperrin.net> Message-ID: <1429783797-28903-4-git-send-email-fred@fperrin.net> From: Fr?d?ric Perrin When packets that are too short to be valid IP packets happen to start with 0x45 or 0x60, iftop will still try to read source and destination addresses, which will usually just be random garbage. Note the assumption about what libpcap guarantees in the comments to handle_ip_packet(): * It is assumed that the snaplen (currently hard-coded to 1000) is * big enough to always capture the IP header past the L2 encap, and * that pcap never truncates the packet to less than snaplen; in * other words, that pcaphdr->caplen = MIN(pcaphdr->len, snaplen). --- iftop.c | 115 ++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/iftop.c b/iftop.c index f887d93..1640b11 100644 --- a/iftop.c +++ b/iftop.c @@ -249,16 +249,16 @@ void assign_addr_pair(addr_pair* ap, struct ip* iptr, int flip) { } } -static void handle_ip_packet(struct ip* iptr, int hw_dir) +static void handle_ip_packet(struct ip* iptr, int hw_dir, int pld_len) { int direction = 0; /* incoming */ + int len; history_type* ht; union { history_type **ht_pp; void **void_pp; } u_ht = { &ht }; addr_pair ap; - unsigned int len = 0; struct in6_addr scribdst; /* Scratch pad. */ struct in6_addr scribsrc; /* Scratch pad. */ /* Reinterpret packet type. */ @@ -268,7 +268,21 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) tick(0); - if( (IP_V(iptr) ==4 && options.netfilter == 0) + /* + * Sanity check: drop obviously short packets. + * pld_len comes from pcaphdr->len - sizeof(struct l2_header). + * + * It is assumed that the snaplen (currently hard-coded to 1000) is + * big enough to always capture the IP header past the L2 encap, and + * that pcap never truncates the packet to less than snaplen; in + * other words, that pcaphdr->caplen = MIN(pcaphdr->len, snaplen). + */ + if (pld_len < sizeof (struct ip)) + return; + if (IP_V(iptr) == 6 && pld_len < sizeof (struct ip6_hdr)) + return; + + if( (IP_V(iptr) == 4 && options.netfilter == 0) || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { /* * Net filter is off, so assign direction based on MAC address @@ -424,7 +438,6 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) break; } - if(hash_find(history, &ap, u_ht.void_pp) == HASH_STATUS_KEY_NOT_FOUND) { ht = history_create(); hash_insert(history, &ap, ht); @@ -434,19 +447,13 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) switch (options.bandwidth_unit) { case OPTION_BW_BITS: case OPTION_BW_BYTES: - switch (IP_V(iptr)) { - case 4: - len = ntohs(iptr->ip_len); - break; - case 6: - len = ntohs(ip6tr->ip6_plen) + 40; - default: - break; - } + len = pld_len; break; case OPTION_BW_PKTS: len = 1; break; + default: + return; } /* Update record */ @@ -476,7 +483,7 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) static void handle_raw_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { - handle_ip_packet((struct ip*)packet, -1); + handle_ip_packet((struct ip*)packet, -1, pkthdr->len); } #ifdef DLT_PFLOG @@ -490,18 +497,19 @@ static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* p hdrlen = BPF_WORDALIGN(hdr->length); length -= hdrlen; packet += hdrlen; - handle_ip_packet((struct ip*)packet, -1); + handle_ip_packet((struct ip*)packet, -1, length); } #endif static void handle_null_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { - handle_ip_packet((struct ip*)(packet + 4), -1); + handle_ip_packet((struct ip*)(packet + 4), -1, pkthdr->len); } -static void handle_llc_packet(const struct llc* llc, int dir) { - - struct ip* ip = (struct ip*)((void*)llc + sizeof(struct llc)); +static void handle_llc_packet(const struct llc* llc, int dir, int llclen) { + int hdrlen = sizeof(struct llc); + int pldlen = llclen - hdrlen; + struct ip* ip = (struct ip*)((void*)llc + hdrlen); /* Taken from tcpdump/print-llc.c */ if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP @@ -513,11 +521,11 @@ static void handle_llc_packet(const struct llc* llc, int dir) { switch(orgcode) { case OUI_ENCAP_ETHER: case OUI_CISCO_90: - handle_ip_packet(ip, dir); + handle_ip_packet(ip, dir, pldlen); break; case OUI_APPLETALK: if(et == ETHERTYPE_ATALK) { - handle_ip_packet(ip, dir); + handle_ip_packet(ip, dir, pldlen); } break; default:; @@ -529,52 +537,55 @@ static void handle_llc_packet(const struct llc* llc, int dir) { static void handle_tokenring_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { struct token_header *trp; + int hdrlen = 0; int dir = -1; trp = (struct token_header *)packet; if(IS_SOURCE_ROUTED(trp)) { - packet += RIF_LENGTH(trp); + hdrlen += RIF_LENGTH(trp); } - packet += TOKEN_HDRLEN; + hdrlen += TOKEN_HDRLEN; + packet += hdrlen; if(memcmp(trp->token_shost, if_hw_addr, 6) == 0 ) { /* packet leaving this i/f */ dir = 1; - } - else if(memcmp(trp->token_dhost, if_hw_addr, 6) == 0 || memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", trp->token_dhost, 6) == 0) { + } + else if(memcmp(trp->token_dhost, if_hw_addr, 6) == 0 || memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", trp->token_dhost, 6) == 0) { /* packet entering this i/f */ dir = 0; } /* Only know how to deal with LLC encapsulated packets */ if(FRAME_TYPE(trp) == TOKEN_FC_LLC) { - handle_llc_packet((struct llc*)packet, dir); + handle_llc_packet((struct llc*)packet, dir, pkthdr->len - hdrlen); } } static void handle_ppp_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { - register u_int length = pkthdr->len; - register u_int caplen = pkthdr->caplen; - u_int proto; + register u_int length = pkthdr->len; + register u_int caplen = pkthdr->caplen; + u_int proto; - if (caplen < 2) - return; + if (caplen < 2) + return; - if(packet[0] == PPP_ADDRESS) { - if (caplen < 4) - return; + if(packet[0] == PPP_ADDRESS) { + if (caplen < 4) + return; - packet += 2; - length -= 2; + packet += 2; + length -= 2; - proto = EXTRACT_16BITS(packet); - packet += 2; - length -= 2; + proto = EXTRACT_16BITS(packet); + packet += 2; + length -= 2; - if(proto == PPP_IP || proto == ETHERTYPE_IP || proto == ETHERTYPE_IPV6) { - handle_ip_packet((struct ip*)packet, -1); - } + if(proto == PPP_IP || proto == ETHERTYPE_IP + || proto == ETHERTYPE_IPV6) { + handle_ip_packet((struct ip*)packet, -1, length); + } } } @@ -596,24 +607,25 @@ static void handle_cooked_packet(unsigned char *args, const struct pcap_pkthdr * dir=1; break; } - handle_ip_packet((struct ip*)(packet+SLL_HDR_LEN), dir); + handle_ip_packet((struct ip*)(packet+SLL_HDR_LEN), dir, + thdr->len - SLL_HDR_LEN); } #endif /* DLT_LINUX_SLL */ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) { struct ether_header *eptr; - int ether_type; - const unsigned char *payload; + int ether_type, hdrlen; + eptr = (struct ether_header*)packet; ether_type = ntohs(eptr->ether_type); - payload = packet + sizeof(struct ether_header); + hdrlen = sizeof(struct ether_header); if(ether_type == ETHERTYPE_8021Q) { struct vlan_8021q_header* vptr; - vptr = (struct vlan_8021q_header*)payload; + vptr = (struct vlan_8021q_header*) (packet + hdrlen); ether_type = ntohs(vptr->ether_type); - payload += sizeof(struct vlan_8021q_header); + hdrlen += sizeof(struct vlan_8021q_header); } if(ether_type == ETHERTYPE_IP || ether_type == ETHERTYPE_IPV6) { @@ -637,8 +649,8 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt } /* Distinguishing ip_hdr and ip6_hdr will be done later. */ - iptr = (struct ip*)(payload); /* alignment? */ - handle_ip_packet(iptr, dir); + iptr = (struct ip*) (packet + hdrlen); /* alignment? */ + handle_ip_packet(iptr, dir, pkthdr->len - hdrlen); } } @@ -651,7 +663,8 @@ static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr { /* 802.11 MAC header is = 34 bytes (not sure if that's universally true) */ /* We could try harder to figure out hardware direction from the MAC header */ - handle_ip_packet((struct ip*)(packet + ((struct radiotap_header *)packet)->it_len + 34),-1); + int hdrlen = ((struct radiotap_header *)packet)->it_len + 34; + handle_ip_packet((struct ip*)(packet + hdrlen), -1, pkthdr->len - hdrlen); } -- 2.3.5 From fred at fperrin.net Thu Apr 23 11:09:56 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:09:56 +0000 Subject: [Iftop-users] [PATCH 2/4] Do traffic accounting in pps In-Reply-To: <1429783797-28903-1-git-send-email-fred@fperrin.net> References: <1429783797-28903-1-git-send-email-fred@fperrin.net> Message-ID: <1429783797-28903-3-git-send-email-fred@fperrin.net> From: Fr?d?ric Perrin Add a "-u unit" CLI option, as well as a "bandwidth-unit" configuration file option. With "-u packets", traffic is accounted using packets per second; the other options are "-u bits" and "-u bytes". "-B" is still recognized as synonym to "-u bytes". The default is "-u bits", keeping the current behaviour of iftop (everything is in bits/s, except the cumulative totals). --- cfgfile.c | 3 ++- iftop.8 | 12 +++++++++--- iftop.c | 24 ++++++++++++++++-------- options.c | 39 ++++++++++++++++++++++++++++++++++----- options.h | 8 +++++++- tui.c | 16 ++++++++-------- ui.c | 33 ++++++++++++++++++++------------- ui_common.c | 22 +++++++++++++++------- ui_common.h | 2 +- 9 files changed, 112 insertions(+), 47 deletions(-) diff --git a/cfgfile.c b/cfgfile.c index fa50c9e..581909b 100644 --- a/cfgfile.c +++ b/cfgfile.c @@ -30,7 +30,8 @@ char * config_directives[] = { "promiscuous", "hide-source", "hide-destination", - "use-bytes", + "use-bytes", + "bandwidth-unit", "sort", "line-display", "show-totals", diff --git a/iftop.8 b/iftop.8 index 90f3dc2..0dbaac0 100644 --- a/iftop.8 +++ b/iftop.8 @@ -11,7 +11,7 @@ iftop - display bandwidth usage on an interface by host .SH SYNOPSIS \fBiftop\fP \fB-h\fP | -[\fB-nNpblBP\fP] [\fB-i\fP \fIinterface\fP] [\fB-f\fP \fIfilter code\fP] [\fB-F\fP \fInet\fP/\fImask\fP] +[\fB-nNpblP\fP] [\fB-u\fP \fIunit\fP] [\fB-i\fP \fIinterface\fP] [\fB-f\fP \fIfilter code\fP] [\fB-F\fP \fInet\fP/\fImask\fP] [\fB-G\fP \fInet6\fP/\fImask6\fP] .SH DESCRIPTION \fBiftop\fP listens to network traffic on a named \fIinterface\fP, or on the @@ -75,8 +75,11 @@ Don't display bar graphs of traffic. \fB-m\fP \fIlimit\fP Set the upper limit for the bandwidth scale. Specified as a number with a 'K', 'M' or 'G' suffix. .TP +\fB-u\fP \fIbits\fP|\fIbytes\fP|\fIpackets\fP +Display bandwidth rates in the given unit (per second). +.TP \fB-B\fP -Display bandwidth rates in bytes/sec rather than bits/sec. +Synonym for \fB-u\fP \fIbits\fP. .TP \fB-i\fP \fIinterface\fP Listen to packets on \fIinterface\fP. @@ -236,8 +239,11 @@ Hides source host names. \fBhide-destination:\fP \fI(yes|no)\fP Hides destination host names. .TP +\fBbandwidth-unit:\fP \fI(bits|bytes|packets)\fP +Use the specified unit for bandwidth display. The default is bits. +.TP \fBuse-bytes:\fP \fI(yes|no)\fP -Use bytes for bandwidth display, rather than bits. +\fBuse-bytes: yes\fP is a synonym of \fBbandwidth-unit: packets\fP. .TP \fBsort:\fP \fI(2s|10s|40s|source|destination)\fP Sets which column is used to sort the display. diff --git a/iftop.c b/iftop.c index a090dcf..f887d93 100644 --- a/iftop.c +++ b/iftop.c @@ -431,14 +431,22 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) } /* Do accounting. */ - switch (IP_V(iptr)) { - case 4: - len = ntohs(iptr->ip_len); - break; - case 6: - len = ntohs(ip6tr->ip6_plen) + 40; - default: - break; + switch (options.bandwidth_unit) { + case OPTION_BW_BITS: + case OPTION_BW_BYTES: + switch (IP_V(iptr)) { + case 4: + len = ntohs(iptr->ip_len); + break; + case 6: + len = ntohs(ip6tr->ip6_plen) + 40; + default: + break; + } + break; + case OPTION_BW_PKTS: + len = 1; + break; } /* Update record */ diff --git a/options.c b/options.c index b438d4c..10b08e7 100644 --- a/options.c +++ b/options.c @@ -30,7 +30,7 @@ options_t options; -char optstr[] = "+i:f:nNF:G:lhpbBPm:c:s:tL:o:"; +char optstr[] = "+i:f:nNF:G:lhpbBu:Pm:c:s:tL:o:"; /* Global options. */ @@ -75,6 +75,13 @@ config_enumeration_type showports_enumeration[] = { { NULL, -1 } }; +config_enumeration_type bandwidth_unit_enumeration[] = { + { "bits", OPTION_BW_BITS }, + { "bytes", OPTION_BW_BYTES }, + { "packets", OPTION_BW_PKTS }, + { NULL, -1 } +}; + static int is_bad_interface_name(char *i) { char **p; for (p = bad_interface_names; *p; ++p) @@ -145,7 +152,7 @@ void options_set_defaults() { options.aggregate_dest = 0; options.paused = 0; options.showhelp = 0; - options.bandwidth_in_bytes = 0; + options.bandwidth_unit = OPTION_BW_BITS; options.sort = OPTION_SORT_DIV2; options.screenfilter = NULL; options.freezeorder = 0; @@ -188,7 +195,8 @@ static void usage(FILE *fp) { " -p run in promiscuous mode (show traffic between other\n" " hosts on the same network segment)\n" " -b don't display a bar graph of traffic\n" -" -B Display bandwidth in bytes\n" +" -B display bandwidth in bytes\n" +" -a display bandwidth in packets\n" " -i interface listen on named interface\n" " -f filter code use filter code to select packets to count\n" " (default: none, but only IP packets are counted)\n" @@ -271,9 +279,13 @@ void options_read_args(int argc, char **argv) { break; case 'B': - config_set_string("use-bytes", "true"); + config_set_string("bandwidth-unit", "bytes"); break; + case 'u': + config_set_string("bandwidth-unit", optarg); + break; + case 's': config_set_string("timed-output", optarg); break; @@ -370,6 +382,23 @@ int options_config_get_promiscuous() { return 0; } +int options_config_get_bw_unit() { + int i; + + if (options_config_get_enum("bandwidth-unit", bandwidth_unit_enumeration, + (int*)&options.bandwidth_unit)) + return 1; + /* compatibility with use-bytes / -B */ + if (options_config_get_bool("use-bytes", &i)) { + if (i) + options.bandwidth_unit = OPTION_BW_BYTES; + else + options.bandwidth_unit = OPTION_BW_BITS; + return 1; + } + return 0; +} + int options_config_get_bw_rate(char *directive, long long* result) { char* units; long long mult = 1; @@ -544,7 +573,7 @@ void options_make() { options_config_get_promiscuous(); options_config_get_bool("hide-source", &options.aggregate_src); options_config_get_bool("hide-destination", &options.aggregate_dest); - options_config_get_bool("use-bytes", &options.bandwidth_in_bytes); + options_config_get_bw_unit(); options_config_get_enum("sort", sort_enumeration, (int*)&options.sort); options_config_get_enum("line-display", linedisplay_enumeration, (int*)&options.linedisplay); options_config_get_bool("show-totals", &options.show_totals); diff --git a/options.h b/options.h index 8526254..9628dfe 100644 --- a/options.h +++ b/options.h @@ -34,6 +34,12 @@ typedef enum { OPTION_LINEDISPLAY_ONE_LINE_SENT } option_linedisplay_t; +typedef enum { + OPTION_BW_BITS, + OPTION_BW_BYTES, + OPTION_BW_PKTS, +} option_bw_unit_t; + /* * This structure has to be defined in the same order as the config * directives in cfgfile.c. Clearly this is EBW. @@ -59,7 +65,7 @@ typedef struct { int timed_output; int no_curses; int num_lines; - int bandwidth_in_bytes; + option_bw_unit_t bandwidth_unit; option_sort_t sort; int bar_interval; diff --git a/tui.c b/tui.c index 31d4109..75c6e08 100644 --- a/tui.c +++ b/tui.c @@ -87,7 +87,7 @@ void tui_print() { /* Send rate per connection */ printf("%4d %s%s", l, host1, " =>"); for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size(screen_line->sent[j], buf0_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(screen_line->sent[j], buf0_10, 10, 1024, options.bandwidth_unit); printf(" %10s", buf0_10); } /* Cumulative sent data per connection */ @@ -97,7 +97,7 @@ void tui_print() { /* Receive rate per connection */ printf(" %s%s", host2, " <="); for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size(screen_line->recv[j], buf0_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(screen_line->recv[j], buf0_10, 10, 1024, options.bandwidth_unit); printf(" %10s", buf0_10); } /* Cumulative received data per connection */ @@ -115,21 +115,21 @@ void tui_print() { snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send rate:"); printf("%s ", labellong); for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size((((host_pair_line *)&totals)->sent[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(((host_pair_line *)&totals)->sent[j], buf0_10, 10, 1024, options.bandwidth_unit); printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' '); } snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total receive rate:"); printf("%s ", labellong); for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size((((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(((host_pair_line *)&totals)->recv[j], buf0_10, 10, 1024, options.bandwidth_unit); printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' '); } snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send and receive rate:"); printf("%s ", labellong); for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size((((host_pair_line *)&totals)->sent[j] + ((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(((host_pair_line *)&totals)->sent[j] + ((host_pair_line *)&totals)->recv[j], buf0_10, 10, 1024, options.bandwidth_unit); printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' '); } @@ -141,9 +141,9 @@ void tui_print() { /* Peak traffic */ snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Peak rate (sent/received/total):"); - readable_size(peaksent / RESOLUTION, buf0_10, 10, 1024, options.bandwidth_in_bytes); - readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_in_bytes); - readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_in_bytes); + readable_size(peaksent / RESOLUTION, buf0_10, 10, 1024, options.bandwidth_unit); + readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_unit); + readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_unit); printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10); /* Cumulative totals */ diff --git a/ui.c b/ui.c index 57ca6c0..771be31 100644 --- a/ui.c +++ b/ui.c @@ -153,7 +153,7 @@ static void draw_bar_scale(int* y) { char s[40], *p; int x; /* This 1024 vs 1000 stuff is just plain evil */ - readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_in_bytes); + readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_unit); p = s + strspn(s, " "); x = get_bar_length(i * 8); mvaddch(*y + 1, x, ACS_BTEE); @@ -177,13 +177,13 @@ static void draw_bar_scale(int* y) { } } -void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t linedisplay, int bytes) { +void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t linedisplay, option_bw_unit_t unit) { char buf[10]; float n = 0; switch(linedisplay) { case OPTION_LINEDISPLAY_TWO_LINE: - draw_line_total(sent, recv, y, x, OPTION_LINEDISPLAY_ONE_LINE_SENT, bytes); - draw_line_total(sent, recv, y+1, x, OPTION_LINEDISPLAY_ONE_LINE_RECV, bytes); + draw_line_total(sent, recv, y, x, OPTION_LINEDISPLAY_ONE_LINE_SENT, unit); + draw_line_total(sent, recv, y+1, x, OPTION_LINEDISPLAY_ONE_LINE_RECV, unit); break; case OPTION_LINEDISPLAY_ONE_LINE_SENT: n = sent; @@ -196,7 +196,7 @@ void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t break; } if(linedisplay != OPTION_LINEDISPLAY_TWO_LINE) { - readable_size(n, buf, 10, 1024, bytes); + readable_size(n, buf, 10, 1024, unit); mvaddstr(y, x, buf); } } @@ -214,7 +214,7 @@ void draw_line_totals(int y, host_pair_line* line, option_linedisplay_t linedisp int x = (COLS - 8 * HISTORY_DIVISIONS); for(j = 0; j < HISTORY_DIVISIONS; j++) { - draw_line_total(line->sent[j], line->recv[j], y, x, linedisplay, options.bandwidth_in_bytes); + draw_line_total(line->sent[j], line->recv[j], y, x, linedisplay, options.bandwidth_unit); x += 8; } @@ -247,7 +247,7 @@ void draw_totals(host_pair_line* totals) { draw_line_totals(y, totals, OPTION_LINEDISPLAY_TWO_LINE); y += 2; for(j = 0; j < HISTORY_DIVISIONS; j++) { - readable_size((totals->sent[j] + totals->recv[j]) , buf, 10, 1024, options.bandwidth_in_bytes); + readable_size((totals->sent[j] + totals->recv[j]) , buf, 10, 1024, options.bandwidth_unit); mvaddstr(y, x, buf); x += 8; } @@ -262,6 +262,7 @@ void ui_print() { static char *line; static int lcols; int y = 0; + option_bw_unit_t cumunit; if (dontshowdisplay) return; @@ -375,25 +376,31 @@ void ui_print() { /* Cummulative totals */ mvaddstr(y, 16, "cum: "); - readable_size(history_totals.total_sent, line, 10, 1024, 1); + /* Previous versions of iftop always displayed totals in bytes, even when + use-bytes = false. Stay compatible when the default unit hasn't been + changed. */ + cumunit = options.bandwidth_unit; + if (cumunit == OPTION_BW_BITS) + cumunit = OPTION_BW_BYTES; + readable_size(history_totals.total_sent, line, 10, 1024, cumunit); mvaddstr(y, 22, line); - readable_size(history_totals.total_recv, line, 10, 1024, 1); + readable_size(history_totals.total_recv, line, 10, 1024, cumunit); mvaddstr(y+1, 22, line); - readable_size(history_totals.total_recv + history_totals.total_sent, line, 10, 1024, 1); + readable_size(history_totals.total_recv + history_totals.total_sent, line, 10, 1024, cumunit); mvaddstr(y+2, 22, line); /* peak traffic */ mvaddstr(y, 32, "peak: "); - readable_size(peaksent / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes); + readable_size(peaksent / RESOLUTION, line, 10, 1024, options.bandwidth_unit); mvaddstr(y, 39, line); - readable_size(peakrecv / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes); + readable_size(peakrecv / RESOLUTION, line, 10, 1024, options.bandwidth_unit); mvaddstr(y+1, 39, line); - readable_size(peaktotal / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes); + readable_size(peaktotal / RESOLUTION, line, 10, 1024, options.bandwidth_unit); mvaddstr(y+2, 39, line); mvaddstr(y, COLS - 8 * HISTORY_DIVISIONS - 8, "rates:"); diff --git a/ui_common.c b/ui_common.c index a4d4ba0..dcf6646 100644 --- a/ui_common.c +++ b/ui_common.c @@ -21,8 +21,11 @@ int history_divs[HISTORY_DIVISIONS] = {1, 5, 20}; #define UNIT_DIVISIONS 4 -char* unit_bits[UNIT_DIVISIONS] = { "b", "Kb", "Mb", "Gb"}; -char* unit_bytes[UNIT_DIVISIONS] = { "B", "KB", "MB", "GB"}; +char* unit_disp[][UNIT_DIVISIONS] = { + [OPTION_BW_BITS] = { "b", "Kb", "Mb", "Gb"}, + [OPTION_BW_BYTES] = { "B", "KB", "MB", "GB"}, + [OPTION_BW_PKTS] = { "p", "Kp", "Mp", "GB"}, +}; extern hash_type* history; extern int history_pos; @@ -121,29 +124,34 @@ int screen_line_compare(void* a, void* b) { /* * Format a data size in human-readable format */ -void readable_size(float n, char* buf, int bsize, int ksize, int bytes) { +void readable_size(float n, char* buf, int bsize, int ksize, + option_bw_unit_t unit) { int i = 0; float size = 1; /* Convert to bits? */ - if(bytes == 0) { + if (unit == OPTION_BW_BITS) { n *= 8; } + /* Force power of ten for pps */ + if (unit == OPTION_BW_PKTS) + ksize = 1000; + while(1) { if(n < size * 1000 || i >= UNIT_DIVISIONS - 1) { - snprintf(buf, bsize, " %4.0f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]); + snprintf(buf, bsize, " %4.0f%s", n / size, unit_disp[unit][i]); break; } i++; size *= ksize; if(n < size * 10) { - snprintf(buf, bsize, " %4.2f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]); + snprintf(buf, bsize, " %4.2f%s", n / size, unit_disp[unit][i]); break; } else if(n < size * 100) { - snprintf(buf, bsize, " %4.1f%s", n / size, bytes ? unit_bytes[i] : unit_bits[i]); + snprintf(buf, bsize, " %4.1f%s", n / size, unit_disp[unit][i]); break; } } diff --git a/ui_common.h b/ui_common.h index e4fcc2e..63ae5bb 100644 --- a/ui_common.h +++ b/ui_common.h @@ -43,6 +43,6 @@ hash_type* service_hash; void analyse_data(void); void screen_list_init(void); void sprint_host(char * line, int af, struct in6_addr* addr, unsigned int port, unsigned int protocol, int L, int unspecified_as_star); -void readable_size(float, char*, int, int, int); +void readable_size(float, char*, int, int, option_bw_unit_t); #endif /* __UI_COMMON_H_ */ -- 2.3.5 From fred at fperrin.net Thu Apr 23 11:12:39 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:12:39 +0000 Subject: [Iftop-users] iftop performance issue Message-ID: <1429783960-29164-1-git-send-email-fred@fperrin.net> Hi list, On my machine, if I generate the following IPv6 flood: ip -6 neigh add fe80::1234 dev eth0 lladdr 00:11:22:33:44:55 nc -6 -u fe80::1234%eth0 1234 < /dev/zero The traffic reported by iftop is much less than the reality, as iftop can't read packets off pcap fast enough. This patch only demonstrate the problem, I don't intend for it to be applied. I haven't started to dig into the cause yet. From fred at fperrin.net Thu Apr 23 11:12:40 2015 From: fred at fperrin.net (fred at fperrin.net) Date: Thu, 23 Apr 2015 10:12:40 +0000 Subject: [Iftop-users] [PATCH 4/4] Keep track of lost packets as reported by pcap_stats In-Reply-To: <1429783960-29164-1-git-send-email-fred@fperrin.net> References: <1429783960-29164-1-git-send-email-fred@fperrin.net> Message-ID: <1429783960-29164-2-git-send-email-fred@fperrin.net> From: Fr?d?ric Perrin On my machine, if I generate the following IPv6 flood: ip -6 neigh add fe80::1234 dev eth0 lladdr 00:11:22:33:44:55 nc -6 -u fe80::1234%eth0 1234 < /dev/zero The traffic reported by iftop is much less than the reality, as iftop can't read packets off pcap fast enough. This patch only demonstrate the problem, I haven't started to dig into the cause yet. --- iftop.c | 5 +++++ iftop.h | 1 + tui.c | 5 +++++ ui.c | 4 +++- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/iftop.c b/iftop.c index 1640b11..562a45b 100644 --- a/iftop.c +++ b/iftop.c @@ -109,6 +109,8 @@ history_type* history_create() { void history_rotate() { hash_node_type* n = NULL; + struct pcap_stat ps; + history_pos = (history_pos + 1) % HISTORY_LENGTH; hash_next_item(history, &n); while(n != NULL) { @@ -134,6 +136,9 @@ void history_rotate() { if(history_len < HISTORY_LENGTH) { history_len++; } + + pcap_stats(pd, &ps); + history_totals.lost_packets = ps.ps_drop + ps.ps_ifdrop; } diff --git a/iftop.h b/iftop.h index f273c0f..e5279d1 100644 --- a/iftop.h +++ b/iftop.h @@ -28,6 +28,7 @@ typedef struct { long sent[HISTORY_LENGTH]; double long total_sent; double long total_recv; + long lost_packets; int last_write; } history_type; diff --git a/tui.c b/tui.c index 75c6e08..ebf7b4f 100644 --- a/tui.c +++ b/tui.c @@ -153,6 +153,11 @@ void tui_print() { readable_size(history_totals.total_recv + history_totals.total_sent, buf2_10, 10, 1024, 1); printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10); + /* Dropped packets */ + snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Dropped packets:"); + readable_size(history_totals.lost_packets, buf0_10, 10, 1024, options.bandwidth_unit); + printf("%s %10s\n", labellong, buf0_10, buf1_10, buf2_10); + /* Double divider line */ for (j = 0; j < PRINT_WIDTH + 52; j++) { printf("="); diff --git a/ui.c b/ui.c index 771be31..37bf3d5 100644 --- a/ui.c +++ b/ui.c @@ -400,7 +400,9 @@ void ui_print() { readable_size(peakrecv / RESOLUTION, line, 10, 1024, options.bandwidth_unit); mvaddstr(y+1, 39, line); - readable_size(peaktotal / RESOLUTION, line, 10, 1024, options.bandwidth_unit); + /* lost packets */ + mvaddstr(y+2, 32, "lost: "); + readable_size(history_totals.lost_packets, line, 10, 1000, OPTION_BW_PKTS); mvaddstr(y+2, 39, line); mvaddstr(y, COLS - 8 * HISTORY_DIVISIONS - 8, "rates:"); -- 2.3.5 From alijawad1 at gmail.com Thu Apr 23 11:17:48 2015 From: alijawad1 at gmail.com (Ali Jawad) Date: Thu, 23 Apr 2015 12:17:48 +0200 Subject: [Iftop-users] unsubscribe Message-ID: unsubscribe On Thu, Apr 23, 2015 at 12:12 PM, wrote: > Hi list, > > On my machine, if I generate the following IPv6 flood: > > ip -6 neigh add fe80::1234 dev eth0 lladdr 00:11:22:33:44:55 > nc -6 -u fe80::1234%eth0 1234 < /dev/zero > > The traffic reported by iftop is much less than the reality, as iftop > can't read packets off pcap fast enough. This patch only demonstrate > the problem, I don't intend for it to be applied. I haven't started to > dig into the cause yet. > > > _______________________________________________ > iftop-users mailing list > iftop-users at lists.beasts.org > http://lists.beasts.org/mailman/listinfo/iftop-users > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pdw at ex-parrot.com Thu Apr 23 12:02:07 2015 From: pdw at ex-parrot.com (Paul Warren) Date: Thu, 23 Apr 2015 12:02:07 +0100 Subject: [Iftop-users] Add traffic accounting in PPS; drop short packets In-Reply-To: <1429783797-28903-1-git-send-email-fred@fperrin.net> References: <1429783797-28903-1-git-send-email-fred@fperrin.net> Message-ID: <5538D12F.4070404@ex-parrot.com> Fr?d?ric, Thank you for these. I will review and apply. regards, Paul On 23/04/2015 11:09, fred at fperrin.net wrote: > Hi list, > > I'm sending the following patches. The first is a one-liner gcc was > complaining about; the second add a new feature to do traffic > accounting in packet per second rather than bit/s; the third is a fix > to handle_ip_packet() which was reading past the end of certain > malformed packets. > > [PATCH 1/4] Silence a warning > [PATCH 2/4] Do traffic accounting in pps > [PATCH 3/4] Drop packets shorter than sizeof (struct iphdr) > > _______________________________________________ > iftop-users mailing list > iftop-users at lists.beasts.org > http://lists.beasts.org/mailman/listinfo/iftop-users >