]> gitweb.fperrin.net Git - iftop.git/blob - iftop.c
gitignore
[iftop.git] / iftop.c
1 /*
2  * iftop.c:
3  *
4  */
5
6 #include "integers.h"
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <time.h>
11 #include <sys/types.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <net/if.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)
18 #   include <pcap.h>
19 #elif defined(HAVE_PCAP_PCAP_H)
20 #   include <pcap/pcap.h>
21 #else
22 #   error No pcap.h
23 #endif
24
25 #include <pthread.h>
26 #include <curses.h>
27 #include <signal.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <locale.h>
31
32 #include "iftop.h"
33 #include "addr_hash.h"
34 #include "resolver.h"
35 #include "ui_common.h"
36 #include "ui.h"
37 #include "tui.h"
38 #include "options.h"
39 #ifdef DLT_LINUX_SLL
40 #include "sll.h"
41 #endif /* DLT_LINUX_SLL */
42 #include "threadprof.h"
43 #include "ether.h"
44 #include "ip.h"
45 #include "tcp.h"
46 #include "token.h"
47 #include "llc.h"
48 #include "extract.h"
49 #include "ethertype.h"
50 #include "cfgfile.h"
51 #include "ppp.h"
52 #include "addrs_ioctl.h"
53
54 #include <netinet/ip6.h>
55
56 /* ethernet address of interface. */
57 int have_hw_addr = 0;
58 char if_hw_addr[6];    
59
60 /* IP address of interface */
61 int have_ip_addr = 0;
62 int have_ip6_addr = 0;
63 struct in_addr if_ip_addr;
64 struct in6_addr if_ip6_addr;
65
66 extern options_t options;
67
68 hash_type* history;
69 history_type history_totals;
70 time_t last_timestamp;
71 time_t first_timestamp;
72 int history_pos = 0;
73 int history_len = 1;
74 pthread_mutex_t tick_mutex;
75
76 pcap_t* pd; /* pcap descriptor */
77 struct bpf_program pcap_filter;
78 pcap_handler packet_handler;
79
80 sig_atomic_t foad;
81
82 static void finish(int sig) {
83     foad = sig;
84 }
85
86
87
88
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
97
98 void init_history() {
99     history = addr_hash_create();
100     last_timestamp = time(NULL);
101     memset(&history_totals, 0, sizeof history_totals);
102 }
103
104 history_type* history_create() {
105     history_type* h;
106     h = xcalloc(1, sizeof *h);
107     return h;
108 }
109
110 void history_rotate() {
111     hash_node_type* n = NULL;
112     struct pcap_stat ps;
113
114     history_pos = (history_pos + 1) % HISTORY_LENGTH;
115     hash_next_item(history, &n);
116     while(n != NULL) {
117         hash_node_type* next = n;
118         history_type* d = (history_type*)n->rec;
119         hash_next_item(history, &next);
120
121         if(d->last_write == history_pos) {
122             addr_pair key = *(addr_pair*)(n->key);
123             hash_delete(history, &key);
124             free(d);
125         }
126         else {
127             d->recv[history_pos] = 0;
128             d->sent[history_pos] = 0;
129         }
130         n = next; 
131     }
132
133     history_totals.sent[history_pos] = 0;
134     history_totals.recv[history_pos] = 0;
135
136     if(history_len < HISTORY_LENGTH) {
137         history_len++;
138     }
139
140     pcap_stats(pd, &ps);
141     history_totals.lost_packets = ps.ps_drop + ps.ps_ifdrop;
142 }
143
144
145 void tick(int print) {
146     time_t t;
147
148     pthread_mutex_lock(&tick_mutex);
149    
150     t = time(NULL);
151     if(t - last_timestamp >= RESOLUTION) {
152         analyse_data();
153         if (options.no_curses) {
154           if (!options.timed_output || (options.timed_output && t - first_timestamp >= options.timed_output)) {
155             tui_print();
156             if (options.timed_output) {
157               finish(SIGINT);
158             }
159           }
160         }
161         else {
162           ui_print();
163         }
164         history_rotate();
165         last_timestamp = t;
166     }
167     else {
168       if (options.no_curses) {
169         tui_tick(print);
170       }
171       else {
172         ui_tick(print);
173       }
174     }
175
176     pthread_mutex_unlock(&tick_mutex);
177 }
178
179 int in_filter_net(struct in_addr addr) {
180     int ret;
181     ret = ((addr.s_addr & options.netfiltermask.s_addr) == options.netfilternet.s_addr);
182     return ret;
183 }
184
185 static int __inline__ ip_addr_match(struct in_addr addr) {
186     return addr.s_addr == if_ip_addr.s_addr;
187 }
188
189 static int __inline__ ip6_addr_match(struct in6_addr *addr) {
190     return IN6_ARE_ADDR_EQUAL(addr, &if_ip6_addr);
191 }
192
193 /**
194  * Creates an addr_pair from an ip (and tcp/udp) header, swapping src and dst
195  * if required
196  */
197 void assign_addr_pair(addr_pair* ap, struct ip* iptr, int flip) {
198   unsigned short int src_port = 0;
199   unsigned short int dst_port = 0;
200
201   /* Arrange for predictable values. */
202   memset(ap, '\0', sizeof(*ap));
203
204   if(IP_V(iptr) == 4) {
205     ap->af = AF_INET;
206   /* Does this protocol use ports? */
207   if(iptr->ip_p == IPPROTO_TCP || iptr->ip_p == IPPROTO_UDP) {
208     /* We take a slight liberty here by treating UDP the same as TCP */
209
210     /* Find the TCP/UDP header */
211     struct tcphdr* thdr = ((void*)iptr) + IP_HL(iptr) * 4;
212     src_port = ntohs(thdr->th_sport);
213     dst_port = ntohs(thdr->th_dport);
214   }
215
216   if(flip == 0) {
217     ap->src = iptr->ip_src;
218     ap->src_port = src_port;
219     ap->dst = iptr->ip_dst;
220     ap->dst_port = dst_port;
221   }
222   else {
223     ap->src = iptr->ip_dst;
224     ap->src_port = dst_port;
225     ap->dst = iptr->ip_src;
226     ap->dst_port = src_port;
227   }
228   } /* IPv4 */
229   else if (IP_V(iptr) == 6) {
230     /* IPv6 packet seen. */
231     struct ip6_hdr *ip6tr = (struct ip6_hdr *) iptr;
232
233     ap->af = AF_INET6;
234
235     if( (ip6tr->ip6_nxt == IPPROTO_TCP) || (ip6tr->ip6_nxt == IPPROTO_UDP) ) {
236       struct tcphdr *thdr = ((void *) ip6tr) + 40;
237
238       src_port = ntohs(thdr->th_sport);
239       dst_port = ntohs(thdr->th_dport);
240     }
241
242     if(flip == 0) {
243       memcpy(&ap->src6, &ip6tr->ip6_src, sizeof(ap->src6));
244       ap->src_port = src_port;
245       memcpy(&ap->dst6, &ip6tr->ip6_dst, sizeof(ap->dst6));
246       ap->dst_port = dst_port;
247     }
248     else {
249       memcpy(&ap->src6, &ip6tr->ip6_dst, sizeof(ap->src6));
250       ap->src_port = dst_port;
251       memcpy(&ap->dst6, &ip6tr->ip6_src, sizeof(ap->dst6));
252       ap->dst_port = src_port;
253     }
254   }
255 }
256
257 static void handle_ip_packet(struct ip* iptr, int hw_dir, int pld_len)
258 {
259     int direction = 0; /* incoming */
260     int len;
261     history_type* ht;
262     union {
263       history_type **ht_pp;
264       void **void_pp;
265     } u_ht = { &ht };
266     addr_pair ap;
267     struct in6_addr scribdst;   /* Scratch pad. */
268     struct in6_addr scribsrc;   /* Scratch pad. */
269     /* Reinterpret packet type. */
270     struct ip6_hdr* ip6tr = (struct ip6_hdr *) iptr;
271
272     memset(&ap, '\0', sizeof(ap));
273
274     tick(0);
275
276     /*
277      * Sanity check: drop obviously short packets.
278      * pld_len comes from pcaphdr->len - sizeof(struct l2_header).
279      *
280      * It is assumed that the snaplen (currently hard-coded to 1000) is
281      * big enough to always capture the IP header past the L2 encap, and
282      * that pcap never truncates the packet to less than snaplen; in
283      * other words, that pcaphdr->caplen = MIN(pcaphdr->len, snaplen).
284      */
285     if (pld_len < sizeof (struct ip))
286         return;
287     if (IP_V(iptr) == 6 && pld_len < sizeof (struct ip6_hdr))
288         return;
289
290     if( (IP_V(iptr) == 4 && options.netfilter == 0)
291             || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { 
292         /*
293          * Net filter is off, so assign direction based on MAC address
294          */
295         if(hw_dir == 1) {
296             /* Packet leaving this interface. */
297             assign_addr_pair(&ap, iptr, 0);
298             direction = 1;
299         }
300         else if(hw_dir == 0) {
301             /* Packet incoming */
302             assign_addr_pair(&ap, iptr, 1);
303             direction = 0;
304         }
305         /* Packet direction is not given away by h/ware layer.  Try IP
306          * layer
307          */
308         else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_src)) {
309             /* outgoing */
310             assign_addr_pair(&ap, iptr, 0);
311             direction = 1;
312         }
313         else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_dst)) {
314             /* incoming */
315             assign_addr_pair(&ap, iptr, 1);
316             direction = 0;
317         }
318         else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_src)) {
319             /* outgoing */
320             assign_addr_pair(&ap, iptr, 0);
321             direction = 1;
322         }
323         else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
324             /* incoming */
325             assign_addr_pair(&ap, iptr, 1);
326             direction = 0;
327         }
328         else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) {
329             assign_addr_pair(&ap, iptr, 1);
330             direction = 0;
331         }
332         else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) {
333             assign_addr_pair(&ap, iptr, 1);
334             direction = 0;
335         }
336         /*
337          * Cannot determine direction from hardware or IP levels.  Therefore 
338          * assume that it was a packet between two other machines, assign
339          * source and dest arbitrarily (by numerical value) and account as 
340          * incoming.
341          */
342         else if (options.promiscuous_but_choosy) {
343             return;             /* junk it */
344         }
345         else if((IP_V(iptr) == 4) && (iptr->ip_src.s_addr < iptr->ip_dst.s_addr)) {
346             assign_addr_pair(&ap, iptr, 1);
347             direction = 0;
348         }
349         else if(IP_V(iptr) == 4) {
350             assign_addr_pair(&ap, iptr, 0);
351             direction = 0;
352         }
353         /* Drop other uncertain packages. */
354         else
355             return;
356     }
357
358     if(IP_V(iptr) == 4 && options.netfilter != 0) {
359         /* 
360          * Net filter on, assign direction according to netmask 
361          */ 
362         if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
363             /* out of network */
364             assign_addr_pair(&ap, iptr, 0);
365             direction = 1;
366         }
367         else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
368             /* into network */
369             assign_addr_pair(&ap, iptr, 1);
370             direction = 0;
371         }
372         else {
373             /* drop packet */
374             return ;
375         }
376     }
377
378     if(IP_V(iptr) == 6 && options.netfilter6 != 0) {
379         /*
380          * Net filter IPv6 active.
381          */
382         int j;
383         //else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
384         /* First reduce the participating addresses using the netfilter prefix.
385          * We need scratch pads to do this.
386          */
387         for (j=0; j < 16; ++j) {
388             scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j]
389                                         & options.netfilter6mask.s6_addr[j];
390             scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j]
391                                         & options.netfilter6mask.s6_addr[j];
392         }
393
394         /* Now look for any hits. */
395         //if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
396         if (IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
397                 && ! IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
398             /* out of network */
399             assign_addr_pair(&ap, iptr, 0);
400             direction = 1;
401         }
402         //else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
403         else if (! IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
404                     && IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
405             /* into network */
406             assign_addr_pair(&ap, iptr, 1);
407             direction = 0;
408         }
409         else {
410             /* drop packet */
411             return ;
412         }
413     }
414
415 #if 1
416     /* Test if link-local IPv6 packets should be dropped. */
417     if( IP_V(iptr) == 6 && !options.link_local
418             && (IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_dst)
419                 || IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_src)) )
420         return;
421 #endif
422
423     /* Do address resolving. */
424     switch (IP_V(iptr)) {
425       case 4:
426           ap.protocol = iptr->ip_p;
427           /* Add the addresses to be resolved */
428           /* The IPv4 address is embedded in a in6_addr structure,
429            * so it need be copied, and delivered to resolve(). */
430           memset(&scribdst, '\0', sizeof(scribdst));
431           memcpy(&scribdst, &iptr->ip_dst, sizeof(struct in_addr));
432           resolve(ap.af, &scribdst, NULL, 0);
433           memset(&scribsrc, '\0', sizeof(scribsrc));
434           memcpy(&scribsrc, &iptr->ip_src, sizeof(struct in_addr));
435           resolve(ap.af, &scribsrc, NULL, 0);
436           break;
437       case 6:
438           ap.protocol = ip6tr->ip6_nxt;
439           /* Add the addresses to be resolved */
440           resolve(ap.af, &ip6tr->ip6_dst, NULL, 0);
441           resolve(ap.af, &ip6tr->ip6_src, NULL, 0);
442       default:
443           break;
444     }
445
446     if(hash_find(history, &ap, u_ht.void_pp) == HASH_STATUS_KEY_NOT_FOUND) {
447         ht = history_create();
448         hash_insert(history, &ap, ht);
449     }
450
451     /* Do accounting. */
452     switch (options.bandwidth_unit) {
453       case OPTION_BW_BITS:
454       case OPTION_BW_BYTES:
455           len = pld_len;
456           break;
457       case OPTION_BW_PKTS:
458           len = 1;
459           break;
460       default:
461           return;
462     }
463
464     /* Update record */
465     ht->last_write = history_pos;
466     if( ((IP_V(iptr) == 4) && (iptr->ip_src.s_addr == ap.src.s_addr))
467        || ((IP_V(iptr) == 6) && !memcmp(&ip6tr->ip6_src, &ap.src6, sizeof(ap.src6))) )
468     {
469         ht->sent[history_pos] += len;
470         ht->total_sent += len;
471     }
472     else {
473         ht->recv[history_pos] += len;
474         ht->total_recv += len;
475     }
476
477     if(direction == 0) {
478         /* incoming */
479         history_totals.recv[history_pos] += len;
480         history_totals.total_recv += len;
481     }
482     else {
483         history_totals.sent[history_pos] += len;
484         history_totals.total_sent += len;
485     }
486     
487 }
488
489 static void handle_raw_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
490 {
491     handle_ip_packet((struct ip*)packet, -1, pkthdr->len);
492 }
493
494 #ifdef DLT_PFLOG
495 static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
496 {
497         register u_int length = pkthdr->len;
498         u_int hdrlen;
499         const struct pfloghdr *hdr;
500         
501         hdr = (struct pfloghdr *)packet;
502         hdrlen = BPF_WORDALIGN(hdr->length);
503         length -= hdrlen;
504         packet += hdrlen;
505         handle_ip_packet((struct ip*)packet, -1, length);
506 }
507 #endif
508
509 static void handle_null_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
510 {
511     handle_ip_packet((struct ip*)(packet + 4), -1, pkthdr->len);
512 }
513
514 static void handle_llc_packet(const struct llc* llc, int dir, int llclen) {
515     int hdrlen = sizeof(struct llc);
516     int pldlen = llclen - hdrlen;
517     struct ip* ip = (struct ip*)((void*)llc + hdrlen);
518
519     /* Taken from tcpdump/print-llc.c */
520     if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP
521        && llc->llcui == LLC_UI) {
522         u_int32_t orgcode;
523         u_int16_t et;
524         orgcode = EXTRACT_24BITS(&llc->llc_orgcode[0]);
525         et = (llc->llc_ethertype[0] << 8) + llc->llc_ethertype[1];
526         switch(orgcode) {
527           case OUI_ENCAP_ETHER:
528           case OUI_CISCO_90:
529               handle_ip_packet(ip, dir, pldlen);
530             break;
531           case OUI_APPLETALK:
532             if(et == ETHERTYPE_ATALK) {
533                 handle_ip_packet(ip, dir, pldlen);
534             }
535             break;
536           default:;
537             /* Not a lot we can do */
538         }
539     }
540 }
541
542 static void handle_tokenring_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
543 {
544     struct token_header *trp;
545     int hdrlen = 0;
546     int dir = -1;
547     trp = (struct token_header *)packet;
548
549     if(IS_SOURCE_ROUTED(trp)) {
550       hdrlen += RIF_LENGTH(trp);
551     }
552     hdrlen += TOKEN_HDRLEN;
553     packet += hdrlen;
554
555     if(memcmp(trp->token_shost, if_hw_addr, 6) == 0 ) {
556       /* packet leaving this i/f */
557       dir = 1;
558     }
559     else if(memcmp(trp->token_dhost, if_hw_addr, 6) == 0 || memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", trp->token_dhost, 6) == 0) {
560       /* packet entering this i/f */
561       dir = 0;
562     }
563
564     /* Only know how to deal with LLC encapsulated packets */
565     if(FRAME_TYPE(trp) == TOKEN_FC_LLC) {
566         handle_llc_packet((struct llc*)packet, dir, pkthdr->len - hdrlen);
567     }
568 }
569
570 static void handle_ppp_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
571 {
572     register u_int length = pkthdr->len;
573     register u_int caplen = pkthdr->caplen;
574     u_int proto;
575
576     if (caplen < 2)
577         return;
578
579     if(packet[0] == PPP_ADDRESS) {
580         if (caplen < 4)
581             return;
582
583         packet += 2;
584         length -= 2;
585
586         proto = EXTRACT_16BITS(packet);
587         packet += 2;
588         length -= 2;
589
590         if(proto == PPP_IP || proto == ETHERTYPE_IP
591            || proto == ETHERTYPE_IPV6) {
592             handle_ip_packet((struct ip*)packet, -1, length);
593         }
594     }
595 }
596
597 #ifdef DLT_LINUX_SLL
598 static void handle_cooked_packet(unsigned char *args, const struct pcap_pkthdr * thdr, const unsigned char * packet)
599 {
600     struct sll_header *sptr;
601     int dir = -1;
602     sptr = (struct sll_header *) packet;
603
604     switch (ntohs(sptr->sll_pkttype))
605     {
606     case LINUX_SLL_HOST:
607         /*entering this interface*/
608         dir = 0;
609         break;
610     case LINUX_SLL_OUTGOING:
611         /*leaving this interface */
612         dir=1;
613         break;
614     }
615     handle_ip_packet((struct ip*)(packet+SLL_HDR_LEN), dir,
616                      thdr->len - SLL_HDR_LEN);
617 }
618 #endif /* DLT_LINUX_SLL */
619
620 static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
621 {
622     struct ether_header *eptr;
623     int ether_type, hdrlen;
624
625     eptr = (struct ether_header*)packet;
626     ether_type = ntohs(eptr->ether_type);
627     hdrlen = sizeof(struct ether_header);
628
629     if(ether_type == ETHERTYPE_8021Q) {
630         struct vlan_8021q_header* vptr;
631         vptr = (struct vlan_8021q_header*) (packet + hdrlen);
632         ether_type = ntohs(vptr->ether_type);
633         hdrlen += sizeof(struct vlan_8021q_header);
634     }
635
636     if(ether_type == ETHERTYPE_IP || ether_type == ETHERTYPE_IPV6) {
637         struct ip* iptr;
638         int dir = -1;
639         
640         /*
641          * Is a direction implied by the MAC addresses?
642          */
643         if(have_hw_addr && memcmp(eptr->ether_shost, if_hw_addr, 6) == 0 ) {
644             /* packet leaving this i/f */
645             dir = 1;
646         }
647         else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) {
648             /* packet entering this i/f */
649             dir = 0;
650         }
651         else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) {
652             /* broadcast packet, count as incoming */
653             dir = 0;
654         }
655
656         /* Distinguishing ip_hdr and ip6_hdr will be done later. */
657         iptr = (struct ip*) (packet + hdrlen); /* alignment? */
658         handle_ip_packet(iptr, dir, pkthdr->len - hdrlen);
659     }
660 }
661
662 #ifdef DLT_IEEE802_11_RADIO
663 /*
664  * Packets with a bonus radiotap header.
665  * See http://www.gsp.com/cgi-bin/man.cgi?section=9&topic=ieee80211_radiotap
666  */
667 static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
668 {
669     /* 802.11 MAC header is = 34 bytes (not sure if that's universally true) */
670     /* We could try harder to figure out hardware direction from the MAC header */
671     int hdrlen = ((struct radiotap_header *)packet)->it_len + 34;
672     handle_ip_packet((struct ip*)(packet + hdrlen), -1, pkthdr->len - hdrlen);
673 }
674
675
676 #endif
677
678 /* set_filter_code:
679  * Install some filter code. Returns NULL on success or an error message on
680  * failure. */
681 char *set_filter_code(const char *filter) {
682     char *x;
683     if (filter) {
684         x = xmalloc(strlen(filter) + sizeof "() and (ip or ip6)");
685         sprintf(x, "(%s) and (ip or ip6)", filter);
686     } else
687         x = xstrdup("ip or ip6");
688     if (pcap_compile(pd, &pcap_filter, x, 1, 0) == -1) {
689         xfree(x);
690         return pcap_geterr(pd);
691     }
692     xfree(x);
693     if (pcap_setfilter(pd, &pcap_filter) == -1)
694         return pcap_geterr(pd);
695     else
696         return NULL;
697 }
698
699
700
701 /*
702  * packet_init:
703  *
704  * performs pcap initialisation, called before ui is initialised
705  */
706 void packet_init() {
707     char errbuf[PCAP_ERRBUF_SIZE];
708     char *m;
709     int dlt;
710     int result;
711
712 #ifdef HAVE_DLPI
713     result = get_addrs_dlpi(options.interface, if_hw_addr, &if_ip_addr);
714 #else
715     result = get_addrs_ioctl(options.interface, if_hw_addr,
716           &if_ip_addr, &if_ip6_addr);
717 #endif
718
719     if (result < 0) {
720       exit(1);
721     }
722
723     have_hw_addr = result & 0x01;
724     have_ip_addr = result & 0x02;
725     have_ip6_addr = result & 0x04;
726     
727     if(have_ip_addr) {
728       fprintf(stderr, "IP address is: %s\n", inet_ntoa(if_ip_addr));
729     }
730     if(have_ip6_addr) {
731        char ip6str[INET6_ADDRSTRLEN];
732
733        ip6str[0] = '\0';
734        inet_ntop(AF_INET6, &if_ip6_addr, ip6str, sizeof(ip6str));
735        fprintf(stderr, "IPv6 address is: %s\n", ip6str);
736     }
737
738     if(have_hw_addr) {
739       fprintf(stderr, "MAC address is: %s\n", ether_ntoa(if_hw_addr));
740     }
741     
742     //    exit(0);
743     resolver_initialise();
744
745     pd = pcap_open_live(options.interface, CAPTURE_LENGTH, options.promiscuous, 1000, errbuf);
746     // DEBUG: pd = pcap_open_offline("tcpdump.out", errbuf);
747     if(pd == NULL) { 
748         fprintf(stderr, "pcap_open_live(%s): %s\n", options.interface, errbuf); 
749         exit(1);
750     }
751     dlt = pcap_datalink(pd);
752     if(dlt == DLT_EN10MB) {
753         packet_handler = handle_eth_packet;
754     }
755 #ifdef DLT_PFLOG
756     else if (dlt == DLT_PFLOG) {
757                 packet_handler = handle_pflog_packet;
758     }
759 #endif
760     else if(dlt == DLT_RAW) {
761         packet_handler = handle_raw_packet;
762     } 
763     else if(dlt == DLT_NULL) {
764         packet_handler = handle_null_packet;
765     } 
766 #ifdef DLT_LOOP
767     else if(dlt == DLT_LOOP) {
768         packet_handler = handle_null_packet;
769     }
770 #endif
771 #ifdef DLT_IEEE802_11_RADIO
772     else if(dlt == DLT_IEEE802_11_RADIO) {
773         packet_handler = handle_radiotap_packet;
774     }
775 #endif
776     else if(dlt == DLT_IEEE802) {
777         packet_handler = handle_tokenring_packet;
778     }
779     else if(dlt == DLT_PPP) {
780         packet_handler = handle_ppp_packet;
781     }
782 /* 
783  * SLL support not available in older libpcaps
784  */
785 #ifdef DLT_LINUX_SLL
786     else if(dlt == DLT_LINUX_SLL) {
787       packet_handler = handle_cooked_packet;
788     }
789 #endif
790     else {
791         fprintf(stderr, "Unsupported datalink type: %d\n"
792                 "Please email pdw@ex-parrot.com, quoting the datalink type and what you were\n"
793                 "trying to do at the time\n.", dlt);
794         exit(1);
795     }
796
797     if ((m = set_filter_code(options.filtercode))) {
798         fprintf(stderr, "set_filter_code: %s\n", m);
799         exit(1);
800         return;
801     }
802 }
803
804 /* packet_loop:
805  * Worker function for packet capture thread. */
806 void packet_loop(void* ptr) {
807     pcap_loop(pd,-1,(pcap_handler)packet_handler,NULL);
808 }
809
810
811 /* main:
812  * Entry point. See usage(). */
813 int main(int argc, char **argv) {
814     pthread_t thread;
815     struct sigaction sa = {};
816
817     setlocale(LC_ALL, "");
818
819     /* TODO: tidy this up */
820     /* read command line options and config file */   
821     config_init();
822     options_set_defaults();
823     options_read_args(argc, argv);
824     /* If a config was explicitly specified, whinge if it can't be found */
825     read_config(options.config_file, options.config_file_specified);
826     options_make();
827     
828     sa.sa_handler = finish;
829     sigaction(SIGINT, &sa, NULL);
830
831     pthread_mutex_init(&tick_mutex, NULL);
832
833     packet_init();
834
835     init_history();
836
837     if (options.no_curses) {
838       tui_init();
839     }
840     else {
841       ui_init();
842     }
843
844     pthread_create(&thread, NULL, (void*)&packet_loop, NULL);
845
846     /* Keep the starting time (used for timed termination) */
847     first_timestamp = time(NULL);
848
849     if (options.no_curses) {
850       if (options.timed_output) {
851         while(!foad) {
852           sleep(1);
853         }
854       }
855       else {
856         tui_loop();
857       }
858     }
859     else {
860       ui_loop();
861     }
862
863     pthread_cancel(thread);
864
865     ui_finish();
866     
867     return 0;
868 }