2 * collectd - src/dnstop.c
3 * Copyright (C) 2006 Florian octo Forster
4 * Copyright (C) 2002 The Measurement Factory, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * 3. Neither the name of The Measurement Factory nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 * The Measurement Factory, Inc. <http://www.measurement-factory.com/>
33 * Florian octo Forster <octo at verplant.org>
36 #include <sys/types.h>
40 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <arpa/nameser.h>
55 #include <arpa/nameser_compat.h>
58 #include <sys/socket.h>
59 #include <net/if_arp.h>
61 #include <netinet/if_ether.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/ip.h>
65 #include <netinet/udp.h>
67 #define PCAP_SNAPLEN 1460
68 #define MAX_QNAME_SZ 512
70 #define ETHER_ADDR_LEN 6
71 #define ETHER_TYPE_LEN 2
72 #define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
74 #ifndef ETHERTYPE_8021Q
75 #define ETHERTYPE_8021Q 0x8100
79 #include <net/if_ppp.h>
80 #define PPP_ADDRESS_VAL 0xff /* The address byte value */
81 #define PPP_CONTROL_VAL 0x03 /* The control byte value */
93 typedef struct _AgentAddr AgentAddr;
100 typedef struct _StringCounter StringCounter;
101 struct _StringCounter {
107 /* This struct cobbles together Source and Sld */
108 typedef struct _StringAddrCounter StringAddrCounter;
109 struct _StringAddrCounter {
113 StringAddrCounter *next;
116 typedef struct _foo foo;
122 typedef struct _rfc1035_header rfc1035_header;
123 struct _rfc1035_header {
126 unsigned int opcode:4;
131 unsigned int rcode:4;
132 unsigned short qdcount;
133 unsigned short ancount;
134 unsigned short nscount;
135 unsigned short arcount;
138 typedef struct _AnonMap AnonMap;
145 typedef int Filter_t(unsigned short,
148 const struct in_addr,
149 const struct in_addr);
151 typedef int (printer)(const char *, ...);
154 * flags/features for non-interactive mode
170 static int interactive = 1;
171 static char *device = NULL;
172 static struct in_addr ignore_addr;
173 static pcap_t *pcap = NULL;
174 static char *bpf_program_str = "udp dst port 53 and udp[10:2] & 0x8000 = 0";
176 static unsigned short port53;
177 static void (*SubReport) (void) = NULL;
178 static int (*handle_datalink) (const u_char * pkt, int len) = NULL;
180 static char *progname = NULL;
181 static int anon_flag = 0;
182 static int sld_flag = 0;
183 static int nld_flag = 0;
184 static int promisc_flag = 1;
185 static AnonMap *Anons = NULL;
187 static int query_count_intvl = 0;
188 static int query_count_total = 0;
189 int qtype_counts[T_MAX];
190 static int opcode_counts[OP_MAX];
191 static int qclass_counts[C_MAX];
192 static AgentAddr *Sources = NULL;
193 static AgentAddr *Destinations = NULL;
194 static StringCounter *Tlds = NULL;
195 static StringCounter *Slds = NULL;
196 static StringCounter *Nlds = NULL;
197 static StringAddrCounter *SSC2 = NULL;
198 static StringAddrCounter *SSC3 = NULL;
200 static struct bpf_timeval last_ts;
202 static struct timeval last_ts;
206 static void SldBySource_report(void);
207 static void NldBySource_report(void);
208 static void Sources_report(void);
209 static void Destinatioreport(void);
210 static void Qtypes_report(void);
211 static void Opcodes_report(void);
212 static void Tld_report(void);
213 static void Sld_report(void);
214 static void Nld_report(void);
215 static void Help_report(void);
216 static void ResetCounters(void);
218 static Filter_t UnknownTldFilter;
219 static Filter_t AforAFilter;
220 static Filter_t RFC1918PtrFilter;
221 static Filter_t *Filter = NULL;
223 static printer *print_func = (printer *) printw;
225 static struct in_addr
226 AnonMap_lookup_or_add(AnonMap ** headP, struct in_addr real)
229 for (T = headP; (*T); T = &(*T)->next)
230 if ((*T)->real.s_addr == real.s_addr)
232 (*T) = calloc(1, sizeof(**T));
234 (*T)->anon.s_addr = random();
239 anon_inet_ntoa(struct in_addr a)
242 a = AnonMap_lookup_or_add(&Anons, a);
247 AgentAddr_lookup_or_add(AgentAddr ** headP, struct in_addr a)
250 for (T = headP; (*T); T = &(*T)->next)
251 if ((*T)->src.s_addr == a.s_addr)
253 (*T) = calloc(1, sizeof(**T));
258 static StringCounter *
259 StringCounter_lookup_or_add(StringCounter ** headP, const char *s)
262 for (T = headP; (*T); T = &(*T)->next)
263 if (0 == strcmp((*T)->s, s))
265 (*T) = calloc(1, sizeof(**T));
270 static StringAddrCounter *
271 StringAddrCounter_lookup_or_add(StringAddrCounter ** headP, struct in_addr a, const char *str)
273 StringAddrCounter **T;
274 for (T = headP; (*T); T = &(*T)->next)
275 if (0 == strcmp((*T)->str, str))
276 if ((*T)->src.s_addr == a.s_addr)
278 (*T) = calloc(1, sizeof(**T));
279 (*T)->str = strdup(str);
285 foo_cmp(const void *A, const void *B)
301 AgentAddr_sort(AgentAddr ** headP)
307 for (a = *headP; a; a = a->next)
309 sortme = calloc(n_agents, sizeof(foo));
311 for (a = *headP; a; a = a->next) {
312 sortme[n_agents].cnt = a->count;
313 sortme[n_agents].ptr = a;
316 qsort(sortme, n_agents, sizeof(foo), foo_cmp);
317 for (i = 0; i < n_agents; i++) {
318 *headP = sortme[i].ptr;
319 headP = &(*headP)->next;
326 StringCounter_sort(StringCounter ** headP)
332 for (sc = *headP; sc; sc = sc->next)
334 sortme = calloc(n_things, sizeof(foo));
336 for (sc = *headP; sc; sc = sc->next) {
337 sortme[n_things].cnt = sc->count;
338 sortme[n_things].ptr = sc;
341 qsort(sortme, n_things, sizeof(foo), foo_cmp);
342 for (i = 0; i < n_things; i++) {
343 *headP = sortme[i].ptr;
344 headP = &(*headP)->next;
351 StringAddrCounter_sort(StringAddrCounter ** headP)
356 StringAddrCounter *ssc;
357 for (ssc = *headP; ssc; ssc = ssc->next)
359 sortme = calloc(n_things, sizeof(foo));
361 for (ssc = *headP; ssc; ssc = ssc->next) {
362 sortme[n_things].cnt = ssc->count;
363 sortme[n_things].ptr = ssc;
366 qsort(sortme, n_things, sizeof(foo), foo_cmp);
367 for (i = 0; i < n_things; i++) {
368 *headP = sortme[i].ptr;
369 headP = &(*headP)->next;
375 #define RFC1035_MAXLABELSZ 63
377 rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
389 /* blasted compression */
392 memcpy(&s, buf + (*off), sizeof(s));
399 /* Make sure the pointer is inside this message */
402 return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
403 } else if (c > RFC1035_MAXLABELSZ) {
405 * "(The 10 and 01 combinations are reserved for future use.)"
416 if ((*off) + len > sz) /* message is too short */
418 memcpy(name + no, buf + (*off), len);
421 *(name + (no++)) = '.';
424 *(name + no - 1) = '\0';
425 /* make sure we didn't allow someone to overflow the name buffer */
431 QnameToNld(const char *qname, int nld)
433 const char *t = strrchr(qname, '.');
437 if (0 == strcmp(t, ".arpa"))
439 while (t > qname && dotcount < nld) {
450 handle_dns(const char *buf, int len, const struct in_addr sip, const struct in_addr dip)
454 char qname[MAX_QNAME_SZ];
455 unsigned short qtype;
456 unsigned short qclass;
462 StringAddrCounter *ssc;
464 if (len < sizeof(qh))
467 memcpy(&us, buf + 00, 2);
470 memcpy(&us, buf + 2, 2);
472 qh.qr = (us >> 15) & 0x01;
473 qh.opcode = (us >> 11) & 0x0F;
474 qh.aa = (us >> 10) & 0x01;
475 qh.tc = (us >> 9) & 0x01;
476 qh.rd = (us >> 8) & 0x01;
477 qh.ra = (us >> 7) & 0x01;
478 qh.rcode = us & 0x0F;
480 memcpy(&us, buf + 4, 2);
481 qh.qdcount = ntohs(us);
483 memcpy(&us, buf + 6, 2);
484 qh.ancount = ntohs(us);
486 memcpy(&us, buf + 8, 2);
487 qh.nscount = ntohs(us);
489 memcpy(&us, buf + 10, 2);
490 qh.arcount = ntohs(us);
493 memset(qname, '\0', MAX_QNAME_SZ);
494 x = rfc1035NameUnpack(buf, len, &offset, qname, MAX_QNAME_SZ);
497 if ('\0' == qname[0])
499 while ((t = strchr(qname, '\n')))
501 while ((t = strchr(qname, '\r')))
503 for (t = qname; *t; t++)
506 memcpy(&us, buf + offset, 2);
508 memcpy(&us, buf + offset + 2, 2);
511 if (Filter && 0 == Filter(qtype, qclass, qname, sip, dip))
515 qtype_counts[qtype]++;
516 qclass_counts[qclass]++;
517 opcode_counts[qh.opcode]++;
519 s = QnameToNld(qname, 1);
520 sc = StringCounter_lookup_or_add(&Tlds, s);
524 s = QnameToNld(qname, 2);
525 sc = StringCounter_lookup_or_add(&Slds, s);
528 /* increment StringAddrCounter */
529 ssc = StringAddrCounter_lookup_or_add(&SSC2, sip, s);
534 s = QnameToNld(qname, 3);
535 sc = StringCounter_lookup_or_add(&Nlds, s);
538 /* increment StringAddrCounter */
539 ssc = StringAddrCounter_lookup_or_add(&SSC3, sip, s);
547 handle_udp(const struct udphdr *udp, int len, struct in_addr sip, struct in_addr dip)
549 char buf[PCAP_SNAPLEN];
550 if (port53 != udp->uh_dport)
552 memcpy(buf, udp + 1, len - sizeof(*udp));
553 if (0 == handle_dns(buf, len - sizeof(*udp), sip, dip))
559 handle_ip(const struct ip *ip, int len)
561 char buf[PCAP_SNAPLEN];
562 int offset = ip->ip_hl << 2;
565 if (ignore_addr.s_addr)
566 if (ip->ip_src.s_addr == ignore_addr.s_addr)
568 if (IPPROTO_UDP != ip->ip_p)
570 memcpy(buf, (void *) ip + offset, len - offset);
571 if (0 == handle_udp((struct udphdr *) buf, len - offset, ip->ip_src, ip->ip_dst))
573 clt = AgentAddr_lookup_or_add(&Sources, ip->ip_src);
575 srv = AgentAddr_lookup_or_add(&Destinations, ip->ip_dst);
582 handle_ppp(const u_char * pkt, int len)
584 char buf[PCAP_SNAPLEN];
586 unsigned short proto;
589 if (*pkt == PPP_ADDRESS_VAL && *(pkt + 1) == PPP_CONTROL_VAL) {
590 pkt += 2; /* ACFC not used */
596 proto = *pkt; /* PFC is used */
600 memcpy(&us, pkt, sizeof(us));
605 if (ETHERTYPE_IP != proto && PPP_IP != proto)
607 memcpy(buf, pkt, len);
608 return handle_ip((struct ip *) buf, len);
614 handle_null(const u_char * pkt, int len)
617 memcpy(&family, pkt, sizeof(family));
618 if (AF_INET != family)
620 return handle_ip((struct ip *) (pkt + 4), len - 4);
625 handle_loop(const u_char * pkt, int len)
628 memcpy(&family, pkt, sizeof(family));
629 if (AF_INET != ntohl(family))
631 return handle_ip((struct ip *) (pkt + 4), len - 4);
638 handle_raw(const u_char * pkt, int len)
640 return handle_ip((struct ip *) pkt, len);
646 handle_ether(const u_char * pkt, int len)
648 char buf[PCAP_SNAPLEN];
649 struct ether_header *e = (void *) pkt;
650 unsigned short etype = ntohs(e->ether_type);
651 if (len < ETHER_HDR_LEN)
653 pkt += ETHER_HDR_LEN;
654 len -= ETHER_HDR_LEN;
655 if (ETHERTYPE_8021Q == etype) {
656 etype = ntohs(*(unsigned short *) (pkt + 2));
660 if (ETHERTYPE_IP != etype)
662 memcpy(buf, pkt, len);
663 return handle_ip((struct ip *) buf, len);
666 /* public function */
667 void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt)
671 if (hdr->caplen < ETHER_HDR_LEN)
674 switch (pcap_datalink (pcap))
677 status = handle_ether (pkt, hdr->caplen);
681 status = handle_ppp (pkt, hdr->caplen);
686 status = handle_loop (pkt, hdr->caplen);
691 status = handle_raw (pkt, hdr->caplen);
695 status = handle_null (pkt, hdr->caplen);
699 fprintf (stderr, "unsupported data link type %d\n",
700 pcap_datalink(pcap));
703 } /* switch (pcap_datalink(pcap)) */
716 AgentAddr_sort(&Sources);
717 AgentAddr_sort(&Destinations);
718 StringCounter_sort(&Tlds);
719 StringCounter_sort(&Slds);
720 StringCounter_sort(&Nlds);
721 StringAddrCounter_sort(&SSC2);
722 StringAddrCounter_sort(&SSC3);
728 query_count_intvl = 0;
736 if (ch >= 'A' && ch <= 'Z')
740 SubReport = Sources_report;
743 SubReport = Destinatioreport;
746 SubReport = Tld_report;
749 SubReport = Sld_report;
752 SubReport = Nld_report;
756 SubReport = SldBySource_report;
759 SubReport = NldBySource_report;
762 SubReport = Qtypes_report;
765 SubReport = Opcodes_report;
774 SubReport = Help_report;
784 print_func(" s - Sources list\n");
785 print_func(" d - Destinations list\n");
786 print_func(" t - Query types\n");
787 print_func(" o - Opcodes\n");
788 print_func(" 1 - TLD list\n");
789 print_func(" 2 - SLD list\n");
790 print_func(" 3 - 3LD list\n");
791 print_func(" @ - SLD+Sources list\n");
792 print_func(" # - 3LD+Sources list\n");
793 print_func("^R - Reset counters\n");
794 print_func("^X - Exit\n");
796 print_func("? - this\n");
847 snprintf(buf, 30, "#%d?", t);
874 snprintf(buf, 30, "Opcode%d", o);
884 return getmaxy(w) - 6;
890 StringCounter_report(StringCounter * list, char *what)
893 int nlines = get_nlines();
894 print_func("%-30s %9s %6s\n", what, "count", "%");
895 print_func("%-30s %9s %6s\n",
896 "------------------------------", "---------", "------");
897 for (sc = list; sc; sc = sc->next) {
898 print_func("%-30.30s %9d %6.1f\n",
901 100.0 * sc->count / query_count_total);
908 StringCounter_free(StringCounter ** headP)
912 for (sc = *headP; sc; sc = next) {
921 StringAddrCounter_free(StringAddrCounter ** headP)
923 StringAddrCounter *ssc;
925 for (ssc = *headP; ssc; ssc = next) {
936 StringCounter_report(Tlds, "TLD");
943 print_func("\tYou must start %s with the -s option\n", progname);
944 print_func("\tto collect 2nd level domain stats.\n", progname);
946 StringCounter_report(Slds, "SLD");
954 print_func("\tYou must start %s with the -t option\n", progname);
955 print_func("\tto collect 3nd level domain stats.\n", progname);
957 StringCounter_report(Nlds, "3LD");
965 int nlines = get_nlines();
966 print_func("%-10s %9s %6s\n", "Query Type", "count", "%");
967 print_func("%-10s %9s %6s\n", "----------", "---------", "------");
968 for (type = 0; type < T_MAX; type++) {
969 if (0 == qtype_counts[type])
971 print_func("%-10s %9d %6.1f\n",
974 100.0 * qtype_counts[type] / query_count_total);
984 int nlines = get_nlines();
985 print_func("%-10s %9s %6s\n", "Opcode ", "count", "%");
986 print_func("%-10s %9s %6s\n", "----------", "---------", "------");
987 for (op = 0; op < OP_MAX; op++) {
988 if (0 == opcode_counts[op])
990 print_func("%-10s %9d %6.1f\n",
993 100.0 * opcode_counts[op] / query_count_total);
1000 AgentAddr_report(AgentAddr * list, const char *what)
1003 int nlines = get_nlines();
1004 print_func("%-16s %9s %6s\n", what, "count", "%");
1005 print_func("%-16s %9s %6s\n", "----------------", "---------", "------");
1006 for (agent = list; agent; agent = agent->next) {
1007 print_func("%-16s %9d %6.1f\n",
1008 anon_inet_ntoa(agent->src),
1010 100.0 * agent->count / query_count_total);
1017 Combo_report(StringAddrCounter * list, char *what1, char *what2)
1019 StringAddrCounter *ssc;
1020 int nlines = get_nlines();
1021 print_func("%-16s %-32s %9s %6s\n", what1, what2, "count", "%");
1022 print_func("%-16s %-32s %9s %6s\n",
1023 "----------------", "--------------------", "---------", "------");
1024 for (ssc = list; ssc; ssc = ssc->next) {
1025 print_func("%-16s %-32s %9d %6.1f\n",
1026 anon_inet_ntoa(ssc->src),
1029 100.0 * ssc->count / query_count_total);
1036 SldBySource_report(void)
1038 if (0 == sld_flag) {
1039 print_func("\tYou must start %s with the -s option\n", progname);
1040 print_func("\tto collect 2nd level domain stats.\n", progname);
1042 Combo_report(SSC2, "Source", "SLD");
1047 NldBySource_report(void)
1049 if (0 == nld_flag) {
1050 print_func("\tYou must start %s with the -t option\n", progname);
1051 print_func("\tto collect 3nd level domain stats.\n", progname);
1053 Combo_report(SSC3, "Source", "3LD");
1059 AgentAddr_free(AgentAddr ** headP)
1063 for (aa = *headP; aa; aa = next) {
1071 Sources_report(void)
1073 AgentAddr_report(Sources, "Sources");
1077 Destinatioreport(void)
1079 AgentAddr_report(Destinations, "Destinations");
1086 print_func("%d new queries, %d total queries",
1087 query_count_intvl, query_count_total);
1089 if (last_ts.tv_sec) {
1090 time_t t = (time_t) last_ts.tv_sec;
1092 print_func("%s", ctime(&t));
1102 * === BEGIN FILTERS ==========================================================
1105 #include "known_tlds.h"
1108 UnknownTldFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1110 const char *tld = QnameToNld(qn, 1);
1113 return 1; /* tld is unknown */
1114 for (i = 0; KnownTLDS[i]; i++)
1115 if (0 == strcmp(KnownTLDS[i], tld))
1116 return 0; /* tld is known */
1117 return 1; /* tld is unknown */
1121 AforAFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1126 return inet_aton(qn, &a);
1130 RFC1918PtrFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1137 strncpy(q, qn, sizeof(q)-1);
1138 q[sizeof(q)-1] = '\0';
1139 t = strstr(q, ".in-addr.arpa");
1143 for (t = strtok(q, "."); t; t = strtok(NULL, ".")) {
1145 i |= ((atoi(t) & 0xff) << 24);
1147 if ((i & 0xff000000) == 0x0a000000)
1149 if ((i & 0xfff00000) == 0xac100000)
1151 if ((i & 0xffff0000) == 0xc0a80000)
1157 set_filter(const char *fn)
1159 if (0 == strcmp(fn, "unknown-tlds"))
1160 Filter = UnknownTldFilter;
1161 else if (0 == strcmp(fn, "A-for-A"))
1162 Filter = AforAFilter;
1163 else if (0 == strcmp(fn, "rfc1918-ptr"))
1164 Filter = RFC1918PtrFilter;
1170 * === END FILTERS ==========================================================
1185 query_count_intvl = 0;
1186 query_count_total = 0;
1187 memset(qtype_counts, '\0', sizeof(qtype_counts));
1188 memset(qclass_counts, '\0', sizeof(qclass_counts));
1189 memset(opcode_counts, '\0', sizeof(opcode_counts));
1190 AgentAddr_free(&Sources);
1191 AgentAddr_free(&Destinations);
1192 StringCounter_free(&Tlds);
1193 StringCounter_free(&Slds);
1194 StringCounter_free(&Nlds);
1195 StringAddrCounter_free(&SSC2);
1196 StringAddrCounter_free(&SSC3);
1197 memset(&last_ts, '\0', sizeof(last_ts));
1203 fprintf(stderr, "usage: %s [opts] netdevice|savefile\n",
1205 fprintf(stderr, "\t-a\tAnonymize IP Addrs\n");
1206 fprintf(stderr, "\t-b expr\tBPF program code\n");
1207 fprintf(stderr, "\t-i addr\tIgnore this source IP address\n");
1208 fprintf(stderr, "\t-p\tDon't put interface in promiscuous mode\n");
1209 fprintf(stderr, "\t-s\tEnable 2nd level domain stats collection\n");
1210 fprintf(stderr, "\t-t\tEnable 3nd level domain stats collection\n");
1211 fprintf(stderr, "\t-f\tfilter-name\n");
1212 fprintf(stderr, "\n");
1213 fprintf(stderr, "Available filters:\n");
1214 fprintf(stderr, "\tunknown-tlds\n");
1215 fprintf(stderr, "\tA-for-A\n");
1216 fprintf(stderr, "\trfc1918-ptr\n");
1221 pcap_select(pcap_t * p, int sec, int usec)
1226 FD_SET(pcap_fileno(p), &R);
1229 return select(pcap_fileno(p) + 1, &R, NULL, NULL, &to);
1234 main(int argc, char *argv[])
1236 char errbuf[PCAP_ERRBUF_SIZE];
1239 int readfile_state = 0;
1240 struct bpf_program fp;
1243 SubReport = Sources_report;
1244 ignore_addr.s_addr = 0;
1245 progname = strdup(strrchr(argv[0], '/') ? strchr(argv[0], '/') + 1 : argv[0]);
1246 srandom(time(NULL));
1249 while ((x = getopt(argc, argv, "ab:f:i:pst")) != -1) {
1264 bpf_program_str = strdup(optarg);
1267 ignore_addr.s_addr = inet_addr(optarg);
1282 device = strdup(argv[0]);
1284 if (0 == stat(device, &sb))
1286 if (readfile_state) {
1287 pcap = pcap_open_offline(device, errbuf);
1289 pcap = pcap_open_live(device, PCAP_SNAPLEN, promisc_flag, 1000, errbuf);
1292 fprintf(stderr, "pcap_open_*: %s\n", errbuf);
1296 if (0 == isatty(1)) {
1297 if (0 == readfile_state) {
1298 fprintf(stderr, "Non-interactive mode requires savefile argument\n");
1302 print_func = printf;
1305 memset(&fp, '\0', sizeof(fp));
1306 x = pcap_compile(pcap, &fp, bpf_program_str, 1, 0);
1308 fprintf(stderr, "pcap_compile failed\n");
1311 x = pcap_setfilter(pcap, &fp);
1313 fprintf(stderr, "pcap_setfilter failed\n");
1318 * non-blocking call added for Mac OS X bugfix. Sent by Max Horn.
1319 * ref http://www.tcpdump.org/lists/workers/2002/09/msg00033.html
1321 x = pcap_setnonblock(pcap, 1, errbuf);
1323 fprintf(stderr, "pcap_setnonblock failed: %s\n", errbuf);
1327 switch (pcap_datalink(pcap)) {
1329 handle_datalink = handle_ether;
1333 handle_datalink = handle_ppp;
1338 handle_datalink = handle_loop;
1343 handle_datalink = handle_raw;
1347 handle_datalink = handle_null;
1350 fprintf(stderr, "unsupported data link type %d\n",
1351 pcap_datalink(pcap));
1358 if (readfile_state < 2) {
1360 * On some OSes select() might return 0 even when
1361 * there are packets to process. Thus, we always
1362 * ignore its return value and just call pcap_dispatch()
1365 if (0 == readfile_state) /* interactive */
1366 pcap_select(pcap, 1, 0);
1367 x = pcap_dispatch(pcap, 50, handle_pcap, NULL);
1369 if (0 == x && 1 == readfile_state) {
1370 /* block on keyboard until user quits */
1379 endwin(); /* klin, Thu Nov 28 08:56:51 2002 */
1381 while (pcap_dispatch(pcap, 50, handle_pcap, NULL))
1384 Sources_report(); print_func("\n");
1385 Destinatioreport(); print_func("\n");
1386 Qtypes_report(); print_func("\n");
1387 Opcodes_report(); print_func("\n");
1388 Tld_report(); print_func("\n");
1389 Sld_report(); print_func("\n");
1390 Nld_report(); print_func("\n");
1391 SldBySource_report();
1396 } /* static int main(int argc, char *argv[]) */