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
169 static int interactive = 1;
170 static char *device = NULL;
171 static struct in_addr ignore_addr;
172 static pcap_t *pcap = NULL;
173 static char *bpf_program_str = "udp dst port 53 and udp[10:2] & 0x8000 = 0";
175 static unsigned short port53;
176 static void (*SubReport) (void) = NULL;
177 static int (*handle_datalink) (const u_char * pkt, int len) = NULL;
179 static char *progname = NULL;
180 static int anon_flag = 0;
181 static int sld_flag = 0;
182 static int nld_flag = 0;
183 static int promisc_flag = 1;
184 static AnonMap *Anons = NULL;
186 static int query_count_intvl = 0;
187 static int query_count_total = 0;
188 int qtype_counts[T_MAX];
189 static int opcode_counts[OP_MAX];
190 static int qclass_counts[C_MAX];
191 static AgentAddr *Sources = NULL;
192 static AgentAddr *Destinations = NULL;
193 static StringCounter *Tlds = NULL;
194 static StringCounter *Slds = NULL;
195 static StringCounter *Nlds = NULL;
196 static StringAddrCounter *SSC2 = NULL;
197 static StringAddrCounter *SSC3 = NULL;
199 static struct bpf_timeval last_ts;
201 static struct timeval last_ts;
205 static void SldBySource_report(void);
206 static void NldBySource_report(void);
207 static void Sources_report(void);
208 static void Destinatioreport(void);
209 static void Qtypes_report(void);
210 static void Opcodes_report(void);
211 static void Tld_report(void);
212 static void Sld_report(void);
213 static void Nld_report(void);
214 static void Help_report(void);
215 static void ResetCounters(void);
217 static Filter_t UnknownTldFilter;
218 static Filter_t AforAFilter;
219 static Filter_t RFC1918PtrFilter;
220 static Filter_t *Filter = NULL;
222 static printer *print_func = (printer *) printw;
224 static struct in_addr
225 AnonMap_lookup_or_add(AnonMap ** headP, struct in_addr real)
228 for (T = headP; (*T); T = &(*T)->next)
229 if ((*T)->real.s_addr == real.s_addr)
231 (*T) = calloc(1, sizeof(**T));
233 (*T)->anon.s_addr = random();
238 anon_inet_ntoa(struct in_addr a)
241 a = AnonMap_lookup_or_add(&Anons, a);
246 AgentAddr_lookup_or_add(AgentAddr ** headP, struct in_addr a)
249 for (T = headP; (*T); T = &(*T)->next)
250 if ((*T)->src.s_addr == a.s_addr)
252 (*T) = calloc(1, sizeof(**T));
257 static StringCounter *
258 StringCounter_lookup_or_add(StringCounter ** headP, const char *s)
261 for (T = headP; (*T); T = &(*T)->next)
262 if (0 == strcmp((*T)->s, s))
264 (*T) = calloc(1, sizeof(**T));
269 static StringAddrCounter *
270 StringAddrCounter_lookup_or_add(StringAddrCounter ** headP, struct in_addr a, const char *str)
272 StringAddrCounter **T;
273 for (T = headP; (*T); T = &(*T)->next)
274 if (0 == strcmp((*T)->str, str))
275 if ((*T)->src.s_addr == a.s_addr)
277 (*T) = calloc(1, sizeof(**T));
278 (*T)->str = strdup(str);
284 foo_cmp(const void *A, const void *B)
300 AgentAddr_sort(AgentAddr ** headP)
306 for (a = *headP; a; a = a->next)
308 sortme = calloc(n_agents, sizeof(foo));
310 for (a = *headP; a; a = a->next) {
311 sortme[n_agents].cnt = a->count;
312 sortme[n_agents].ptr = a;
315 qsort(sortme, n_agents, sizeof(foo), foo_cmp);
316 for (i = 0; i < n_agents; i++) {
317 *headP = sortme[i].ptr;
318 headP = &(*headP)->next;
325 StringCounter_sort(StringCounter ** headP)
331 for (sc = *headP; sc; sc = sc->next)
333 sortme = calloc(n_things, sizeof(foo));
335 for (sc = *headP; sc; sc = sc->next) {
336 sortme[n_things].cnt = sc->count;
337 sortme[n_things].ptr = sc;
340 qsort(sortme, n_things, sizeof(foo), foo_cmp);
341 for (i = 0; i < n_things; i++) {
342 *headP = sortme[i].ptr;
343 headP = &(*headP)->next;
350 StringAddrCounter_sort(StringAddrCounter ** headP)
355 StringAddrCounter *ssc;
356 for (ssc = *headP; ssc; ssc = ssc->next)
358 sortme = calloc(n_things, sizeof(foo));
360 for (ssc = *headP; ssc; ssc = ssc->next) {
361 sortme[n_things].cnt = ssc->count;
362 sortme[n_things].ptr = ssc;
365 qsort(sortme, n_things, sizeof(foo), foo_cmp);
366 for (i = 0; i < n_things; i++) {
367 *headP = sortme[i].ptr;
368 headP = &(*headP)->next;
374 #define RFC1035_MAXLABELSZ 63
376 rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
388 /* blasted compression */
391 memcpy(&s, buf + (*off), sizeof(s));
398 /* Make sure the pointer is inside this message */
401 return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
402 } else if (c > RFC1035_MAXLABELSZ) {
404 * "(The 10 and 01 combinations are reserved for future use.)"
415 if ((*off) + len > sz) /* message is too short */
417 memcpy(name + no, buf + (*off), len);
420 *(name + (no++)) = '.';
423 *(name + no - 1) = '\0';
424 /* make sure we didn't allow someone to overflow the name buffer */
430 QnameToNld(const char *qname, int nld)
432 const char *t = strrchr(qname, '.');
436 if (0 == strcmp(t, ".arpa"))
438 while (t > qname && dotcount < nld) {
449 handle_dns(const char *buf, int len, const struct in_addr sip, const struct in_addr dip)
453 char qname[MAX_QNAME_SZ];
454 unsigned short qtype;
455 unsigned short qclass;
461 StringAddrCounter *ssc;
463 if (len < sizeof(qh))
466 memcpy(&us, buf + 00, 2);
469 memcpy(&us, buf + 2, 2);
471 qh.qr = (us >> 15) & 0x01;
472 qh.opcode = (us >> 11) & 0x0F;
473 qh.aa = (us >> 10) & 0x01;
474 qh.tc = (us >> 9) & 0x01;
475 qh.rd = (us >> 8) & 0x01;
476 qh.ra = (us >> 7) & 0x01;
477 qh.rcode = us & 0x0F;
479 memcpy(&us, buf + 4, 2);
480 qh.qdcount = ntohs(us);
482 memcpy(&us, buf + 6, 2);
483 qh.ancount = ntohs(us);
485 memcpy(&us, buf + 8, 2);
486 qh.nscount = ntohs(us);
488 memcpy(&us, buf + 10, 2);
489 qh.arcount = ntohs(us);
492 memset(qname, '\0', MAX_QNAME_SZ);
493 x = rfc1035NameUnpack(buf, len, &offset, qname, MAX_QNAME_SZ);
496 if ('\0' == qname[0])
498 while ((t = strchr(qname, '\n')))
500 while ((t = strchr(qname, '\r')))
502 for (t = qname; *t; t++)
505 memcpy(&us, buf + offset, 2);
507 memcpy(&us, buf + offset + 2, 2);
510 if (Filter && 0 == Filter(qtype, qclass, qname, sip, dip))
514 qtype_counts[qtype]++;
515 qclass_counts[qclass]++;
516 opcode_counts[qh.opcode]++;
518 s = QnameToNld(qname, 1);
519 sc = StringCounter_lookup_or_add(&Tlds, s);
523 s = QnameToNld(qname, 2);
524 sc = StringCounter_lookup_or_add(&Slds, s);
527 /* increment StringAddrCounter */
528 ssc = StringAddrCounter_lookup_or_add(&SSC2, sip, s);
533 s = QnameToNld(qname, 3);
534 sc = StringCounter_lookup_or_add(&Nlds, s);
537 /* increment StringAddrCounter */
538 ssc = StringAddrCounter_lookup_or_add(&SSC3, sip, s);
546 handle_udp(const struct udphdr *udp, int len, struct in_addr sip, struct in_addr dip)
548 char buf[PCAP_SNAPLEN];
549 if (port53 != udp->uh_dport)
551 memcpy(buf, udp + 1, len - sizeof(*udp));
552 if (0 == handle_dns(buf, len - sizeof(*udp), sip, dip))
558 handle_ip(const struct ip *ip, int len)
560 char buf[PCAP_SNAPLEN];
561 int offset = ip->ip_hl << 2;
564 if (ignore_addr.s_addr)
565 if (ip->ip_src.s_addr == ignore_addr.s_addr)
567 if (IPPROTO_UDP != ip->ip_p)
569 memcpy(buf, (void *) ip + offset, len - offset);
570 if (0 == handle_udp((struct udphdr *) buf, len - offset, ip->ip_src, ip->ip_dst))
572 clt = AgentAddr_lookup_or_add(&Sources, ip->ip_src);
574 srv = AgentAddr_lookup_or_add(&Destinations, ip->ip_dst);
581 handle_ppp(const u_char * pkt, int len)
583 char buf[PCAP_SNAPLEN];
585 unsigned short proto;
588 if (*pkt == PPP_ADDRESS_VAL && *(pkt + 1) == PPP_CONTROL_VAL) {
589 pkt += 2; /* ACFC not used */
595 proto = *pkt; /* PFC is used */
599 memcpy(&us, pkt, sizeof(us));
604 if (ETHERTYPE_IP != proto && PPP_IP != proto)
606 memcpy(buf, pkt, len);
607 return handle_ip((struct ip *) buf, len);
613 handle_null(const u_char * pkt, int len)
616 memcpy(&family, pkt, sizeof(family));
617 if (AF_INET != family)
619 return handle_ip((struct ip *) (pkt + 4), len - 4);
624 handle_loop(const u_char * pkt, int len)
627 memcpy(&family, pkt, sizeof(family));
628 if (AF_INET != ntohl(family))
630 return handle_ip((struct ip *) (pkt + 4), len - 4);
637 handle_raw(const u_char * pkt, int len)
639 return handle_ip((struct ip *) pkt, len);
645 handle_ether(const u_char * pkt, int len)
647 char buf[PCAP_SNAPLEN];
648 struct ether_header *e = (void *) pkt;
649 unsigned short etype = ntohs(e->ether_type);
650 if (len < ETHER_HDR_LEN)
652 pkt += ETHER_HDR_LEN;
653 len -= ETHER_HDR_LEN;
654 if (ETHERTYPE_8021Q == etype) {
655 etype = ntohs(*(unsigned short *) (pkt + 2));
659 if (ETHERTYPE_IP != etype)
661 memcpy(buf, pkt, len);
662 return handle_ip((struct ip *) buf, len);
665 /* public function */
666 void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt)
670 if (hdr->caplen < ETHER_HDR_LEN)
673 switch (pcap_datalink (pcap))
676 status = handle_ether (pkt, hdr->caplen);
680 status = handle_ppp (pkt, hdr->caplen);
685 status = handle_loop (pkt, hdr->caplen);
690 status = handle_raw (pkt, hdr->caplen);
694 status = handle_null (pkt, hdr->caplen);
698 fprintf (stderr, "unsupported data link type %d\n",
699 pcap_datalink(pcap));
702 } /* switch (pcap_datalink(pcap)) */
715 AgentAddr_sort(&Sources);
716 AgentAddr_sort(&Destinations);
717 StringCounter_sort(&Tlds);
718 StringCounter_sort(&Slds);
719 StringCounter_sort(&Nlds);
720 StringAddrCounter_sort(&SSC2);
721 StringAddrCounter_sort(&SSC3);
727 query_count_intvl = 0;
735 if (ch >= 'A' && ch <= 'Z')
739 SubReport = Sources_report;
742 SubReport = Destinatioreport;
745 SubReport = Tld_report;
748 SubReport = Sld_report;
751 SubReport = Nld_report;
755 SubReport = SldBySource_report;
758 SubReport = NldBySource_report;
761 SubReport = Qtypes_report;
764 SubReport = Opcodes_report;
773 SubReport = Help_report;
783 print_func(" s - Sources list\n");
784 print_func(" d - Destinations list\n");
785 print_func(" t - Query types\n");
786 print_func(" o - Opcodes\n");
787 print_func(" 1 - TLD list\n");
788 print_func(" 2 - SLD list\n");
789 print_func(" 3 - 3LD list\n");
790 print_func(" @ - SLD+Sources list\n");
791 print_func(" # - 3LD+Sources list\n");
792 print_func("^R - Reset counters\n");
793 print_func("^X - Exit\n");
795 print_func("? - this\n");
846 snprintf(buf, 30, "#%d?", t);
873 snprintf(buf, 30, "Opcode%d", o);
883 return getmaxy(w) - 6;
889 StringCounter_report(StringCounter * list, char *what)
892 int nlines = get_nlines();
893 print_func("%-30s %9s %6s\n", what, "count", "%");
894 print_func("%-30s %9s %6s\n",
895 "------------------------------", "---------", "------");
896 for (sc = list; sc; sc = sc->next) {
897 print_func("%-30.30s %9d %6.1f\n",
900 100.0 * sc->count / query_count_total);
907 StringCounter_free(StringCounter ** headP)
911 for (sc = *headP; sc; sc = next) {
920 StringAddrCounter_free(StringAddrCounter ** headP)
922 StringAddrCounter *ssc;
924 for (ssc = *headP; ssc; ssc = next) {
935 StringCounter_report(Tlds, "TLD");
942 print_func("\tYou must start %s with the -s option\n", progname);
943 print_func("\tto collect 2nd level domain stats.\n", progname);
945 StringCounter_report(Slds, "SLD");
953 print_func("\tYou must start %s with the -t option\n", progname);
954 print_func("\tto collect 3nd level domain stats.\n", progname);
956 StringCounter_report(Nlds, "3LD");
964 int nlines = get_nlines();
965 print_func("%-10s %9s %6s\n", "Query Type", "count", "%");
966 print_func("%-10s %9s %6s\n", "----------", "---------", "------");
967 for (type = 0; type < T_MAX; type++) {
968 if (0 == qtype_counts[type])
970 print_func("%-10s %9d %6.1f\n",
973 100.0 * qtype_counts[type] / query_count_total);
983 int nlines = get_nlines();
984 print_func("%-10s %9s %6s\n", "Opcode ", "count", "%");
985 print_func("%-10s %9s %6s\n", "----------", "---------", "------");
986 for (op = 0; op < OP_MAX; op++) {
987 if (0 == opcode_counts[op])
989 print_func("%-10s %9d %6.1f\n",
992 100.0 * opcode_counts[op] / query_count_total);
999 AgentAddr_report(AgentAddr * list, const char *what)
1002 int nlines = get_nlines();
1003 print_func("%-16s %9s %6s\n", what, "count", "%");
1004 print_func("%-16s %9s %6s\n", "----------------", "---------", "------");
1005 for (agent = list; agent; agent = agent->next) {
1006 print_func("%-16s %9d %6.1f\n",
1007 anon_inet_ntoa(agent->src),
1009 100.0 * agent->count / query_count_total);
1016 Combo_report(StringAddrCounter * list, char *what1, char *what2)
1018 StringAddrCounter *ssc;
1019 int nlines = get_nlines();
1020 print_func("%-16s %-32s %9s %6s\n", what1, what2, "count", "%");
1021 print_func("%-16s %-32s %9s %6s\n",
1022 "----------------", "--------------------", "---------", "------");
1023 for (ssc = list; ssc; ssc = ssc->next) {
1024 print_func("%-16s %-32s %9d %6.1f\n",
1025 anon_inet_ntoa(ssc->src),
1028 100.0 * ssc->count / query_count_total);
1035 SldBySource_report(void)
1037 if (0 == sld_flag) {
1038 print_func("\tYou must start %s with the -s option\n", progname);
1039 print_func("\tto collect 2nd level domain stats.\n", progname);
1041 Combo_report(SSC2, "Source", "SLD");
1046 NldBySource_report(void)
1048 if (0 == nld_flag) {
1049 print_func("\tYou must start %s with the -t option\n", progname);
1050 print_func("\tto collect 3nd level domain stats.\n", progname);
1052 Combo_report(SSC3, "Source", "3LD");
1058 AgentAddr_free(AgentAddr ** headP)
1062 for (aa = *headP; aa; aa = next) {
1070 Sources_report(void)
1072 AgentAddr_report(Sources, "Sources");
1076 Destinatioreport(void)
1078 AgentAddr_report(Destinations, "Destinations");
1085 print_func("%d new queries, %d total queries",
1086 query_count_intvl, query_count_total);
1088 if (last_ts.tv_sec) {
1089 time_t t = (time_t) last_ts.tv_sec;
1091 print_func("%s", ctime(&t));
1101 * === BEGIN FILTERS ==========================================================
1104 #include "known_tlds.h"
1107 UnknownTldFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1109 const char *tld = QnameToNld(qn, 1);
1112 return 1; /* tld is unknown */
1113 for (i = 0; KnownTLDS[i]; i++)
1114 if (0 == strcmp(KnownTLDS[i], tld))
1115 return 0; /* tld is known */
1116 return 1; /* tld is unknown */
1120 AforAFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1125 return inet_aton(qn, &a);
1129 RFC1918PtrFilter(unsigned short qt, unsigned short qc, const char *qn, const struct in_addr sip, const struct in_addr dip)
1136 strncpy(q, qn, sizeof(q)-1);
1137 q[sizeof(q)-1] = '\0';
1138 t = strstr(q, ".in-addr.arpa");
1142 for (t = strtok(q, "."); t; t = strtok(NULL, ".")) {
1144 i |= ((atoi(t) & 0xff) << 24);
1146 if ((i & 0xff000000) == 0x0a000000)
1148 if ((i & 0xfff00000) == 0xac100000)
1150 if ((i & 0xffff0000) == 0xc0a80000)
1156 set_filter(const char *fn)
1158 if (0 == strcmp(fn, "unknown-tlds"))
1159 Filter = UnknownTldFilter;
1160 else if (0 == strcmp(fn, "A-for-A"))
1161 Filter = AforAFilter;
1162 else if (0 == strcmp(fn, "rfc1918-ptr"))
1163 Filter = RFC1918PtrFilter;
1169 * === END FILTERS ==========================================================
1184 query_count_intvl = 0;
1185 query_count_total = 0;
1186 memset(qtype_counts, '\0', sizeof(qtype_counts));
1187 memset(qclass_counts, '\0', sizeof(qclass_counts));
1188 memset(opcode_counts, '\0', sizeof(opcode_counts));
1189 AgentAddr_free(&Sources);
1190 AgentAddr_free(&Destinations);
1191 StringCounter_free(&Tlds);
1192 StringCounter_free(&Slds);
1193 StringCounter_free(&Nlds);
1194 StringAddrCounter_free(&SSC2);
1195 StringAddrCounter_free(&SSC3);
1196 memset(&last_ts, '\0', sizeof(last_ts));
1202 fprintf(stderr, "usage: %s [opts] netdevice|savefile\n",
1204 fprintf(stderr, "\t-a\tAnonymize IP Addrs\n");
1205 fprintf(stderr, "\t-b expr\tBPF program code\n");
1206 fprintf(stderr, "\t-i addr\tIgnore this source IP address\n");
1207 fprintf(stderr, "\t-p\tDon't put interface in promiscuous mode\n");
1208 fprintf(stderr, "\t-s\tEnable 2nd level domain stats collection\n");
1209 fprintf(stderr, "\t-t\tEnable 3nd level domain stats collection\n");
1210 fprintf(stderr, "\t-f\tfilter-name\n");
1211 fprintf(stderr, "\n");
1212 fprintf(stderr, "Available filters:\n");
1213 fprintf(stderr, "\tunknown-tlds\n");
1214 fprintf(stderr, "\tA-for-A\n");
1215 fprintf(stderr, "\trfc1918-ptr\n");
1220 pcap_select(pcap_t * p, int sec, int usec)
1225 FD_SET(pcap_fileno(p), &R);
1228 return select(pcap_fileno(p) + 1, &R, NULL, NULL, &to);
1233 main(int argc, char *argv[])
1235 char errbuf[PCAP_ERRBUF_SIZE];
1238 int readfile_state = 0;
1239 struct bpf_program fp;
1242 SubReport = Sources_report;
1243 ignore_addr.s_addr = 0;
1244 progname = strdup(strrchr(argv[0], '/') ? strchr(argv[0], '/') + 1 : argv[0]);
1245 srandom(time(NULL));
1248 while ((x = getopt(argc, argv, "ab:f:i:pst")) != -1) {
1263 bpf_program_str = strdup(optarg);
1266 ignore_addr.s_addr = inet_addr(optarg);
1281 device = strdup(argv[0]);
1283 if (0 == stat(device, &sb))
1285 if (readfile_state) {
1286 pcap = pcap_open_offline(device, errbuf);
1288 pcap = pcap_open_live(device, PCAP_SNAPLEN, promisc_flag, 1000, errbuf);
1291 fprintf(stderr, "pcap_open_*: %s\n", errbuf);
1295 if (0 == isatty(1)) {
1296 if (0 == readfile_state) {
1297 fprintf(stderr, "Non-interactive mode requires savefile argument\n");
1301 print_func = printf;
1304 memset(&fp, '\0', sizeof(fp));
1305 x = pcap_compile(pcap, &fp, bpf_program_str, 1, 0);
1307 fprintf(stderr, "pcap_compile failed\n");
1310 x = pcap_setfilter(pcap, &fp);
1312 fprintf(stderr, "pcap_setfilter failed\n");
1317 * non-blocking call added for Mac OS X bugfix. Sent by Max Horn.
1318 * ref http://www.tcpdump.org/lists/workers/2002/09/msg00033.html
1320 x = pcap_setnonblock(pcap, 1, errbuf);
1322 fprintf(stderr, "pcap_setnonblock failed: %s\n", errbuf);
1326 switch (pcap_datalink(pcap)) {
1328 handle_datalink = handle_ether;
1332 handle_datalink = handle_ppp;
1337 handle_datalink = handle_loop;
1342 handle_datalink = handle_raw;
1346 handle_datalink = handle_null;
1349 fprintf(stderr, "unsupported data link type %d\n",
1350 pcap_datalink(pcap));
1357 if (readfile_state < 2) {
1359 * On some OSes select() might return 0 even when
1360 * there are packets to process. Thus, we always
1361 * ignore its return value and just call pcap_dispatch()
1364 if (0 == readfile_state) /* interactive */
1365 pcap_select(pcap, 1, 0);
1366 x = pcap_dispatch(pcap, 50, handle_pcap, NULL);
1368 if (0 == x && 1 == readfile_state) {
1369 /* block on keyboard until user quits */
1378 endwin(); /* klin, Thu Nov 28 08:56:51 2002 */
1380 while (pcap_dispatch(pcap, 50, handle_pcap, NULL))
1383 Sources_report(); print_func("\n");
1384 Destinatioreport(); print_func("\n");
1385 Qtypes_report(); print_func("\n");
1386 Opcodes_report(); print_func("\n");
1387 Tld_report(); print_func("\n");
1388 Sld_report(); print_func("\n");
1389 Nld_report(); print_func("\n");
1390 SldBySource_report();
1395 } /* static int main(int argc, char *argv[]) */