1 /*
2 ** This file is a part of PassiveDNS.
3 **
4 ** Copyright (C) 2010-2013, Edward Fjellskål <edwardfjellskaal@gmail.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 **
20 */
21 
22 /*  I N C L U D E S  **********************************************************/
23 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <libgen.h>
27 #include <string.h>
28 #include <arpa/inet.h>
29 #include <netinet/in.h>
30 #include <signal.h>
31 #include <pcap.h>
32 #include <getopt.h>
33 #include <time.h>
34 #include <sys/types.h>
35 #include <grp.h>
36 #include <pwd.h>
37 #include <unistd.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <syslog.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <ctype.h>
44 #include <limits.h>
45 #include "passivedns.h"
46 #include "dns.h"
47 
48 #ifdef HAVE_JSON
49 #include <jansson.h>
50 #endif /* HAVE_JSON */
51 
52 #ifdef HAVE_PFRING
53 #include <pfring.h>
54 #endif /* HAVE_PFRING */
55 
56 #ifndef CONFDIR
57 #define CONFDIR "/etc/passivedns/"
58 #endif
59 
60 /*  G L O B A L S  *** (or candidates for refactoring, as we say)***********/
61 globalconfig config;
62 connection *bucket[BUCKET_SIZE];
63 uint8_t signal_reopen_log_files = 0;
64 
65 /*  I N T E R N A L   P R O T O T Y P E S  ***********************************/
66 static void usage();
67 static void show_version();
68 void check_vlan (packetinfo *pi);
69 void prepare_raw (packetinfo *pi);
70 void prepare_sll (packetinfo *pi);
71 void prepare_eth (packetinfo *pi);
72 void prepare_ip4 (packetinfo *pi);
73 void prepare_ip4ip (packetinfo *pi);
74 void prepare_ip6 (packetinfo *pi);
75 void prepare_ip6ip (packetinfo *pi);
76 void prepare_udp (packetinfo *pi);
77 void prepare_tcp (packetinfo *pi);
78 void parse_eth (packetinfo *pi);
79 void parse_ip4 (packetinfo *pi);
80 void parse_ip6 (packetinfo *pi);
81 void parse_udp (packetinfo *pi);
82 void parse_tcp (packetinfo *pi);
83 const char *u_ntop_src(packetinfo *pi, char *dest);
84 void set_pkt_end_ptr (packetinfo *pi);
85 void check_interrupt();
86 void end_sessions();
87 void set_end_sessions();
88 void set_end_dns_records();
89 void cxt_init();
90 int connection_tracking(packetinfo *pi);
91 connection *cxt_new(packetinfo *pi);
92 void del_connection(connection *, connection **);
93 void print_pdns_stats();
94 void free_config();
95 void reopen_log_files();
96 void game_over ();
97 void got_packet(u_char *useless, const struct pcap_pkthdr *pheader,
98                 const u_char *packet);
99 #ifdef HAVE_PFRING
100 void pfring_got_packet(const struct pfring_pkthdr *pfheader,
101                        const u_char *packet, const u_char *useless);
102 #endif /* HAVE_PFRING */
103 
104 /* F U N C T I O N S  ********************************************************/
105 
106 #ifdef HAVE_PFRING
107 
pfring_got_packet(const struct pfring_pkthdr * pfheader,const u_char * packet,const u_char * useless)108 void pfring_got_packet(const struct pfring_pkthdr *pfheader,
109                        const u_char *packet, const u_char *useless)
110 {
111     /* pcap_pkthdr and pfring_pkthdr are identical to each other*/
112     struct pcap_pkthdr *pheader = (struct pcap_pkthdr *)pfheader;
113 
114     /* Set timestamp if it's not set */
115     if (pheader->ts.tv_sec == 0)
116         pheader->ts.tv_sec = time(NULL);
117 
118     /* pfring_loop orders the arguments differently than pcap_loop */
119     got_packet((u_char *)useless, (const struct pcap_pkthdr *)pheader, packet);
120 }
121 
122 #endif /* HAVE_PFRING */
123 
got_packet(u_char * useless,const struct pcap_pkthdr * pheader,const u_char * packet)124 void got_packet(u_char *useless, const struct pcap_pkthdr *pheader,
125                 const u_char *packet)
126 {
127     config.p_s.got_packets++;
128     packetinfo pstruct = {0};
129     packetinfo *pi = &pstruct;
130     pi->packet = packet;
131     pi->pheader = pheader;
132     set_pkt_end_ptr (pi);
133     memcpy( &config.tstamp, &pi->pheader->ts, sizeof( struct timeval ) ); /* Global */
134 
135     if (signal_reopen_log_files)
136         reopen_log_files();
137 
138     if (config.intr_flag != 0) {
139         check_interrupt();
140     }
141     config.inpacket = 1;
142 
143     switch (config.linktype) {
144         case DLT_RAW:
145             prepare_raw(pi);
146             break;
147 #ifdef DLT_LINUX_SLL
148         case DLT_LINUX_SLL:
149             prepare_sll(pi);
150             break;
151 #endif
152         default:
153             prepare_eth(pi);
154             check_vlan(pi);
155             break;
156     }
157 
158     switch (pi->eth_type) {
159         case ETHERNET_TYPE_IP:
160             prepare_ip4(pi);
161             parse_ip4(pi);
162             break;
163         case ETHERNET_TYPE_IPV6:
164             prepare_ip6(pi);
165             parse_ip6(pi);
166             break;
167         default:
168             config.p_s.otherl_recv++;
169             //vlog(0x3, "[*] ETHERNET TYPE : %x\n",pi->eth_hdr->eth_ip_type);
170             break;
171     }
172 
173     config.inpacket = 0;
174 }
175 
prepare_raw(packetinfo * pi)176 void prepare_raw(packetinfo *pi)
177 {
178     pi->eth_hlen = 0;
179     if (IP_V((ip4_header *)pi->packet) == 4)
180         pi->eth_type = ETHERNET_TYPE_IP;
181     else
182         pi->eth_type = ETHERNET_TYPE_IPV6;
183 }
184 
prepare_sll(packetinfo * pi)185 void prepare_sll(packetinfo *pi)
186 {
187     pi->eth_hlen = SLL_HDR_LEN;
188 
189     if (IP_V((ip4_header *)(pi->packet + SLL_HDR_LEN)) == 4)
190         pi->eth_type = ETHERNET_TYPE_IP;
191     else
192         pi->eth_type = ETHERNET_TYPE_IPV6;
193 }
194 
prepare_eth(packetinfo * pi)195 void prepare_eth(packetinfo *pi)
196 {
197     if (pi->packet + ETHERNET_HEADER_LEN > pi->end_ptr)
198         return;
199 
200     config.p_s.eth_recv++;
201     pi->eth_hdr = (ether_header *) (pi->packet);
202     pi->eth_type = ntohs(pi->eth_hdr->eth_ip_type);
203     pi->eth_hlen = ETHERNET_HEADER_LEN;
204 }
205 
check_vlan(packetinfo * pi)206 void check_vlan(packetinfo *pi)
207 {
208     if (pi->eth_type == ETHERNET_TYPE_8021Q) {
209         vlog(0x3, "[*] ETHERNET TYPE 8021Q\n");
210         config.p_s.vlan_recv++;
211         pi->vlan = pi->eth_hdr->eth_8_vid;
212         pi->eth_type = ntohs(pi->eth_hdr->eth_8_ip_type);
213         pi->eth_hlen += 4;
214         if ( pi->eth_type == ETHERNET_TYPE_8021Q ) {
215             vlog(0x3, "[*] ETHERNET TYPE 8021Q in 8021Q\n");
216             pi->eth_type = ntohs(pi->eth_hdr->eth_82_ip_type);
217             pi->eth_hlen += 4;
218             pi->vlan = pi->eth_hdr->eth_82_vid;
219         }
220     }
221     else if (pi->eth_type == (ETHERNET_TYPE_802Q1MT  | ETHERNET_TYPE_802Q1MT2 |
222                               ETHERNET_TYPE_802Q1MT3 | ETHERNET_TYPE_8021AD)) {
223         vlog(0x3, "[*] ETHERNET TYPE 802Q1MT\n");
224         pi->mvlan = pi->eth_hdr->eth_82_mvid;
225         pi->eth_type = ntohs(pi->eth_hdr->eth_82_ip_type);
226         pi->eth_hlen += 8;
227     }
228 }
229 
prepare_ip4(packetinfo * pi)230 void prepare_ip4(packetinfo *pi)
231 {
232     config.p_s.ip4_recv++;
233     pi->af = AF_INET;
234     pi->ip4 = (ip4_header *) (pi->packet + pi->eth_hlen);
235     pi->packet_bytes = (pi->ip4->ip_len - (IP_HL(pi->ip4) * 4));
236 }
237 
parse_ip4(packetinfo * pi)238 void parse_ip4(packetinfo *pi)
239 {
240     /* Paranoia */
241     if (((pi->packet + pi->eth_hlen) + (IP_HL(pi->ip4) * 4)) > pi->end_ptr) {
242         dlog("[D] Refusing to parse IPv4 packet: IPv4-hdr passed end_ptr\n");
243         return;
244     }
245 
246     switch (pi->ip4->ip_p) {
247         case IP_PROTO_TCP:
248             prepare_tcp(pi);
249             parse_tcp(pi);
250             break;
251         case IP_PROTO_UDP:
252             prepare_udp(pi);
253             parse_udp(pi);
254             break;
255         case IP_PROTO_IP4:
256             prepare_ip4ip(pi);
257             break;
258         case IP_PROTO_IP6:
259             prepare_ip4ip(pi);
260             break;
261         default:
262             break;
263     }
264 }
265 
prepare_ip6ip(packetinfo * pi)266 void prepare_ip6ip(packetinfo *pi)
267 {
268     packetinfo pipi;
269     memset(&pipi, 0, sizeof(packetinfo));
270     config.p_s.ip6ip_recv++;
271     pipi.pheader = pi->pheader;
272     pipi.packet = (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
273     pipi.end_ptr = pi->end_ptr;
274 
275     if (pi->ip6->next == IP_PROTO_IP4) {
276         prepare_ip4(&pipi);
277         parse_ip4(&pipi);
278     }
279     else {
280         prepare_ip6(&pipi);
281         parse_ip6(&pipi);
282     }
283 }
284 
prepare_ip4ip(packetinfo * pi)285 void prepare_ip4ip(packetinfo *pi)
286 {
287     packetinfo pipi;
288     memset(&pipi, 0, sizeof(packetinfo));
289     config.p_s.ip4ip_recv++;
290     pipi.pheader = pi->pheader;
291     pipi.packet = (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
292     pipi.end_ptr = pi->end_ptr;
293 
294     if (pi->ip4->ip_p == IP_PROTO_IP4) {
295         prepare_ip4(&pipi);
296         parse_ip4(&pipi);
297     }
298     else {
299         prepare_ip6(&pipi);
300         parse_ip6(&pipi);
301     }
302 }
303 
prepare_ip6(packetinfo * pi)304 void prepare_ip6(packetinfo *pi)
305 {
306     config.p_s.ip6_recv++;
307     pi->af = AF_INET6;
308     pi->ip6 = (ip6_header *) (pi->packet + pi->eth_hlen);
309     pi->packet_bytes = pi->ip6->len;
310 }
311 
parse_ip6(packetinfo * pi)312 void parse_ip6(packetinfo *pi)
313 {
314     switch (pi->ip6->next) {
315         case IP_PROTO_TCP:
316             prepare_tcp(pi);
317             parse_tcp(pi);
318             break;
319         case IP_PROTO_UDP:
320             prepare_udp(pi);
321             parse_udp(pi);
322             break;
323         case IP_PROTO_IP4:
324             prepare_ip6ip(pi);
325             break;
326         case IP_PROTO_IP6:
327             prepare_ip6ip(pi);
328             break;
329         default:
330             break;
331     }
332 }
333 
set_pkt_end_ptr(packetinfo * pi)334 void set_pkt_end_ptr(packetinfo *pi)
335 {
336     /* Paranoia! */
337     if (pi->pheader->len <= SNAPLENGTH)
338         pi->end_ptr = (pi->packet + pi->pheader->len);
339     else
340         pi->end_ptr = (pi->packet + SNAPLENGTH);
341 }
342 
prepare_tcp(packetinfo * pi)343 void prepare_tcp(packetinfo *pi)
344 {
345     config.p_s.tcp_recv++;
346     if (pi->af == AF_INET) {
347         vlog(0x3, "[*] IPv4 PROTOCOL TYPE TCP:\n");
348         pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen +
349                    (IP_HL(pi->ip4) * 4));
350         pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 -
351                    (IP_HL(pi->ip4) * 4) - pi->eth_hlen);
352         pi->payload = (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4) +
353                       (TCP_OFFSET(pi->tcph) * 4));
354     }
355     else if (pi->af == AF_INET6) {
356         vlog(0x3, "[*] IPv6 PROTOCOL TYPE TCP:\n");
357         pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
358         pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 -
359                    IP6_HEADER_LEN - pi->eth_hlen);
360         pi->payload = (pi->packet + pi->eth_hlen + IP6_HEADER_LEN +
361                       (TCP_OFFSET(pi->tcph)*4));
362     }
363     pi->proto  = IP_PROTO_TCP;
364     pi->s_port = pi->tcph->src_port;
365     pi->d_port = pi->tcph->dst_port;
366     connection_tracking(pi);
367 }
368 
prepare_udp(packetinfo * pi)369 void prepare_udp(packetinfo *pi)
370 {
371     config.p_s.udp_recv++;
372     if (pi->af == AF_INET) {
373         vlog(0x3, "[*] IPv4 PROTOCOL TYPE UDP:\n");
374         pi->udph = (udp_header *) (pi->packet + pi->eth_hlen +
375                    (IP_HL(pi->ip4) * 4));
376         pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
377                     (IP_HL(pi->ip4) * 4) - pi->eth_hlen;
378         pi->payload = (pi->packet + pi->eth_hlen +
379                         (IP_HL(pi->ip4) * 4) + UDP_HEADER_LEN);
380     }
381     else if (pi->af == AF_INET6) {
382         vlog(0x3, "[*] IPv6 PROTOCOL TYPE UDP:\n");
383         pi->udph = (udp_header *) (pi->packet + pi->eth_hlen +
384                    IP6_HEADER_LEN);
385         pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
386                     IP6_HEADER_LEN - pi->eth_hlen;
387         pi->payload = (pi->packet + pi->eth_hlen +
388                         IP6_HEADER_LEN + UDP_HEADER_LEN);
389     }
390     pi->proto  = IP_PROTO_UDP;
391     pi->s_port = pi->udph->src_port;
392     pi->d_port = pi->udph->dst_port;
393     connection_tracking(pi);
394 }
395 
parse_tcp(packetinfo * pi)396 void parse_tcp(packetinfo *pi)
397 {
398     if (pi->plen <= 0) return;
399 
400     /* Reliable traffic comes from the servers (normally on port 53 or 5353)
401      * and the client has sent at least one packet on that
402      * connecton (Maybe asking for an aswer :) */
403     dlog("[D] Parsing TCP packet...\n");
404     dns_parser(pi);
405 }
406 
parse_udp(packetinfo * pi)407 void parse_udp(packetinfo *pi)
408 {
409     if (pi->plen <= 0) return;
410 
411     /* Reliable traffic comes from the servers (normally on port 53 or 5353)
412      * and the client has sent at least one packet on that
413      * connecton (Maybe asking for an aswer :) */
414     dlog("[D] Parsing UDP packet...\n");
415     dns_parser(pi);
416 }
417 
connection_tracking(packetinfo * pi)418 int connection_tracking(packetinfo *pi)
419 {
420     struct in6_addr *ip_src;
421     struct in6_addr *ip_dst;
422     struct in6_addr ips;
423     struct in6_addr ipd;
424     uint16_t src_port = pi->s_port;
425     uint16_t dst_port = pi->d_port;
426     int af = pi->af;
427     connection *cxt = NULL;
428     connection *head = NULL;
429     uint32_t hash;
430 
431     if(af == AF_INET6){
432         ip_src = &PI_IP6SRC(pi);
433         ip_dst = &PI_IP6DST(pi);
434     }
435     else {
436 #ifdef BSD_DERIVED
437         ips.__u6_addr.__u6_addr32[0] = pi->ip4->ip_src;
438         ipd.__u6_addr.__u6_addr32[0] = pi->ip4->ip_dst;
439 #else
440         ips.s6_addr32[0] = pi->ip4->ip_src;
441         ipd.s6_addr32[0] = pi->ip4->ip_dst;
442 #endif
443         ip_src = &ips;
444         ip_dst = &ipd;
445     }
446 
447     /* Find the right connection bucket */
448     if (af == AF_INET)
449         hash = CXT_HASH4(IP4ADDR(ip_src), IP4ADDR(ip_dst), src_port, dst_port,
450                          pi->proto);
451     else if (af == AF_INET6)
452         hash = CXT_HASH6(ip_src, ip_dst, src_port, dst_port, pi->proto);
453     else {
454         dlog("[D] Only CTX with AF_INET and AF_INET6 are supported: %d\n", af);
455         return 0;
456     }
457 
458     cxt = bucket[hash];
459     head = cxt;
460 
461     /* Search through the bucket */
462     while (cxt != NULL)
463     {
464         /* Two-way compare of given connection against connection table */
465         if (af == AF_INET) {
466             if (CMP_CXT4(cxt, IP4ADDR(ip_src), src_port, IP4ADDR(ip_dst), dst_port)) {
467                 /* Client sends first packet (TCP/SYN - UDP?) hence this is a client */
468                 dlog("[D] Found existing v4 client connection.\n");
469                 return cxt_update_client(cxt, pi);
470             }
471             else if (CMP_CXT4(cxt, IP4ADDR(ip_dst), dst_port, IP4ADDR(ip_src), src_port)) {
472 
473                 if (pi->sc == SC_SERVER) {
474                     /* This is a server */
475                     dlog("[D] Found existing v4 server connection.\n");
476                     return cxt_update_server(cxt, pi);
477                 }
478                 else {
479                     /* This is a client, where we saw a mid-stream DNS response first */
480                     dlog("[D] Found existing unknown v4 server connection.\n");
481                     return cxt_update_client(cxt, pi);
482                 }
483             }
484         }
485         else if (af == AF_INET6) {
486             if (CMP_CXT6(cxt, ip_src, src_port, ip_dst, dst_port)) {
487                 dlog("[D] Found existing v6 client connection.\n");
488                 return cxt_update_client(cxt, pi);
489             }
490             else if (CMP_CXT6(cxt, ip_dst, dst_port, ip_src, src_port)) {
491                 dlog("[D] Found existing v6 client connection.\n");
492                 return cxt_update_server(cxt, pi);
493             }
494         }
495         cxt = cxt->next;
496     }
497     /* Bucket turned upside down didn't yield anything. New connection */
498     dlog("[D] New connection.\n");
499     cxt = cxt_new(pi);
500 
501     /* New connections are pushed on to the head of bucket[s_hash] */
502     cxt->next = head;
503     if (head != NULL)
504         /* Are we double linked? */
505         head->prev = cxt;
506 
507     bucket[hash] = cxt;
508     pi->cxt = cxt;
509     return cxt_update_unknown(cxt, pi);
510 }
511 
512 /* Freshly smelling connection :d */
cxt_new(packetinfo * pi)513 connection *cxt_new(packetinfo *pi)
514 {
515     struct in6_addr ips;
516     struct in6_addr ipd;
517     connection *cxt;
518     config.cxtrackerid++;
519     cxt = (connection *) calloc(1, sizeof(connection));
520     cxt->cxid = config.cxtrackerid;
521     cxt->af = pi->af;
522 
523     if (pi->tcph)
524         cxt->s_tcpFlags |= pi->tcph->t_flags;
525 
526     cxt->start_time = pi->pheader->ts.tv_sec;
527     cxt->last_pkt_time = pi->pheader->ts.tv_sec;
528 
529     if (pi->af == AF_INET6){
530         cxt->s_ip = PI_IP6SRC(pi);
531         cxt->d_ip = PI_IP6DST(pi);
532     }
533     else {
534 #ifdef BSD_DERIVED
535         ips.__u6_addr.__u6_addr32[0] = pi->ip4->ip_src;
536         ipd.__u6_addr.__u6_addr32[0] = pi->ip4->ip_dst;
537 #else
538         ips.s6_addr32[0] = pi->ip4->ip_src;
539         ipd.s6_addr32[0] = pi->ip4->ip_dst;
540 #endif
541         cxt->s_ip = ips;
542         cxt->d_ip = ipd;
543     }
544 
545     cxt->s_port = pi->s_port;
546     cxt->d_port = pi->d_port;
547     cxt->proto = pi->proto;
548 
549     cxt->check = 0x00;
550     cxt->reversed = 0;
551     config.curcxt++;
552 
553     return cxt;
554 }
555 
cxt_update_client(connection * cxt,packetinfo * pi)556 int cxt_update_client(connection *cxt, packetinfo *pi)
557 {
558     cxt->last_pkt_time = pi->pheader->ts.tv_sec;
559 
560     if (pi->tcph)
561         cxt->s_tcpFlags |= pi->tcph->t_flags;
562 
563     cxt->s_total_bytes += pi->packet_bytes;
564     cxt->s_total_pkts += 1;
565 
566     pi->cxt = cxt;
567     pi->sc = SC_CLIENT;
568 
569     if (cxt->s_total_bytes > MAX_BYTE_CHECK ||
570         cxt->s_total_pkts  > MAX_PKT_CHECK) {
571         return 0;   /* Don't Check! */
572     }
573 
574     return SC_CLIENT;
575 }
576 
cxt_update_unknown(connection * cxt,packetinfo * pi)577 int cxt_update_unknown(connection *cxt, packetinfo *pi)
578 {
579     cxt->last_pkt_time = pi->pheader->ts.tv_sec;
580 
581     if (pi->tcph)
582         cxt->s_tcpFlags |= pi->tcph->t_flags;
583 
584     cxt->s_total_bytes += pi->packet_bytes;
585     cxt->s_total_pkts += 1;
586 
587     pi->cxt = cxt;
588     pi->sc = SC_UNKNOWN;
589 
590     if (cxt->s_total_bytes > MAX_BYTE_CHECK ||
591         cxt->s_total_pkts  > MAX_PKT_CHECK) {
592         return 0;   /* Don't Check! */
593     }
594 
595     return SC_UNKNOWN;
596 }
597 
cxt_update_server(connection * cxt,packetinfo * pi)598 int cxt_update_server(connection *cxt, packetinfo *pi)
599 {
600     cxt->last_pkt_time = pi->pheader->ts.tv_sec;
601 
602     if (pi->tcph)
603         cxt->d_tcpFlags |= pi->tcph->t_flags;
604 
605     cxt->d_total_bytes += pi->packet_bytes;
606     cxt->d_total_pkts += 1;
607 
608     pi->cxt = cxt;
609     pi->sc = SC_SERVER;
610 
611     if (cxt->d_total_bytes > MAX_BYTE_CHECK ||
612             cxt->d_total_pkts  > MAX_PKT_CHECK)
613         return 0;   /* Don't check! */
614 
615     return SC_SERVER;
616 }
617 
end_all_sessions()618 void end_all_sessions()
619 {
620     connection *cxt;
621     int cxkey;
622     config.llcxt = 0;
623 
624     for (cxkey = 0; cxkey < BUCKET_SIZE; cxkey++)
625     {
626         cxt = bucket[cxkey];
627         while (cxt != NULL)
628         {
629             config.llcxt++;
630             if (cxt->prev)
631                 cxt->prev->next = cxt->next;
632             if (cxt->next)
633                 cxt->next->prev = cxt->prev;
634             connection *tmp = cxt;
635 
636             cxt = cxt->next;
637             del_connection(tmp, &bucket[cxkey]);
638             if (cxt == NULL)
639                 bucket[cxkey] = NULL;
640         }
641     }
642     dlog("CXT in list before cleaning: %10u\n", config.llcxt);
643     dlog("CXT in list after  cleaning: %10u\n", config.curcxt);
644 }
645 
end_sessions()646 void end_sessions()
647 {
648     connection *cxt;
649     time_t check_time;
650     check_time = config.tstamp.tv_sec;
651     int ended, expired = 0;
652     config.llcxt = 0;
653 
654     int iter;
655 
656     for (iter = 0; iter < BUCKET_SIZE; iter++)
657     {
658         cxt = bucket[iter];
659         while (cxt != NULL)
660         {
661             ended = 0;
662             config.llcxt++;
663             /* TCP */
664             if (cxt->proto == IP_PROTO_TCP) {
665                 /* FIN from both sides */
666                 if (cxt->s_tcpFlags & TF_FIN && cxt->d_tcpFlags & TF_FIN
667                         && (check_time - cxt->last_pkt_time) > 5)
668                     ended = 1;
669                 /* RST from either side */
670                 else if ((cxt->s_tcpFlags & TF_RST || cxt->d_tcpFlags & TF_RST)
671                         && (check_time - cxt->last_pkt_time) > 5)
672                     ended = 1;
673                 else if ((check_time - cxt->last_pkt_time) > TCP_TIMEOUT)
674                     expired = 1;
675             }
676             /* UDP */
677             else if (cxt->proto == IP_PROTO_UDP
678                     && (check_time - cxt->last_pkt_time) > UDP_TIMEOUT)
679                 expired = 1;
680             /* ICMP */
681             else if (cxt->proto == IP_PROTO_ICMP ||
682                     cxt->proto == IP6_PROTO_ICMP) {
683                 if ((check_time - cxt->last_pkt_time) > ICMP_TIMEOUT)
684                      expired = 1;
685             }
686             /* All other protocols */
687             else if ((check_time - cxt->last_pkt_time) > OTHER_TIMEOUT)
688                 expired = 1;
689 
690             if (ended == 1 || expired == 1) {
691                 /* Remove from the hash */
692                 if (cxt->prev)
693                     cxt->prev->next = cxt->next;
694                 if (cxt->next)
695                     cxt->next->prev = cxt->prev;
696                 connection *tmp = cxt;
697                 connection *tmp_pre = cxt->prev;
698 
699                 ended = expired = 0;
700 
701                 cxt = cxt->next;
702 
703                 del_connection(tmp, &bucket[iter]);
704                 if (cxt == NULL && tmp_pre == NULL)
705                     bucket[iter] = NULL;
706             }
707             else
708                 cxt = cxt->next;
709         }
710     }
711     dlog("CXT in list before cleaning: %10u\n", config.llcxt);
712     dlog("CXT in list after  cleaning: %10u\n", config.curcxt);
713 }
714 
del_connection(connection * cxt,connection ** bucket_ptr)715 void del_connection(connection * cxt, connection ** bucket_ptr)
716 {
717     connection *prev = cxt->prev;  /* Older connections */
718     connection *next = cxt->next;  /* Newer connections */
719 
720     if (prev == NULL) {
721         /* Beginning of list */
722         *bucket_ptr = next;
723         /* Not only entry */
724         if (next)
725             next->prev = NULL;
726     }
727     else if (next == NULL) {
728         /* At end of list! */
729         prev->next = NULL;
730     }
731     else {
732         /* A node */
733         prev->next = next;
734         next->prev = prev;
735     }
736 
737     /* Free and set to NULL */
738     free(cxt);
739     cxt = NULL;
740     config.curcxt--;
741 }
742 
u_ntop_src(packetinfo * pi,char * dest)743 const char *u_ntop_src(packetinfo *pi, char *dest)
744 {
745     if (pi->af == AF_INET) {
746         if (!inet_ntop(AF_INET, &pi->ip4->ip_src, dest, INET_ADDRSTRLEN + 1)) {
747             perror("Something died in inet_ntop");
748             return NULL;
749         }
750     }
751     else if (pi->af == AF_INET6) {
752         if (!inet_ntop(AF_INET6, &pi->ip6->ip_src, dest,
753             INET6_ADDRSTRLEN + 1)) {
754             perror("Something died in inet_ntop");
755             return NULL;
756         }
757     }
758     return dest;
759 }
760 
check_interrupt()761 void check_interrupt()
762 {
763     dlog("[D] In interrupt. Flag: %d\n",config.intr_flag);
764     if (ISSET_INTERRUPT_END(config))
765         game_over();
766 
767     else if (ISSET_INTERRUPT_SESSION(config))
768         set_end_sessions();
769 
770     else if (ISSET_INTERRUPT_DNS(config))
771         set_end_dns_records();
772 
773     else
774         config.intr_flag = 0;
775 }
776 
sig_alarm_handler()777 void sig_alarm_handler()
778 {
779     time_t now_t;
780     now_t = config.tstamp.tv_sec;
781 
782     dlog("[D] Got SIG ALRM: %lu\n", now_t);
783     /* Each time check for timed out sessions */
784     set_end_sessions();
785 
786     /* Only check for timed-out dns records each 10 minutes */
787     if ((now_t - config.dnslastchk) >= 600) {
788         set_end_dns_records();
789     }
790     alarm(TIMEOUT);
791 }
792 
sig_hup_handler()793 void sig_hup_handler()
794 {
795     signal_reopen_log_files = 1;
796 }
797 
reopen_log_files()798 void reopen_log_files()
799 {
800     if (config.output_log) {
801         if (config.logfile_fd != NULL && config.logfile_fd != stdout)
802             fclose(config.logfile_fd);
803         config.logfile_fd = fopen(config.logfile, "a");
804     }
805 
806     if (config.output_log_nxd) {
807         if (config.logfile_all) {
808             /* Do nothing, since both logs use the same file */
809         }
810         else {
811             if (config.logfile_nxd_fd != NULL && config.logfile_nxd_fd != stdout)
812                 fclose(config.logfile_nxd_fd);
813             config.logfile_nxd_fd = fopen(config.logfile_nxd, "a");
814         }
815     }
816     signal_reopen_log_files = 0;
817 }
818 
set_end_dns_records()819 void set_end_dns_records()
820 {
821     config.intr_flag |= INTERRUPT_DNS;
822 
823     if (config.inpacket == 0) {
824         expire_dns_records();
825         config.dnslastchk = config.tstamp.tv_sec;
826         config.intr_flag &= ~INTERRUPT_DNS;
827     }
828 }
829 
set_end_sessions()830 void set_end_sessions()
831 {
832     config.intr_flag |= INTERRUPT_SESSION;
833 
834     if (config.inpacket == 0) {
835         end_sessions();
836         config.intr_flag &= ~INTERRUPT_SESSION;
837     }
838 }
839 
set_chroot(void)840 static int set_chroot(void)
841 {
842    char *absdir;
843 
844    /* Change to the directory */
845    if (chdir(config.chroot_dir) != 0)
846        printf("set_chroot: Can not chdir to \"%s\": %s\n",
847               config.chroot_dir,strerror(errno));
848 
849    /* Always returns an absolute pathname */
850    absdir = getcwd(NULL, 0);
851 
852    /* Make the chroot call */
853    if (chroot(absdir) < 0)
854        printf("Could not chroot to \"%s\": absolute: %s: %s\n",
855               config.chroot_dir, absdir, strerror(errno));
856 
857    if (chdir("/") < 0)
858        printf("Could not chdir to \"/\" after chroot: %s\n", strerror(errno));
859 
860    return 0;
861 }
862 
drop_privs(void)863 int drop_privs(void)
864 {
865     struct group *gr;
866     struct passwd *pw;
867     char *endptr;
868     int i;
869     int do_setuid = 0;
870     int do_setgid = 0;
871     unsigned long groupid = 0;
872     unsigned long userid = 0;
873 
874     if (config.group_name != NULL) {
875         do_setgid = 1;
876         if (!isdigit(config.group_name[0])) {
877             gr = getgrnam(config.group_name);
878             if (!gr) {
879                 if (config.chroot_dir) {
880                     elog("ERROR: you have chrooted and must set numeric group ID.\n");
881                     exit(1);
882                 }
883                 else {
884                     elog("ERROR: couldn't get ID for group %s, group does not exist.", config.group_name);
885                     exit(1);
886                 }
887             }
888             groupid = gr->gr_gid;
889         }
890         else {
891             groupid = strtoul(config.group_name, &endptr, 10);
892         }
893     }
894 
895     if (config.user_name != NULL) {
896         do_setuid = 1;
897         do_setgid = 1;
898         if (isdigit(config.user_name[0]) == 0) {
899             pw = getpwnam(config.user_name);
900             if (pw != NULL) {
901                 userid = pw->pw_uid;
902             }
903             else {
904                 printf("[E] User %s not found!\n", config.user_name);
905             }
906         }
907         else {
908             userid = strtoul(config.user_name, &endptr, 10);
909             pw = getpwuid(userid);
910         }
911 
912         if (config.group_name == NULL && pw != NULL)
913             groupid = pw->pw_gid;
914     }
915 
916     if (do_setgid) {
917         if ((i = setgid(groupid)) < 0)
918             printf("Unable to set group ID: %s", strerror(i));
919    }
920 
921     endgrent();
922     endpwent();
923 
924     if (do_setuid) {
925         if (getuid() == 0 && initgroups(config.user_name, groupid) < 0)
926             printf("Unable to init group names (%s/%lu)", config.user_name,
927                    groupid);
928 
929         if ((i = setuid(userid)) < 0)
930             printf("Unable to set user ID: %s\n", strerror(i));
931     }
932     return 0;
933 }
934 
is_valid_path(const char * path)935 int is_valid_path(const char *path)
936 {
937     char dir[STDBUF];
938     struct stat st;
939 
940     if (path == NULL)
941         return 0;
942 
943     memcpy(dir, path, strnlen(path, STDBUF));
944     dirname(dir);
945 
946     if (stat(dir, &st) != 0)
947         return 0;
948 
949     if (!S_ISDIR(st.st_mode) || access(dir, W_OK) == -1)
950         return 0;
951 
952     return 1;
953 }
954 
create_pid_file(const char * path)955 int create_pid_file(const char *path)
956 {
957     char pid_buffer[12];
958     struct flock lock;
959     int fd;
960 
961     if (!path)
962         path = config.pidfile;
963 
964     if (!is_valid_path(path))
965         printf("PID path \"%s\" aint writable", path);
966 
967     if ((fd = open(path, O_CREAT | O_WRONLY,
968                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
969         return ERROR;
970 
971     /* PID file locking */
972     lock.l_type = F_WRLCK;
973     lock.l_start = 0;
974     lock.l_whence = SEEK_SET;
975     lock.l_len = 0;
976 
977     if (fcntl(fd, F_SETLK, &lock) == -1) {
978         close(fd);
979         return ERROR;
980     }
981 
982     snprintf(pid_buffer, sizeof(pid_buffer), "%d\n", (int)getpid());
983 
984     if (ftruncate(fd, 0) != 0) {
985         close(fd);
986         return ERROR;
987     }
988 
989     if (write(fd, pid_buffer, strlen(pid_buffer)) != 0) {
990         close(fd);
991         return ERROR;
992     }
993 
994     close(fd);
995     return SUCCESS;
996 }
997 
daemonize()998 int daemonize()
999 {
1000     pid_t pid;
1001     int fd;
1002 
1003     pid = fork();
1004 
1005     if (pid > 0)
1006         exit(0);    /* Parent */
1007 
1008     if (pid < 0)
1009         return ERROR;
1010 
1011     setsid();
1012 
1013     if ((fd = open("/dev/null", O_RDWR)) >= 0) {
1014         dup2(fd, 0);
1015         dup2(fd, 1);
1016         dup2(fd, 2);
1017         if (fd > 2) {
1018             close(fd);
1019         }
1020     }
1021 
1022     if (config.pidfile)
1023         return create_pid_file(config.pidfile);
1024 
1025     return SUCCESS;
1026 }
1027 
game_over()1028 void game_over()
1029 {
1030     if (config.inpacket == 0) {
1031         expire_all_dns_records();
1032         print_pdns_stats();
1033 
1034         if (config.handle != NULL)
1035             pcap_close(config.handle);
1036 
1037         config.handle = NULL;
1038 
1039         if (config.hostname != NULL)
1040             free(config.hostname);
1041 
1042 #ifdef HAVE_PFRING
1043         if (config.use_pfring && config.pfhandle != NULL) {
1044             pfring_breakloop(config.pfhandle);
1045             pfring_close(config.pfhandle);
1046         }
1047 #endif /* HAVE_PFRING */
1048 
1049         end_all_sessions();
1050 
1051         if (config.logfile_fd != NULL && config.logfile_fd != stdout)
1052             fclose(config.logfile_fd);
1053 
1054         if (config.logfile_nxd_fd != NULL && config.logfile_nxd_fd != stdout)
1055             fclose(config.logfile_nxd_fd);
1056 
1057         free_config();
1058         olog("\n[*] passivedns ended.\n");
1059         exit(0);
1060     }
1061     config.intr_flag |= INTERRUPT_END;
1062 }
1063 
free_config()1064 void free_config()
1065 {
1066     if (config.cfilter.bf_insns != NULL)
1067         free(config.cfilter.bf_insns);
1068 }
1069 
print_pdns_stats()1070 void print_pdns_stats()
1071 {
1072     FILE *handle = stdout;
1073     if (config.use_stats_file) {
1074         handle = fopen(config.statsfile, "w");
1075         if (handle == NULL) {
1076             olog("[!] Error opening stats file %s: %s\n", config.statsfile,
1077                  strerror(errno));
1078             return;
1079         }
1080     }
1081 
1082     flog(handle, "\n");
1083     flog(handle, "-- Total DNS records allocated            :%12u\n",
1084          config.p_s.dns_records);
1085     flog(handle, "-- Total DNS assets allocated             :%12u\n",
1086          config.p_s.dns_assets);
1087     flog(handle, "-- Total DNS packets over IPv4/TCP        :%12u\n",
1088          config.p_s.ip4_dns_tcp);
1089     flog(handle, "-- Total DNS packets over IPv6/TCP        :%12u\n",
1090          config.p_s.ip6_dns_tcp);
1091     flog(handle, "-- Total DNS packets over TCP decoded     :%12u\n",
1092          config.p_s.ip4_dec_tcp_ok + config.p_s.ip6_dec_tcp_ok);
1093     flog(handle, "-- Total DNS packets over TCP failed      :%12u\n",
1094          config.p_s.ip4_dec_tcp_er + config.p_s.ip6_dec_tcp_er);
1095     flog(handle, "-- Total DNS packets over IPv4/UDP        :%12u\n",
1096          config.p_s.ip4_dns_udp);
1097     flog(handle, "-- Total DNS packets over IPv6/UDP        :%12u\n",
1098          config.p_s.ip6_dns_udp);
1099     flog(handle, "-- Total DNS packets over UDP decoded     :%12u\n",
1100          config.p_s.ip4_dec_udp_ok + config.p_s.ip6_dec_udp_ok);
1101     flog(handle, "-- Total DNS packets over UDP failed      :%12u\n",
1102          config.p_s.ip4_dec_udp_er + config.p_s.ip6_dec_udp_er);
1103     flog(handle, "-- Total packets received from libpcap    :%12u\n",
1104          config.p_s.got_packets);
1105     flog(handle, "-- Total Ethernet packets received        :%12u\n",
1106          config.p_s.eth_recv);
1107     flog(handle, "-- Total VLAN packets received            :%12u\n",
1108          config.p_s.vlan_recv);
1109 
1110     if (config.use_stats_file) {
1111         fclose(handle);
1112     }
1113 }
1114 
usage()1115 void usage()
1116 {
1117     olog("\n");
1118     olog("USAGE:\n");
1119     olog(" $ passivedns [options]\n\n");
1120     olog(" OPTIONS:\n\n");
1121     olog(" -i <iface>      Network device <iface> (default: eth0).\n");
1122     olog(" -r <file>       Read pcap <file>.\n");
1123     olog(" -H <hostname>   Choose hostname to print in record.\n");
1124 #ifdef HAVE_PFRING
1125     olog(" -n              Use PF_RING.\n");
1126     olog(" -c <cluster_id> Set PF_RING cluster_id.\n");
1127 #endif /* HAVE_PFRING */
1128     olog(" -l <file>       Logfile normal queries (default: /var/log/passivedns.log).\n");
1129     olog(" -L <file>       Logfile for SRC Error queries (default: /var/log/passivedns.log).\n");
1130     olog(" -y              Log to syslog (uses local7 syslog facility).\n");
1131     olog(" -Y              Log NXDOMAIN to syslog.\n");
1132     olog(" -d <delimiter>  Delimiter between fields in log file (default: ||).\n");
1133 #ifdef HAVE_JSON
1134     olog(" -j              Use JSON as output in log file.\n");
1135     olog(" -J              Use JSON as output in NXDOMAIN log file.\n");
1136 #endif /* HAVE_JSON */
1137     olog(" -f <fields>     Choose which fields to print (default: -f SMcsCQTAtn).\n");
1138     olog(" -s <file>       Print stats on signal (SIGUSR1) to this file.\n");
1139     olog(" -b 'BPF'        Berkley Packet Filter (default: 'port 53').\n");
1140     olog(" -p <file>       Name of pid file (default: /var/run/passivedns.pid).\n");
1141     olog(" -S <mem>        Soft memory limit in MB (default: 256).\n");
1142     olog(" -C <sec>        Seconds to cache DNS objects in memory (default: %u).\n", DNSCACHETIMEOUT);
1143     olog(" -P <sec>        Seconds between printing duplicate DNS info (default %u).\n", DNSPRINTTIME);
1144     olog(" -X <flags>      Manually set DNS RR Types to care about (default: -X 46CDNPRS).\n");
1145     olog(" -N              Set interface to non promisc. mode.\n");
1146     olog(" -u <uid>        User ID to drop privileges to.\n");
1147     olog(" -g <gid>        Group ID to drop privileges to.\n");
1148     olog(" -T <dir>        Directory to chroot into.\n");
1149     olog(" -q              Quiet mode (no output except errors).\n");
1150     olog(" -D              Run as daemon.\n");
1151     olog(" -V              Show version and exit.\n");
1152     olog(" -h              This help message.\n\n");
1153     olog(" FIELDS:\n");
1154     olog("\n");
1155     olog("   H: YMD-HMS Stamp S: Timestamp(s)  M: Timestamp(ms)  c: Client IP  \n");
1156     olog("   s: Server IP     C: Class         Q: Query          T: Type       \n");
1157     olog("   A: Answer        t: TTL           p: Protocol       n: Count      \n");
1158     olog("   h: hostname      L: QueryLength   l: AnswerLength   w: Client MAC \n");
1159     olog("   W: Server MAC                                                     \n");
1160     olog("\n");
1161     olog(" FLAGS:\n");
1162     olog("\n");
1163     olog(" * For Record Types:\n");
1164     olog("   4:A      6:AAAA  C:CNAME  D:DNAME  N:NAPTR  O:SOA  L:LOC   F:SPF   I:HINFO\n");
1165     olog("   P:PTR    R:RP    S:SRV    T:TXT    M:MX     n:NS   d:DNSEC H:SSHFP\n");
1166     olog("   L also enables GPOS\n");
1167 #ifdef LDNS_RR_TYPE_NSEC3PARAM
1168     olog("   d enables DS, DNSKEY, NSEC, NSEC3, RRSIG\n");
1169 #else
1170     olog("   d enables DS, DNSKEY, NSEC, NSEC3, NSEC3PARAM, RRSIG\n");
1171 #endif /* LDNS_RR_TYPE_NSEC3PARAM */
1172     olog("\n");
1173     olog(" * For Server Return Code (SRC) Errors:\n");
1174     olog("   f:FORMERR   s:SERVFAIL  x:NXDOMAIN  o:NOTIMPL  r:REFUSED\n");
1175     olog("   y:YXDOMAIN  e:YXRRSET   t:NXRRSET   a:NOTAUTH  z:NOTZONE\n");
1176     olog("\n");
1177 }
1178 
show_version()1179 void show_version()
1180 {
1181     olog("\n");
1182     olog("[*] PassiveDNS %s\n", VERSION);
1183     olog("[*] By Edward Bjarte Fjellskål <edward.fjellskaal@gmail.com>\n");
1184     olog("[*] Using %s\n", pcap_lib_version());
1185     olog("[*] Using ldns version %s\n",ldns_version());
1186 #ifdef HAVE_PFRING
1187     /* Print PF_RING version if PF_RING is used */
1188     if (config.use_pfring) {
1189         char pfv[50];
1190         u_int32_t pf_version;
1191         pfring_version(config.pfhandle, &pf_version);
1192         snprintf(pfv, 50, "%d.%d.%d",
1193                 (pf_version & 0xFFFF0000) >> 16,
1194                 (pf_version & 0x0000FF00) >> 8,
1195                  pf_version & 0x000000FF);
1196         olog("[*] Using PF_RING version %s\n", pfv);
1197     }
1198 #endif /* HAVE_PFRING */
1199 #ifdef HAVE_JSON
1200     if (config.use_json || config.use_json_nxd) {
1201         olog("[*] Using jansson version %s\n", JANSSON_VERSION);
1202     }
1203 #endif /* HAVE_JSON */
1204 }
1205 
1206 extern int optind, opterr, optopt; // getopt()
1207 
1208 /* magic main */
main(int argc,char * argv[])1209 int main(int argc, char *argv[])
1210 {
1211     int ch = 0; // verbose_already = 0;
1212     int daemon = 0;
1213     memset(&config, 0, sizeof(globalconfig));
1214     config.inpacket = config.intr_flag = 0;
1215     config.dnslastchk = 0;
1216     config.bpff = BPFF;
1217     config.logfile = "/var/log/passivedns.log";
1218     config.logfile_nxd = "/var/log/passivedns.log";
1219     config.statsfile = "/var/log/passivedns.stats";
1220     config.pidfile = "/var/run/passivedns.pid";
1221     config.promisc = 1;
1222     config.output_log = 0;
1223     config.output_log_nxd = 0;
1224     config.output_syslog = 0;
1225     config.output_syslog_nxd = 0;
1226     /* Default memory limit: 256 MB */
1227     config.mem_limit_max = (256 * 1024 * 1024);
1228     config.dnsprinttime = DNSPRINTTIME;
1229     config.dnscachetimeout =  DNSCACHETIMEOUT;
1230     config.dnsf = 0;
1231     config.log_delimiter = "||";
1232     config.fieldsf = 0;
1233     config.fieldsf |= FIELD_TIMESTAMP_S;
1234     config.fieldsf |= FIELD_TIMESTAMP_MS;
1235     config.fieldsf |= FIELD_CLIENT;
1236     config.fieldsf |= FIELD_SERVER;
1237     config.fieldsf |= FIELD_CLASS;
1238     config.fieldsf |= FIELD_QUERY;
1239     config.fieldsf |= FIELD_TYPE;
1240     config.fieldsf |= FIELD_ANSWER;
1241     config.fieldsf |= FIELD_TTL;
1242     config.fieldsf |= FIELD_COUNT;
1243     config.dnsf |= DNS_CHK_A;
1244     config.dnsf |= DNS_CHK_AAAA;
1245     config.dnsf |= DNS_CHK_PTR;
1246     config.dnsf |= DNS_CHK_CNAME;
1247     config.dnsf |= DNS_CHK_DNAME;
1248     config.dnsf |= DNS_CHK_NAPTR;
1249     config.dnsf |= DNS_CHK_RP;
1250     config.dnsf |= DNS_CHK_SRV;
1251 #ifdef HAVE_PFRING
1252     config.cluster_id = 0;
1253     u_int32_t flags = 0;
1254 #endif /* HAVE_PFRING */
1255     signal(SIGTERM, game_over);
1256     signal(SIGINT,  game_over);
1257     signal(SIGQUIT, game_over);
1258     signal(SIGALRM, sig_alarm_handler);
1259     signal(SIGHUP,  sig_hup_handler);
1260     signal(SIGUSR1, print_pdns_stats);
1261     signal(SIGUSR2, expire_all_dns_records);
1262 
1263 #define ARGS "i:H:r:qc:nyYNjJl:s:L:d:hb:Dp:C:P:S:f:X:u:g:T:V"
1264 
1265     while ((ch = getopt(argc, argv, ARGS)) != -1)
1266         switch (ch) {
1267         case 'i':
1268             config.dev = optarg;
1269             break;
1270         case 'H':
1271             config.hostname = strdup(optarg);
1272             break;
1273         case 'r':
1274             config.pcap_file = optarg;
1275             break;
1276         case 'q':
1277             config.cflags |= CONFIG_QUIET;
1278             break;
1279         case 'L':
1280             config.output_log_nxd = 1;
1281             config.logfile_nxd = optarg;
1282             break;
1283         case 'l':
1284             config.output_log = 1;
1285             config.logfile = optarg;
1286             break;
1287         case 'y':
1288             config.output_syslog = 1;
1289             break;
1290         case 'Y':
1291             config.output_syslog_nxd = 1;
1292             break;
1293 #ifdef HAVE_JSON
1294         case 'j':
1295             config.use_json = 1;
1296             break;
1297         case 'J':
1298             config.use_json_nxd = 1;
1299             break;
1300 #endif /* HAVE_JSON */
1301         case 'd':
1302             config.log_delimiter = optarg;
1303             break;
1304         case 'b':
1305             config.bpff = optarg;
1306             break;
1307         case 'p':
1308             config.pidfile = optarg;
1309             break;
1310         case 'C':
1311             config.dnscachetimeout = strtol(optarg, NULL, 0);
1312             break;
1313         case 'P':
1314             config.dnsprinttime = strtol(optarg, NULL, 0);
1315             break;
1316         case 'S':
1317             config.mem_limit_max = (strtol(optarg, NULL, 0) * 1024 * 1024);
1318             break;
1319         case 's':
1320             config.use_stats_file = 1;
1321             config.statsfile = optarg;
1322             break;
1323         case 'f':
1324             parse_field_flags(optarg);
1325             break;
1326         case 'X':
1327             parse_dns_flags(optarg);
1328             break;
1329         case 'D':
1330             daemon = 1;
1331             break;
1332         case 'T':
1333             config.chroot_dir = optarg;
1334             config.chroot_flag = 1;
1335             break;
1336         case 'u':
1337             config.user_name = optarg;
1338             config.drop_privs_flag = 1;
1339             break;
1340         case 'g':
1341             config.group_name = optarg;
1342             config.drop_privs_flag = 1;
1343             break;
1344         case 'N':
1345             config.promisc = 0;
1346             break;
1347 #ifdef HAVE_PFRING
1348         case 'n':
1349             config.use_pfring = 1;
1350             break;
1351         case 'c':
1352             config.cluster_id = strtol(optarg, NULL, 0);
1353             break;
1354 #endif /* HAVE_PFRING */
1355         case 'h':
1356             usage();
1357             exit(0);
1358             break;
1359         case 'V':
1360             show_version();
1361             olog("\n");
1362             exit(0);
1363             break;
1364         case '?':
1365             elog("unrecognized argument: '%c'\n", optopt);
1366             break;
1367         default:
1368             elog("Did not recognize argument '%c'\n", ch);
1369     }
1370 
1371     /* Get hostname if not specified by commandline */
1372     if (config.fieldsf & FIELD_HOSTNAME) {
1373         if (config.hostname == NULL) {
1374             config.hostname = malloc(HOST_NAME_MAX + 1);
1375             gethostname(config.hostname, HOST_NAME_MAX);
1376         }
1377     }
1378 
1379     /* Fall back to log file if syslog is not used */
1380     if (config.output_syslog == 0)
1381         config.output_log = 1;
1382 
1383     if (config.output_syslog_nxd == 0)
1384         config.output_log_nxd = 1;
1385 
1386     /* Open log file */
1387     if (config.output_log) {
1388         if (config.logfile[0] == '-' && config.logfile[1] == '\0') {
1389             config.logfile_fd = stdout;
1390         }
1391         else {
1392             config.logfile_fd = fopen(config.logfile, "a");
1393             if (config.logfile_fd == NULL) {
1394                 elog("[!] Error opening log file %s\n", config.logfile);
1395                 exit(1);
1396             }
1397         }
1398     }
1399 
1400     /* Open NXDOMAIN log file */
1401     if (config.output_log_nxd) {
1402         if (config.output_log && strcmp(config.logfile, config.logfile_nxd) == 0) {
1403             config.logfile_all = 1;
1404         }
1405         else if (config.logfile_nxd[0] == '-' && config.logfile_nxd[1] == '\0') {
1406             config.logfile_nxd_fd = stdout;
1407         }
1408         else {
1409             config.logfile_nxd_fd = fopen(config.logfile_nxd, "a");
1410             if (config.logfile_nxd_fd == NULL) {
1411                 elog("[!] Error opening NXDOMAIN log file %s\n", config.logfile_nxd);
1412                 exit(1);
1413             }
1414         }
1415     }
1416 
1417     show_version();
1418 
1419 #ifdef HAVE_PFRING
1420     if (config.use_pfring) {
1421         /* PF_RING does not have an option to read PCAP files */
1422         if (config.pcap_file) {
1423             elog("[!] Reading PCAP files are not supported when using PF_RING\n");
1424             exit(1);
1425         }
1426 
1427         if (config.dev == NULL) {
1428             elog("[!] Must specify capture NIC\n");
1429             exit(1);
1430         }
1431 
1432         flags |= PF_RING_PROMISC;
1433         config.pfhandle = pfring_open(config.dev, SNAPLENGTH, flags);
1434 
1435         if (config.pfhandle == NULL) {
1436             elog("[!] Could not start PF_RING capture\n");
1437             exit(1);
1438         }
1439 
1440         config.linktype = DLT_EN10MB;
1441         pfring_set_application_name(config.pfhandle, "passivedns");
1442 
1443         if (config.cluster_id == 0)
1444             config.cluster_id = 99; /* Default cluster_id */
1445 
1446         /* Don't add ring to cluster when using ZC or DNA */
1447         if ((strncmp(config.dev, "zc", 2) != 0) && (strncmp(config.dev, "dna", 3)) != 0) {
1448             if ((pfring_set_cluster(config.pfhandle, config.cluster_id,
1449                  cluster_per_flow)) != 0) {
1450                 elog("[!] Could not set PF_RING cluster_id\n");
1451             }
1452         }
1453 
1454 #ifdef HAVE_PFRING_BPF
1455         if (*config.bpff != '\0') {
1456             if ((pfring_set_bpf_filter(config.pfhandle, config.bpff)) != 0) {
1457                 elog("[!] Unable to set bpf filter\n");
1458             }
1459         }
1460 #endif /* HAVE_PFRING_BPF */
1461 
1462         if ((pfring_enable_ring(config.pfhandle)) != 0) {
1463             elog("[!] Could not enable ring\n");
1464             exit(1);
1465         }
1466 
1467         if (config.chroot_dir) {
1468             olog("[*] Chrooting to dir '%s'..\n", config.chroot_dir);
1469             if (set_chroot()) {
1470                 elog("[!] failed to chroot\n");
1471                 exit(1);
1472             }
1473         }
1474 
1475         if (config.drop_privs_flag) {
1476             olog("[*] Dropping privs...\n");
1477             drop_privs();
1478         }
1479 
1480         if (daemon) {
1481             if (!is_valid_path(config.pidfile))
1482                 elog("[*] Unable to create pidfile '%s'\n", config.pidfile);
1483             openlog("passivedns", LOG_PID | LOG_CONS, LOG_DAEMON);
1484             olog("[*] Daemonizing...\n\n");
1485             daemonize();
1486         }
1487 
1488         alarm(TIMEOUT);
1489         olog("[*] Device: %s\n", config.dev);
1490         olog("[*] Sniffing...\n\n");
1491 
1492         pfring_loop(config.pfhandle, pfring_got_packet, (u_char*)NULL, 1);
1493 
1494         game_over();
1495         return 0;
1496     }
1497 #endif /* HAVE_PFRING */
1498 
1499     if (config.pcap_file) {
1500         /* Read from PCAP file specified by '-r' switch. */
1501         olog("[*] Reading from file %s\n\n", config.pcap_file);
1502         if (!(config.handle = pcap_open_offline(config.pcap_file, config.errbuf))) {
1503             elog("[*] Unable to open %s.  (%s)", config.pcap_file, config.errbuf);
1504         }
1505 
1506     }
1507     else {
1508         /* Look up an available device if non specified */
1509         if (config.dev == 0x0)
1510             config.dev = pcap_lookupdev(config.errbuf);
1511         olog("[*] Device: %s\n", config.dev);
1512 
1513         if ((config.handle = pcap_open_live(config.dev, SNAPLENGTH, config.promisc, 500,
1514              config.errbuf)) == NULL) {
1515             elog("[*] Error pcap_open_live: %s \n", config.errbuf);
1516             exit(1);
1517         }
1518 
1519         if (strlen(config.errbuf) > 0) {
1520             /* Fix to enable passivedns to run in an OpenVZ container */
1521             if (strcmp(config.errbuf, "arptype 65535 not supported by libpcap - falling back to cooked socket") == 0) {
1522                 olog("[*] %s \n", config.errbuf);
1523             }
1524             else {
1525                 elog("[*] Error errbuf: %s \n", config.errbuf);
1526                 exit(1);
1527             }
1528         }
1529 
1530         if (config.chroot_dir) {
1531             olog("[*] Chrooting to dir '%s'..\n", config.chroot_dir);
1532             if(set_chroot()){
1533                 elog("[!] failed to chroot\n");
1534                 exit(1);
1535             }
1536         }
1537 
1538         if (config.drop_privs_flag) {
1539             olog("[*] Dropping privs...\n");
1540             drop_privs();
1541         }
1542 
1543         if (daemon) {
1544             if (!is_valid_path(config.pidfile))
1545                 elog("[*] Unable to create pidfile '%s'\n", config.pidfile);
1546             openlog("passivedns", LOG_PID | LOG_CONS, LOG_DAEMON);
1547             olog("[*] Daemonizing...\n\n");
1548             daemonize();
1549         }
1550 
1551     }
1552 
1553     if (config.handle == NULL) {
1554        game_over();
1555        return 1;
1556     }
1557 
1558     config.linktype = pcap_datalink(config.handle);
1559 
1560     /* Segfaults on empty pcap! */
1561     if ((pcap_compile(config.handle, &config.cfilter, config.bpff, 1,
1562          config.net_mask)) == -1) {
1563             elog("[*] Error pcap_compile user_filter: %s\n",
1564                  pcap_geterr(config.handle));
1565             exit(1);
1566     }
1567 
1568     if (pcap_setfilter(config.handle, &config.cfilter)) {
1569             olog("[*] Unable to set pcap filter! %s",
1570                  pcap_geterr(config.handle));
1571     }
1572 
1573     alarm(TIMEOUT);
1574 
1575     if (!config.pcap_file) olog("[*] Sniffing...\n\n");
1576 
1577     pcap_loop(config.handle, -1, got_packet, NULL);
1578 
1579     game_over();
1580     return 0;
1581 }
1582 
1583