]> gitweb.fperrin.net Git - iftop.git/blob - iftop.c
Drop packets shorter than sizeof (struct iphdr)
[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     history_pos = (history_pos + 1) % HISTORY_LENGTH;
113     hash_next_item(history, &n);
114     while(n != NULL) {
115         hash_node_type* next = n;
116         history_type* d = (history_type*)n->rec;
117         hash_next_item(history, &next);
118
119         if(d->last_write == history_pos) {
120             addr_pair key = *(addr_pair*)(n->key);
121             hash_delete(history, &key);
122             free(d);
123         }
124         else {
125             d->recv[history_pos] = 0;
126             d->sent[history_pos] = 0;
127         }
128         n = next; 
129     }
130
131     history_totals.sent[history_pos] = 0;
132     history_totals.recv[history_pos] = 0;
133
134     if(history_len < HISTORY_LENGTH) {
135         history_len++;
136     }
137 }
138
139
140 void tick(int print) {
141     time_t t;
142
143     pthread_mutex_lock(&tick_mutex);
144    
145     t = time(NULL);
146     if(t - last_timestamp >= RESOLUTION) {
147         analyse_data();
148         if (options.no_curses) {
149           if (!options.timed_output || (options.timed_output && t - first_timestamp >= options.timed_output)) {
150             tui_print();
151             if (options.timed_output) {
152               finish(SIGINT);
153             }
154           }
155         }
156         else {
157           ui_print();
158         }
159         history_rotate();
160         last_timestamp = t;
161     }
162     else {
163       if (options.no_curses) {
164         tui_tick(print);
165       }
166       else {
167         ui_tick(print);
168       }
169     }
170
171     pthread_mutex_unlock(&tick_mutex);
172 }
173
174 int in_filter_net(struct in_addr addr) {
175     int ret;
176     ret = ((addr.s_addr & options.netfiltermask.s_addr) == options.netfilternet.s_addr);
177     return ret;
178 }
179
180 static int __inline__ ip_addr_match(struct in_addr addr) {
181     return addr.s_addr == if_ip_addr.s_addr;
182 }
183
184 static int __inline__ ip6_addr_match(struct in6_addr *addr) {
185     return IN6_ARE_ADDR_EQUAL(addr, &if_ip6_addr);
186 }
187
188 /**
189  * Creates an addr_pair from an ip (and tcp/udp) header, swapping src and dst
190  * if required
191  */
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;
195
196   /* Arrange for predictable values. */
197   memset(ap, '\0', sizeof(*ap));
198
199   if(IP_V(iptr) == 4) {
200     ap->af = AF_INET;
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 */
204
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);
209   }
210
211   if(flip == 0) {
212     ap->src = iptr->ip_src;
213     ap->src_port = src_port;
214     ap->dst = iptr->ip_dst;
215     ap->dst_port = dst_port;
216   }
217   else {
218     ap->src = iptr->ip_dst;
219     ap->src_port = dst_port;
220     ap->dst = iptr->ip_src;
221     ap->dst_port = src_port;
222   }
223   } /* IPv4 */
224   else if (IP_V(iptr) == 6) {
225     /* IPv6 packet seen. */
226     struct ip6_hdr *ip6tr = (struct ip6_hdr *) iptr;
227
228     ap->af = AF_INET6;
229
230     if( (ip6tr->ip6_nxt == IPPROTO_TCP) || (ip6tr->ip6_nxt == IPPROTO_UDP) ) {
231       struct tcphdr *thdr = ((void *) ip6tr) + 40;
232
233       src_port = ntohs(thdr->th_sport);
234       dst_port = ntohs(thdr->th_dport);
235     }
236
237     if(flip == 0) {
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;
242     }
243     else {
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;
248     }
249   }
250 }
251
252 static void handle_ip_packet(struct ip* iptr, int hw_dir, int pld_len)
253 {
254     int direction = 0; /* incoming */
255     int len;
256     history_type* ht;
257     union {
258       history_type **ht_pp;
259       void **void_pp;
260     } u_ht = { &ht };
261     addr_pair ap;
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;
266
267     memset(&ap, '\0', sizeof(ap));
268
269     tick(0);
270
271     /*
272      * Sanity check: drop obviously short packets.
273      * pld_len comes from pcaphdr->len - sizeof(struct l2_header).
274      *
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).
279      */
280     if (pld_len < sizeof (struct ip))
281         return;
282     if (IP_V(iptr) == 6 && pld_len < sizeof (struct ip6_hdr))
283         return;
284
285     if( (IP_V(iptr) == 4 && options.netfilter == 0)
286             || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { 
287         /*
288          * Net filter is off, so assign direction based on MAC address
289          */
290         if(hw_dir == 1) {
291             /* Packet leaving this interface. */
292             assign_addr_pair(&ap, iptr, 0);
293             direction = 1;
294         }
295         else if(hw_dir == 0) {
296             /* Packet incoming */
297             assign_addr_pair(&ap, iptr, 1);
298             direction = 0;
299         }
300         /* Packet direction is not given away by h/ware layer.  Try IP
301          * layer
302          */
303         else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_src)) {
304             /* outgoing */
305             assign_addr_pair(&ap, iptr, 0);
306             direction = 1;
307         }
308         else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_dst)) {
309             /* incoming */
310             assign_addr_pair(&ap, iptr, 1);
311             direction = 0;
312         }
313         else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_src)) {
314             /* outgoing */
315             assign_addr_pair(&ap, iptr, 0);
316             direction = 1;
317         }
318         else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
319             /* incoming */
320             assign_addr_pair(&ap, iptr, 1);
321             direction = 0;
322         }
323         else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) {
324             assign_addr_pair(&ap, iptr, 1);
325             direction = 0;
326         }
327         else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) {
328             assign_addr_pair(&ap, iptr, 1);
329             direction = 0;
330         }
331         /*
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 
335          * incoming.
336          */
337         else if (options.promiscuous_but_choosy) {
338             return;             /* junk it */
339         }
340         else if((IP_V(iptr) == 4) && (iptr->ip_src.s_addr < iptr->ip_dst.s_addr)) {
341             assign_addr_pair(&ap, iptr, 1);
342             direction = 0;
343         }
344         else if(IP_V(iptr) == 4) {
345             assign_addr_pair(&ap, iptr, 0);
346             direction = 0;
347         }
348         /* Drop other uncertain packages. */
349         else
350             return;
351     }
352
353     if(IP_V(iptr) == 4 && options.netfilter != 0) {
354         /* 
355          * Net filter on, assign direction according to netmask 
356          */ 
357         if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
358             /* out of network */
359             assign_addr_pair(&ap, iptr, 0);
360             direction = 1;
361         }
362         else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
363             /* into network */
364             assign_addr_pair(&ap, iptr, 1);
365             direction = 0;
366         }
367         else {
368             /* drop packet */
369             return ;
370         }
371     }
372
373     if(IP_V(iptr) == 6 && options.netfilter6 != 0) {
374         /*
375          * Net filter IPv6 active.
376          */
377         int j;
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.
381          */
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];
387         }
388
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)) {
393             /* out of network */
394             assign_addr_pair(&ap, iptr, 0);
395             direction = 1;
396         }
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)) {
400             /* into network */
401             assign_addr_pair(&ap, iptr, 1);
402             direction = 0;
403         }
404         else {
405             /* drop packet */
406             return ;
407         }
408     }
409
410 #if 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)) )
415         return;
416 #endif
417
418     /* Do address resolving. */
419     switch (IP_V(iptr)) {
420       case 4:
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);
431           break;
432       case 6:
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);
437       default:
438           break;
439     }
440
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);
444     }
445
446     /* Do accounting. */
447     switch (options.bandwidth_unit) {
448       case OPTION_BW_BITS:
449       case OPTION_BW_BYTES:
450           len = pld_len;
451           break;
452       case OPTION_BW_PKTS:
453           len = 1;
454           break;
455       default:
456           return;
457     }
458
459     /* Update record */
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))) )
463     {
464         ht->sent[history_pos] += len;
465         ht->total_sent += len;
466     }
467     else {
468         ht->recv[history_pos] += len;
469         ht->total_recv += len;
470     }
471
472     if(direction == 0) {
473         /* incoming */
474         history_totals.recv[history_pos] += len;
475         history_totals.total_recv += len;
476     }
477     else {
478         history_totals.sent[history_pos] += len;
479         history_totals.total_sent += len;
480     }
481     
482 }
483
484 static void handle_raw_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
485 {
486     handle_ip_packet((struct ip*)packet, -1, pkthdr->len);
487 }
488
489 #ifdef DLT_PFLOG
490 static void handle_pflog_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
491 {
492         register u_int length = pkthdr->len;
493         u_int hdrlen;
494         const struct pfloghdr *hdr;
495         
496         hdr = (struct pfloghdr *)packet;
497         hdrlen = BPF_WORDALIGN(hdr->length);
498         length -= hdrlen;
499         packet += hdrlen;
500         handle_ip_packet((struct ip*)packet, -1, length);
501 }
502 #endif
503
504 static void handle_null_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
505 {
506     handle_ip_packet((struct ip*)(packet + 4), -1, pkthdr->len);
507 }
508
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);
513
514     /* Taken from tcpdump/print-llc.c */
515     if(llc->ssap == LLCSAP_SNAP && llc->dsap == LLCSAP_SNAP
516        && llc->llcui == LLC_UI) {
517         u_int32_t orgcode;
518         u_int16_t et;
519         orgcode = EXTRACT_24BITS(&llc->llc_orgcode[0]);
520         et = (llc->llc_ethertype[0] << 8) + llc->llc_ethertype[1];
521         switch(orgcode) {
522           case OUI_ENCAP_ETHER:
523           case OUI_CISCO_90:
524               handle_ip_packet(ip, dir, pldlen);
525             break;
526           case OUI_APPLETALK:
527             if(et == ETHERTYPE_ATALK) {
528                 handle_ip_packet(ip, dir, pldlen);
529             }
530             break;
531           default:;
532             /* Not a lot we can do */
533         }
534     }
535 }
536
537 static void handle_tokenring_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
538 {
539     struct token_header *trp;
540     int hdrlen = 0;
541     int dir = -1;
542     trp = (struct token_header *)packet;
543
544     if(IS_SOURCE_ROUTED(trp)) {
545       hdrlen += RIF_LENGTH(trp);
546     }
547     hdrlen += TOKEN_HDRLEN;
548     packet += hdrlen;
549
550     if(memcmp(trp->token_shost, if_hw_addr, 6) == 0 ) {
551       /* packet leaving this i/f */
552       dir = 1;
553     }
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 */
556       dir = 0;
557     }
558
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);
562     }
563 }
564
565 static void handle_ppp_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
566 {
567     register u_int length = pkthdr->len;
568     register u_int caplen = pkthdr->caplen;
569     u_int proto;
570
571     if (caplen < 2)
572         return;
573
574     if(packet[0] == PPP_ADDRESS) {
575         if (caplen < 4)
576             return;
577
578         packet += 2;
579         length -= 2;
580
581         proto = EXTRACT_16BITS(packet);
582         packet += 2;
583         length -= 2;
584
585         if(proto == PPP_IP || proto == ETHERTYPE_IP
586            || proto == ETHERTYPE_IPV6) {
587             handle_ip_packet((struct ip*)packet, -1, length);
588         }
589     }
590 }
591
592 #ifdef DLT_LINUX_SLL
593 static void handle_cooked_packet(unsigned char *args, const struct pcap_pkthdr * thdr, const unsigned char * packet)
594 {
595     struct sll_header *sptr;
596     int dir = -1;
597     sptr = (struct sll_header *) packet;
598
599     switch (ntohs(sptr->sll_pkttype))
600     {
601     case LINUX_SLL_HOST:
602         /*entering this interface*/
603         dir = 0;
604         break;
605     case LINUX_SLL_OUTGOING:
606         /*leaving this interface */
607         dir=1;
608         break;
609     }
610     handle_ip_packet((struct ip*)(packet+SLL_HDR_LEN), dir,
611                      thdr->len - SLL_HDR_LEN);
612 }
613 #endif /* DLT_LINUX_SLL */
614
615 static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
616 {
617     struct ether_header *eptr;
618     int ether_type, hdrlen;
619
620     eptr = (struct ether_header*)packet;
621     ether_type = ntohs(eptr->ether_type);
622     hdrlen = sizeof(struct ether_header);
623
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);
629     }
630
631     if(ether_type == ETHERTYPE_IP || ether_type == ETHERTYPE_IPV6) {
632         struct ip* iptr;
633         int dir = -1;
634         
635         /*
636          * Is a direction implied by the MAC addresses?
637          */
638         if(have_hw_addr && memcmp(eptr->ether_shost, if_hw_addr, 6) == 0 ) {
639             /* packet leaving this i/f */
640             dir = 1;
641         }
642         else if(have_hw_addr && memcmp(eptr->ether_dhost, if_hw_addr, 6) == 0 ) {
643             /* packet entering this i/f */
644             dir = 0;
645         }
646         else if (memcmp("\xFF\xFF\xFF\xFF\xFF\xFF", eptr->ether_dhost, 6) == 0) {
647             /* broadcast packet, count as incoming */
648             dir = 0;
649         }
650
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);
654     }
655 }
656
657 #ifdef DLT_IEEE802_11_RADIO
658 /*
659  * Packets with a bonus radiotap header.
660  * See http://www.gsp.com/cgi-bin/man.cgi?section=9&topic=ieee80211_radiotap
661  */
662 static void handle_radiotap_packet(unsigned char* args, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
663 {
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);
668 }
669
670
671 #endif
672
673 /* set_filter_code:
674  * Install some filter code. Returns NULL on success or an error message on
675  * failure. */
676 char *set_filter_code(const char *filter) {
677     char *x;
678     if (filter) {
679         x = xmalloc(strlen(filter) + sizeof "() and (ip or ip6)");
680         sprintf(x, "(%s) and (ip or ip6)", filter);
681     } else
682         x = xstrdup("ip or ip6");
683     if (pcap_compile(pd, &pcap_filter, x, 1, 0) == -1) {
684         xfree(x);
685         return pcap_geterr(pd);
686     }
687     xfree(x);
688     if (pcap_setfilter(pd, &pcap_filter) == -1)
689         return pcap_geterr(pd);
690     else
691         return NULL;
692 }
693
694
695
696 /*
697  * packet_init:
698  *
699  * performs pcap initialisation, called before ui is initialised
700  */
701 void packet_init() {
702     char errbuf[PCAP_ERRBUF_SIZE];
703     char *m;
704     int i;
705     int dlt;
706     int result;
707
708 #ifdef HAVE_DLPI
709     result = get_addrs_dlpi(options.interface, if_hw_addr, &if_ip_addr);
710 #else
711     result = get_addrs_ioctl(options.interface, if_hw_addr,
712           &if_ip_addr, &if_ip6_addr);
713 #endif
714
715     if (result < 0) {
716       exit(1);
717     }
718
719     have_hw_addr = result & 0x01;
720     have_ip_addr = result & 0x02;
721     have_ip6_addr = result & 0x04;
722     
723     if(have_ip_addr) {
724       fprintf(stderr, "IP address is: %s\n", inet_ntoa(if_ip_addr));
725     }
726     if(have_ip6_addr) {
727        char ip6str[INET6_ADDRSTRLEN];
728
729        ip6str[0] = '\0';
730        inet_ntop(AF_INET6, &if_ip6_addr, ip6str, sizeof(ip6str));
731        fprintf(stderr, "IPv6 address is: %s\n", ip6str);
732     }
733
734     if(have_hw_addr) {
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");
739     }
740     
741     //    exit(0);
742     resolver_initialise();
743
744     pd = pcap_open_live(options.interface, CAPTURE_LENGTH, options.promiscuous, 1000, errbuf);
745     // DEBUG: pd = pcap_open_offline("tcpdump.out", errbuf);
746     if(pd == NULL) { 
747         fprintf(stderr, "pcap_open_live(%s): %s\n", options.interface, errbuf); 
748         exit(1);
749     }
750     dlt = pcap_datalink(pd);
751     if(dlt == DLT_EN10MB) {
752         packet_handler = handle_eth_packet;
753     }
754 #ifdef DLT_PFLOG
755     else if (dlt == DLT_PFLOG) {
756                 packet_handler = handle_pflog_packet;
757     }
758 #endif
759     else if(dlt == DLT_RAW) {
760         packet_handler = handle_raw_packet;
761     } 
762     else if(dlt == DLT_NULL) {
763         packet_handler = handle_null_packet;
764     } 
765 #ifdef DLT_LOOP
766     else if(dlt == DLT_LOOP) {
767         packet_handler = handle_null_packet;
768     }
769 #endif
770 #ifdef DLT_IEEE802_11_RADIO
771     else if(dlt == DLT_IEEE802_11_RADIO) {
772         packet_handler = handle_radiotap_packet;
773     }
774 #endif
775     else if(dlt == DLT_IEEE802) {
776         packet_handler = handle_tokenring_packet;
777     }
778     else if(dlt == DLT_PPP) {
779         packet_handler = handle_ppp_packet;
780     }
781 /* 
782  * SLL support not available in older libpcaps
783  */
784 #ifdef DLT_LINUX_SLL
785     else if(dlt == DLT_LINUX_SLL) {
786       packet_handler = handle_cooked_packet;
787     }
788 #endif
789     else {
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);
793         exit(1);
794     }
795
796     if ((m = set_filter_code(options.filtercode))) {
797         fprintf(stderr, "set_filter_code: %s\n", m);
798         exit(1);
799         return;
800     }
801 }
802
803 /* packet_loop:
804  * Worker function for packet capture thread. */
805 void packet_loop(void* ptr) {
806     pcap_loop(pd,-1,(pcap_handler)packet_handler,NULL);
807 }
808
809
810 /* main:
811  * Entry point. See usage(). */
812 int main(int argc, char **argv) {
813     pthread_t thread;
814     struct sigaction sa = {};
815
816     setlocale(LC_ALL, "");
817
818     /* TODO: tidy this up */
819     /* read command line options and config file */   
820     config_init();
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);
825     options_make();
826     
827     sa.sa_handler = finish;
828     sigaction(SIGINT, &sa, NULL);
829
830     pthread_mutex_init(&tick_mutex, NULL);
831
832     packet_init();
833
834     init_history();
835
836     if (options.no_curses) {
837       tui_init();
838     }
839     else {
840       ui_init();
841     }
842
843     pthread_create(&thread, NULL, (void*)&packet_loop, NULL);
844
845     /* Keep the starting time (used for timed termination) */
846     first_timestamp = time(NULL);
847
848     if (options.no_curses) {
849       if (options.timed_output) {
850         while(!foad) {
851           sleep(1);
852         }
853       }
854       else {
855         tui_loop();
856       }
857     }
858     else {
859       ui_loop();
860     }
861
862     pthread_cancel(thread);
863
864     ui_finish();
865     
866     return 0;
867 }