X-Git-Url: http://gitweb.fperrin.net/?p=iftop.git;a=blobdiff_plain;f=iftop.c;h=a090dcf84a18e63b7b4f74f9a1e6c6268753d7e2;hp=97020ea3f2fae72786bde4a3f7438039571ac76e;hb=HEAD;hpb=cd1db5a0a5c698b647e554a003c7e48b5db695f5 diff --git a/iftop.c b/iftop.c index 97020ea..a090dcf 100644 --- a/iftop.c +++ b/iftop.c @@ -5,13 +5,6 @@ #include "integers.h" -#if defined(HAVE_PCAP_H) -# include -#elif defined(HAVE_PCAP_PCAP_H) -# include -#else -# error No pcap.h -#endif #include #include #include @@ -19,18 +12,29 @@ #include #include #include -#include +/* include -- this was added by the PFLOG patch but seems + * superfluous and breaks on Slackware */ +#if defined(HAVE_PCAP_H) +# include +#elif defined(HAVE_PCAP_PCAP_H) +# include +#else +# error No pcap.h +#endif #include #include #include #include #include +#include #include "iftop.h" #include "addr_hash.h" #include "resolver.h" +#include "ui_common.h" #include "ui.h" +#include "tui.h" #include "options.h" #ifdef DLT_LINUX_SLL #include "sll.h" @@ -45,12 +49,13 @@ #include "ethertype.h" #include "cfgfile.h" #include "ppp.h" +#include "addrs_ioctl.h" #include /* ethernet address of interface. */ int have_hw_addr = 0; -unsigned char if_hw_addr[6]; +char if_hw_addr[6]; /* IP address of interface */ int have_ip_addr = 0; @@ -63,6 +68,7 @@ extern options_t options; hash_type* history; history_type history_totals; time_t last_timestamp; +time_t first_timestamp; int history_pos = 0; int history_len = 1; pthread_mutex_t tick_mutex; @@ -80,9 +86,14 @@ static void finish(int sig) { -/* Only need ethernet (plus optional 4 byte VLAN) and IP headers (48) + first 2 bytes of tcp/udp header */ +/* Only need ethernet (plus optional 4 byte VLAN) and IP headers (48) + first 2 + * bytes of tcp/udp header */ /* Increase with a further 20 to account for IPv6 header length. */ -#define CAPTURE_LENGTH 92 +/* IEEE 802.11 radiotap throws in a variable length header plus 8 (radiotap + * header header) plus 34 (802.11 MAC) plus 40 (IPv6) = 78, plus whatever's in + * the radiotap payload */ +/*#define CAPTURE_LENGTH 92 */ +#define CAPTURE_LENGTH 256 void init_history() { history = addr_hash_create(); @@ -133,14 +144,28 @@ void tick(int print) { t = time(NULL); if(t - last_timestamp >= RESOLUTION) { - //printf("TICKING\n"); analyse_data(); - ui_print(); + if (options.no_curses) { + if (!options.timed_output || (options.timed_output && t - first_timestamp >= options.timed_output)) { + tui_print(); + if (options.timed_output) { + finish(SIGINT); + } + } + } + else { + ui_print(); + } history_rotate(); last_timestamp = t; } else { - ui_tick(print); + if (options.no_curses) { + tui_tick(print); + } + else { + ui_tick(print); + } } pthread_mutex_unlock(&tick_mutex); @@ -152,11 +177,11 @@ int in_filter_net(struct in_addr addr) { return ret; } -int __inline__ ip_addr_match(struct in_addr addr) { +static int __inline__ ip_addr_match(struct in_addr addr) { return addr.s_addr == if_ip_addr.s_addr; } -int __inline__ ip6_addr_match(struct in6_addr *addr) { +static int __inline__ ip6_addr_match(struct in6_addr *addr) { return IN6_ARE_ADDR_EQUAL(addr, &if_ip6_addr); } @@ -229,8 +254,8 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) int direction = 0; /* incoming */ history_type* ht; union { - history_type **ht_pp; - void **void_pp; + history_type **ht_pp; + void **void_pp; } u_ht = { &ht }; addr_pair ap; unsigned int len = 0; @@ -241,6 +266,8 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) memset(&ap, '\0', sizeof(ap)); + tick(0); + if( (IP_V(iptr) ==4 && options.netfilter == 0) || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { /* @@ -279,6 +306,14 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) assign_addr_pair(&ap, iptr, 1); direction = 0; } + else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) { + assign_addr_pair(&ap, iptr, 1); + direction = 0; + } + else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) { + assign_addr_pair(&ap, iptr, 1); + direction = 0; + } /* * Cannot determine direction from hardware or IP levels. Therefore * assume that it was a packet between two other machines, assign @@ -297,6 +332,8 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) direction = 0; } /* Drop other uncertain packages. */ + else + return; } if(IP_V(iptr) == 4 && options.netfilter != 0) { @@ -328,11 +365,11 @@ static void handle_ip_packet(struct ip* iptr, int hw_dir) /* First reduce the participating addresses using the netfilter prefix. * We need scratch pads to do this. */ - for (j=0; j < 4; ++j) { - scribdst.s6_addr32[j] = ip6tr->ip6_dst.s6_addr32[j] - & options.netfilter6mask.s6_addr32[j]; - scribsrc.s6_addr32[j] = ip6tr->ip6_src.s6_addr32[j] - & options.netfilter6mask.s6_addr32[j]; + for (j=0; j < 16; ++j) { + scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j] + & options.netfilter6mask.s6_addr[j]; + scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j] + & options.netfilter6mask.s6_addr[j]; } /* Now look for any hits. */ @@ -445,10 +482,15 @@ 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, length); + handle_ip_packet((struct ip*)packet, -1); } #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); +} + static void handle_llc_packet(const struct llc* llc, int dir) { struct ip* ip = (struct ip*)((void*)llc + sizeof(struct llc)); @@ -457,9 +499,9 @@ static void handle_llc_packet(const struct llc* llc, int dir) { if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP && llc->llcui == LLC_UI) { u_int32_t orgcode; - register u_short et; + u_int16_t et; orgcode = EXTRACT_24BITS(&llc->llc_orgcode[0]); - et = EXTRACT_16BITS(&llc->llc_ethertype[0]); + et = (llc->llc_ethertype[0] << 8) + llc->llc_ethertype[1]; switch(orgcode) { case OUI_ENCAP_ETHER: case OUI_CISCO_90: @@ -559,12 +601,10 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt ether_type = ntohs(eptr->ether_type); payload = packet + sizeof(struct ether_header); - tick(0); - if(ether_type == ETHERTYPE_8021Q) { - struct vlan_8021q_header* vptr; - vptr = (struct vlan_8021q_header*)payload; - ether_type = ntohs(vptr->ether_type); + struct vlan_8021q_header* vptr; + vptr = (struct vlan_8021q_header*)payload; + ether_type = ntohs(vptr->ether_type); payload += sizeof(struct vlan_8021q_header); } @@ -580,11 +620,11 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt dir = 1; } else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) { - /* packet entering this i/f */ - dir = 0; - } - else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) { - /* broadcast packet, count as incoming */ + /* packet entering this i/f */ + dir = 0; + } + else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) { + /* broadcast packet, count as incoming */ dir = 0; } @@ -594,6 +634,20 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt } } +#ifdef DLT_IEEE802_11_RADIO +/* + * Packets with a bonus radiotap header. + * See http://www.gsp.com/cgi-bin/man.cgi?section=9&topic=ieee80211_radiotap + */ +static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet) +{ + /* 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); +} + + +#endif /* set_filter_code: * Install some filter code. Returns NULL on success or an error message on @@ -626,7 +680,6 @@ char *set_filter_code(const char *filter) { void packet_init() { char errbuf[PCAP_ERRBUF_SIZE]; char *m; - int s; int i; int dlt; int result; @@ -682,9 +735,22 @@ void packet_init() { packet_handler = handle_pflog_packet; } #endif - else if(dlt == DLT_RAW || dlt == DLT_NULL) { + else if(dlt == DLT_RAW) { packet_handler = handle_raw_packet; } + else if(dlt == DLT_NULL) { + packet_handler = handle_null_packet; + } +#ifdef DLT_LOOP + else if(dlt == DLT_LOOP) { + packet_handler = handle_null_packet; + } +#endif +#ifdef DLT_IEEE802_11_RADIO + else if(dlt == DLT_IEEE802_11_RADIO) { + packet_handler = handle_radiotap_packet; + } +#endif else if(dlt == DLT_IEEE802) { packet_handler = handle_tokenring_packet; } @@ -726,6 +792,8 @@ int main(int argc, char **argv) { pthread_t thread; struct sigaction sa = {}; + setlocale(LC_ALL, ""); + /* TODO: tidy this up */ /* read command line options and config file */ config_init(); @@ -744,11 +812,31 @@ int main(int argc, char **argv) { init_history(); - ui_init(); + if (options.no_curses) { + tui_init(); + } + else { + ui_init(); + } pthread_create(&thread, NULL, (void*)&packet_loop, NULL); - ui_loop(); + /* Keep the starting time (used for timed termination) */ + first_timestamp = time(NULL); + + if (options.no_curses) { + if (options.timed_output) { + while(!foad) { + sleep(1); + } + } + else { + tui_loop(); + } + } + else { + ui_loop(); + } pthread_cancel(thread);