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