11 #include <sys/types.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
15 /* include <net/bpf.h> -- this was added by the PFLOG patch but seems
16 * superfluous and breaks on Slackware */
17 #if defined(HAVE_PCAP_H)
19 #elif defined(HAVE_PCAP_PCAP_H)
20 # include <pcap/pcap.h>
33 #include "addr_hash.h"
35 #include "ui_common.h"
41 #endif /* DLT_LINUX_SLL */
42 #include "threadprof.h"
49 #include "ethertype.h"
52 #include "addrs_ioctl.h"
54 #include <netinet/ip6.h>
56 /* ethernet address of interface. */
60 /* IP address of interface */
62 int have_ip6_addr = 0;
63 struct in_addr if_ip_addr;
64 struct in6_addr if_ip6_addr;
66 extern options_t options;
69 history_type history_totals;
70 time_t last_timestamp;
71 time_t first_timestamp;
74 pthread_mutex_t tick_mutex;
76 pcap_t* pd; /* pcap descriptor */
77 struct bpf_program pcap_filter;
78 pcap_handler packet_handler;
82 static void finish(int sig) {
89 /* Only need ethernet (plus optional 4 byte VLAN) and IP headers (48) + first 2
90 * bytes of tcp/udp header */
91 /* Increase with a further 20 to account for IPv6 header length. */
92 /* IEEE 802.11 radiotap throws in a variable length header plus 8 (radiotap
93 * header header) plus 34 (802.11 MAC) plus 40 (IPv6) = 78, plus whatever's in
94 * the radiotap payload */
95 /*#define CAPTURE_LENGTH 92 */
96 #define CAPTURE_LENGTH 256
99 history = addr_hash_create();
100 last_timestamp = time(NULL);
101 memset(&history_totals, 0, sizeof history_totals);
104 history_type* history_create() {
106 h = xcalloc(1, sizeof *h);
110 void history_rotate() {
111 hash_node_type* n = NULL;
112 history_pos = (history_pos + 1) % HISTORY_LENGTH;
113 hash_next_item(history, &n);
115 hash_node_type* next = n;
116 history_type* d = (history_type*)n->rec;
117 hash_next_item(history, &next);
119 if(d->last_write == history_pos) {
120 addr_pair key = *(addr_pair*)(n->key);
121 hash_delete(history, &key);
125 d->recv[history_pos] = 0;
126 d->sent[history_pos] = 0;
131 history_totals.sent[history_pos] = 0;
132 history_totals.recv[history_pos] = 0;
134 if(history_len < HISTORY_LENGTH) {
140 void tick(int print) {
143 pthread_mutex_lock(&tick_mutex);
146 if(t - last_timestamp >= RESOLUTION) {
148 if (options.no_curses) {
149 if (!options.timed_output || (options.timed_output && t - first_timestamp >= options.timed_output)) {
151 if (options.timed_output) {
163 if (options.no_curses) {
171 pthread_mutex_unlock(&tick_mutex);
174 int in_filter_net(struct in_addr addr) {
176 ret = ((addr.s_addr & options.netfiltermask.s_addr) == options.netfilternet.s_addr);
180 static int __inline__ ip_addr_match(struct in_addr addr) {
181 return addr.s_addr == if_ip_addr.s_addr;
184 static int __inline__ ip6_addr_match(struct in6_addr *addr) {
185 return IN6_ARE_ADDR_EQUAL(addr, &if_ip6_addr);
189 * Creates an addr_pair from an ip (and tcp/udp) header, swapping src and dst
192 void assign_addr_pair(addr_pair* ap, struct ip* iptr, int flip) {
193 unsigned short int src_port = 0;
194 unsigned short int dst_port = 0;
196 /* Arrange for predictable values. */
197 memset(ap, '\0', sizeof(*ap));
199 if(IP_V(iptr) == 4) {
201 /* Does this protocol use ports? */
202 if(iptr->ip_p == IPPROTO_TCP || iptr->ip_p == IPPROTO_UDP) {
203 /* We take a slight liberty here by treating UDP the same as TCP */
205 /* Find the TCP/UDP header */
206 struct tcphdr* thdr = ((void*)iptr) + IP_HL(iptr) * 4;
207 src_port = ntohs(thdr->th_sport);
208 dst_port = ntohs(thdr->th_dport);
212 ap->src = iptr->ip_src;
213 ap->src_port = src_port;
214 ap->dst = iptr->ip_dst;
215 ap->dst_port = dst_port;
218 ap->src = iptr->ip_dst;
219 ap->src_port = dst_port;
220 ap->dst = iptr->ip_src;
221 ap->dst_port = src_port;
224 else if (IP_V(iptr) == 6) {
225 /* IPv6 packet seen. */
226 struct ip6_hdr *ip6tr = (struct ip6_hdr *) iptr;
230 if( (ip6tr->ip6_nxt == IPPROTO_TCP) || (ip6tr->ip6_nxt == IPPROTO_UDP) ) {
231 struct tcphdr *thdr = ((void *) ip6tr) + 40;
233 src_port = ntohs(thdr->th_sport);
234 dst_port = ntohs(thdr->th_dport);
238 memcpy(&ap->src6, &ip6tr->ip6_src, sizeof(ap->src6));
239 ap->src_port = src_port;
240 memcpy(&ap->dst6, &ip6tr->ip6_dst, sizeof(ap->dst6));
241 ap->dst_port = dst_port;
244 memcpy(&ap->src6, &ip6tr->ip6_dst, sizeof(ap->src6));
245 ap->src_port = dst_port;
246 memcpy(&ap->dst6, &ip6tr->ip6_src, sizeof(ap->dst6));
247 ap->dst_port = src_port;
252 static void handle_ip_packet(struct ip* iptr, int hw_dir, int pld_len)
254 int direction = 0; /* incoming */
258 history_type **ht_pp;
262 struct in6_addr scribdst; /* Scratch pad. */
263 struct in6_addr scribsrc; /* Scratch pad. */
264 /* Reinterpret packet type. */
265 struct ip6_hdr* ip6tr = (struct ip6_hdr *) iptr;
267 memset(&ap, '\0', sizeof(ap));
272 * Sanity check: drop obviously short packets.
273 * pld_len comes from pcaphdr->len - sizeof(struct l2_header).
275 * It is assumed that the snaplen (currently hard-coded to 1000) is
276 * big enough to always capture the IP header past the L2 encap, and
277 * that pcap never truncates the packet to less than snaplen; in
278 * other words, that pcaphdr->caplen = MIN(pcaphdr->len, snaplen).
280 if (pld_len < sizeof (struct ip))
282 if (IP_V(iptr) == 6 && pld_len < sizeof (struct ip6_hdr))
285 if( (IP_V(iptr) == 4 && options.netfilter == 0)
286 || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) {
288 * Net filter is off, so assign direction based on MAC address
291 /* Packet leaving this interface. */
292 assign_addr_pair(&ap, iptr, 0);
295 else if(hw_dir == 0) {
296 /* Packet incoming */
297 assign_addr_pair(&ap, iptr, 1);
300 /* Packet direction is not given away by h/ware layer. Try IP
303 else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_src)) {
305 assign_addr_pair(&ap, iptr, 0);
308 else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_dst)) {
310 assign_addr_pair(&ap, iptr, 1);
313 else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_src)) {
315 assign_addr_pair(&ap, iptr, 0);
318 else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
320 assign_addr_pair(&ap, iptr, 1);
323 else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) {
324 assign_addr_pair(&ap, iptr, 1);
327 else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) {
328 assign_addr_pair(&ap, iptr, 1);
332 * Cannot determine direction from hardware or IP levels. Therefore
333 * assume that it was a packet between two other machines, assign
334 * source and dest arbitrarily (by numerical value) and account as
337 else if (options.promiscuous_but_choosy) {
338 return; /* junk it */
340 else if((IP_V(iptr) == 4) && (iptr->ip_src.s_addr < iptr->ip_dst.s_addr)) {
341 assign_addr_pair(&ap, iptr, 1);
344 else if(IP_V(iptr) == 4) {
345 assign_addr_pair(&ap, iptr, 0);
348 /* Drop other uncertain packages. */
353 if(IP_V(iptr) == 4 && options.netfilter != 0) {
355 * Net filter on, assign direction according to netmask
357 if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
359 assign_addr_pair(&ap, iptr, 0);
362 else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
364 assign_addr_pair(&ap, iptr, 1);
373 if(IP_V(iptr) == 6 && options.netfilter6 != 0) {
375 * Net filter IPv6 active.
378 //else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
379 /* First reduce the participating addresses using the netfilter prefix.
380 * We need scratch pads to do this.
382 for (j=0; j < 16; ++j) {
383 scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j]
384 & options.netfilter6mask.s6_addr[j];
385 scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j]
386 & options.netfilter6mask.s6_addr[j];
389 /* Now look for any hits. */
390 //if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
391 if (IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
392 && ! IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
394 assign_addr_pair(&ap, iptr, 0);
397 //else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
398 else if (! IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
399 && IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
401 assign_addr_pair(&ap, iptr, 1);
411 /* Test if link-local IPv6 packets should be dropped. */
412 if( IP_V(iptr) == 6 && !options.link_local
413 && (IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_dst)
414 || IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_src)) )
418 /* Do address resolving. */
419 switch (IP_V(iptr)) {
421 ap.protocol = iptr->ip_p;
422 /* Add the addresses to be resolved */
423 /* The IPv4 address is embedded in a in6_addr structure,
424 * so it need be copied, and delivered to resolve(). */
425 memset(&scribdst, '\0', sizeof(scribdst));
426 memcpy(&scribdst, &iptr->ip_dst, sizeof(struct in_addr));
427 resolve(ap.af, &scribdst, NULL, 0);
428 memset(&scribsrc, '\0', sizeof(scribsrc));
429 memcpy(&scribsrc, &iptr->ip_src, sizeof(struct in_addr));
430 resolve(ap.af, &scribsrc, NULL, 0);
433 ap.protocol = ip6tr->ip6_nxt;
434 /* Add the addresses to be resolved */
435 resolve(ap.af, &ip6tr->ip6_dst, NULL, 0);
436 resolve(ap.af, &ip6tr->ip6_src, NULL, 0);
441 if(hash_find(history, &ap, u_ht.void_pp) == HASH_STATUS_KEY_NOT_FOUND) {
442 ht = history_create();
443 hash_insert(history, &ap, ht);
447 switch (options.bandwidth_unit) {
449 case OPTION_BW_BYTES:
460 ht->last_write = history_pos;
461 if( ((IP_V(iptr) == 4) && (iptr->ip_src.s_addr == ap.src.s_addr))
462 || ((IP_V(iptr) == 6) && !memcmp(&ip6tr->ip6_src, &ap.src6, sizeof(ap.src6))) )
464 ht->sent[history_pos] += len;
465 ht->total_sent += len;
468 ht->recv[history_pos] += len;
469 ht->total_recv += len;
474 history_totals.recv[history_pos] += len;
475 history_totals.total_recv += len;
478 history_totals.sent[history_pos] += len;
479 history_totals.total_sent += len;
484 static void handle_raw_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
486 handle_ip_packet((struct ip*)packet, -1, pkthdr->len);
490 static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
492 register u_int length = pkthdr->len;
494 const struct pfloghdr *hdr;
496 hdr = (struct pfloghdr *)packet;
497 hdrlen = BPF_WORDALIGN(hdr->length);
500 handle_ip_packet((struct ip*)packet, -1, length);
504 static void handle_null_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
506 handle_ip_packet((struct ip*)(packet + 4), -1, pkthdr->len);
509 static void handle_llc_packet(const struct llc* llc, int dir, int llclen) {
510 int hdrlen = sizeof(struct llc);
511 int pldlen = llclen - hdrlen;
512 struct ip* ip = (struct ip*)((void*)llc + hdrlen);
514 /* Taken from tcpdump/print-llc.c */
515 if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP
516 && llc->llcui == LLC_UI) {
519 orgcode = EXTRACT_24BITS(&llc->llc_orgcode[0]);
520 et = (llc->llc_ethertype[0] << 8) + llc->llc_ethertype[1];
522 case OUI_ENCAP_ETHER:
524 handle_ip_packet(ip, dir, pldlen);
527 if(et == ETHERTYPE_ATALK) {
528 handle_ip_packet(ip, dir, pldlen);
532 /* Not a lot we can do */
537 static void handle_tokenring_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
539 struct token_header *trp;
542 trp = (struct token_header *)packet;
544 if(IS_SOURCE_ROUTED(trp)) {
545 hdrlen += RIF_LENGTH(trp);
547 hdrlen += TOKEN_HDRLEN;
550 if(memcmp(trp->token_shost, if_hw_addr, 6) == 0 ) {
551 /* packet leaving this i/f */
554 else if(memcmp(trp->token_dhost, if_hw_addr, 6) == 0 || memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", trp->token_dhost, 6) == 0) {
555 /* packet entering this i/f */
559 /* Only know how to deal with LLC encapsulated packets */
560 if(FRAME_TYPE(trp) == TOKEN_FC_LLC) {
561 handle_llc_packet((struct llc*)packet, dir, pkthdr->len - hdrlen);
565 static void handle_ppp_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
567 register u_int length = pkthdr->len;
568 register u_int caplen = pkthdr->caplen;
574 if(packet[0] == PPP_ADDRESS) {
581 proto = EXTRACT_16BITS(packet);
585 if(proto == PPP_IP || proto == ETHERTYPE_IP
586 || proto == ETHERTYPE_IPV6) {
587 handle_ip_packet((struct ip*)packet, -1, length);
593 static void handle_cooked_packet(unsigned char *args, const struct pcap_pkthdr * thdr, const unsigned char * packet)
595 struct sll_header *sptr;
597 sptr = (struct sll_header *) packet;
599 switch (ntohs(sptr->sll_pkttype))
602 /*entering this interface*/
605 case LINUX_SLL_OUTGOING:
606 /*leaving this interface */
610 handle_ip_packet((struct ip*)(packet+SLL_HDR_LEN), dir,
611 thdr->len - SLL_HDR_LEN);
613 #endif /* DLT_LINUX_SLL */
615 static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
617 struct ether_header *eptr;
618 int ether_type, hdrlen;
620 eptr = (struct ether_header*)packet;
621 ether_type = ntohs(eptr->ether_type);
622 hdrlen = sizeof(struct ether_header);
624 if(ether_type == ETHERTYPE_8021Q) {
625 struct vlan_8021q_header* vptr;
626 vptr = (struct vlan_8021q_header*) (packet + hdrlen);
627 ether_type = ntohs(vptr->ether_type);
628 hdrlen += sizeof(struct vlan_8021q_header);
631 if(ether_type == ETHERTYPE_IP || ether_type == ETHERTYPE_IPV6) {
636 * Is a direction implied by the MAC addresses?
638 if(have_hw_addr && memcmp(eptr->ether_shost, if_hw_addr, 6) == 0 ) {
639 /* packet leaving this i/f */
642 else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) {
643 /* packet entering this i/f */
646 else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) {
647 /* broadcast packet, count as incoming */
651 /* Distinguishing ip_hdr and ip6_hdr will be done later. */
652 iptr = (struct ip*) (packet + hdrlen); /* alignment? */
653 handle_ip_packet(iptr, dir, pkthdr->len - hdrlen);
657 #ifdef DLT_IEEE802_11_RADIO
659 * Packets with a bonus radiotap header.
660 * See http://www.gsp.com/cgi-bin/man.cgi?section=9&topic=ieee80211_radiotap
662 static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
664 /* 802.11 MAC header is = 34 bytes (not sure if that's universally true) */
665 /* We could try harder to figure out hardware direction from the MAC header */
666 int hdrlen = ((struct radiotap_header *)packet)->it_len + 34;
667 handle_ip_packet((struct ip*)(packet + hdrlen), -1, pkthdr->len - hdrlen);
674 * Install some filter code. Returns NULL on success or an error message on
676 char *set_filter_code(const char *filter) {
679 x = xmalloc(strlen(filter) + sizeof "() and (ip or ip6)");
680 sprintf(x, "(%s) and (ip or ip6)", filter);
682 x = xstrdup("ip or ip6");
683 if (pcap_compile(pd, &pcap_filter, x, 1, 0) == -1) {
685 return pcap_geterr(pd);
688 if (pcap_setfilter(pd, &pcap_filter) == -1)
689 return pcap_geterr(pd);
699 * performs pcap initialisation, called before ui is initialised
702 char errbuf[PCAP_ERRBUF_SIZE];
709 result = get_addrs_dlpi(options.interface, if_hw_addr, &if_ip_addr);
711 result = get_addrs_ioctl(options.interface, if_hw_addr,
712 &if_ip_addr, &if_ip6_addr);
719 have_hw_addr = result & 0x01;
720 have_ip_addr = result & 0x02;
721 have_ip6_addr = result & 0x04;
724 fprintf(stderr, "IP address is: %s\n", inet_ntoa(if_ip_addr));
727 char ip6str[INET6_ADDRSTRLEN];
730 inet_ntop(AF_INET6, &if_ip6_addr, ip6str, sizeof(ip6str));
731 fprintf(stderr, "IPv6 address is: %s\n", ip6str);
735 fprintf(stderr, "MAC address is:");
736 for (i = 0; i < 6; ++i)
737 fprintf(stderr, "%c%02x", i ? ':' : ' ', (unsigned int)if_hw_addr[i]);
738 fprintf(stderr, "\n");
742 resolver_initialise();
744 pd = pcap_open_live(options.interface, CAPTURE_LENGTH, options.promiscuous, 1000, errbuf);
745 // DEBUG: pd = pcap_open_offline("tcpdump.out", errbuf);
747 fprintf(stderr, "pcap_open_live(%s): %s\n", options.interface, errbuf);
750 dlt = pcap_datalink(pd);
751 if(dlt == DLT_EN10MB) {
752 packet_handler = handle_eth_packet;
755 else if (dlt == DLT_PFLOG) {
756 packet_handler = handle_pflog_packet;
759 else if(dlt == DLT_RAW) {
760 packet_handler = handle_raw_packet;
762 else if(dlt == DLT_NULL) {
763 packet_handler = handle_null_packet;
766 else if(dlt == DLT_LOOP) {
767 packet_handler = handle_null_packet;
770 #ifdef DLT_IEEE802_11_RADIO
771 else if(dlt == DLT_IEEE802_11_RADIO) {
772 packet_handler = handle_radiotap_packet;
775 else if(dlt == DLT_IEEE802) {
776 packet_handler = handle_tokenring_packet;
778 else if(dlt == DLT_PPP) {
779 packet_handler = handle_ppp_packet;
782 * SLL support not available in older libpcaps
785 else if(dlt == DLT_LINUX_SLL) {
786 packet_handler = handle_cooked_packet;
790 fprintf(stderr, "Unsupported datalink type: %d\n"
791 "Please email pdw@ex-parrot.com, quoting the datalink type and what you were\n"
792 "trying to do at the time\n.", dlt);
796 if ((m = set_filter_code(options.filtercode))) {
797 fprintf(stderr, "set_filter_code: %s\n", m);
804 * Worker function for packet capture thread. */
805 void packet_loop(void* ptr) {
806 pcap_loop(pd,-1,(pcap_handler)packet_handler,NULL);
811 * Entry point. See usage(). */
812 int main(int argc, char **argv) {
814 struct sigaction sa = {};
816 setlocale(LC_ALL, "");
818 /* TODO: tidy this up */
819 /* read command line options and config file */
821 options_set_defaults();
822 options_read_args(argc, argv);
823 /* If a config was explicitly specified, whinge if it can't be found */
824 read_config(options.config_file, options.config_file_specified);
827 sa.sa_handler = finish;
828 sigaction(SIGINT, &sa, NULL);
830 pthread_mutex_init(&tick_mutex, NULL);
836 if (options.no_curses) {
843 pthread_create(&thread, NULL, (void*)&packet_loop, NULL);
845 /* Keep the starting time (used for timed termination) */
846 first_timestamp = time(NULL);
848 if (options.no_curses) {
849 if (options.timed_output) {
862 pthread_cancel(thread);