indent dump_dns.c
[prads.git] / src / prads.c
blob5c66af86965a63c294ef33dc59b0cc6055848f1e
1 /*
2 ** This file is a part of PRADS.
3 **
4 ** Copyright (C) 2009, Redpill Linpro
5 ** Copyright (C) 2009, Edward Fjellskål <edward.fjellskaal@redpill-linpro.com>
6 ** Copyright (C) 2009, Kacper Wysocki <kacper.wysocki@redpill-linpro.com>
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License, or
11 ** (at your option) any later version.
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 /* I N C L U D E S *********************************************************/
25 #ifdef OSX
26 #include <sys/malloc.h>
27 #else
28 #include <malloc.h>
29 #endif
31 #include "common.h"
32 #include "prads.h"
33 #include "config.h"
34 #include "sys_func.h"
35 #include "assets.h"
36 #include "cxt.h"
37 #include "ipfp/ipfp.h"
38 #include "servicefp/servicefp.h"
39 #include "util-cxt.h"
40 #include "util-cxt-queue.h"
41 #include "sig.h"
42 #include "mac.h"
43 #include "tcp.h"
44 #include "dump_dns.h"
45 //#include "output-plugins/log_init.h"
46 #include "output-plugins/log.h"
48 #ifndef CONFDIR
49 #define CONFDIR "/etc/prads/"
50 #endif
52 /* G L O B A L S *** (or candidates for refactoring, as we say)***********/
53 globalconfig config;
54 time_t tstamp;
55 servicelist *services[MAX_PORTS];
56 int inpacket, gameover, intr_flag;
57 int nets = 1;
59 fmask network[MAX_NETS];
61 // static strings for comparison
62 // - this is lame and should be a flag!
63 struct tagbstring tUNKNOWN = bsStatic("unknown");
64 bstring UNKNOWN = & tUNKNOWN;
66 /* I N T E R N A L P R O T O T Y P E S ***********************************/
67 static void usage();
68 void check_vlan (packetinfo *pi);
69 void prepare_eth (packetinfo *pi);
70 void prepare_ip4 (packetinfo *pi);
71 void prepare_ip4ip (packetinfo *pi);
72 void prepare_ip6 (packetinfo *pi);
73 void prepare_ip6ip (packetinfo *pi);
74 void prepare_tcp (packetinfo *pi);
75 void prepare_udp (packetinfo *pi);
76 void prepare_icmp (packetinfo *pi);
77 void prepare_gre (packetinfo *pi);
78 void prepare_greip (packetinfo *pi);
79 void prepare_other (packetinfo *pi);
80 void parse_eth (packetinfo *pi);
81 void parse_ip4 (packetinfo *pi);
82 void parse_ip6 (packetinfo *pi);
83 void parse_tcp (packetinfo *pi);
84 void parse_udp (packetinfo *pi);
85 void parse_icmp (packetinfo *pi);
86 void parse_gre (packetinfo *pi);
87 void parse_other (packetinfo *pi);
88 void parse_arp (packetinfo *pi);
89 int parse_network (char *net_s, struct in6_addr *network);
90 int parse_netmask (char *f, int type, struct in6_addr *netmask);
91 void parse_nets(const char *s_net, fmask *network);
93 void udp_guess_direction(packetinfo *pi);
94 void set_pkt_end_ptr (packetinfo *pi);
95 inline int filter_packet(const int af, void *ip);
97 /* F U N C T I O N S ********************************************************/
99 void got_packet(u_char * useless, const struct pcap_pkthdr *pheader,
100 const u_char * packet)
102 config.pr_s.got_packets++;
103 packetinfo pstruct = {0};
104 packetinfo *pi = &pstruct;
105 // memset(&pi, 0, sizeof(packetinfo));
106 //pi = (packetinfo *) calloc(1, sizeof(packetinfo));
107 pi->our = 1;
108 pi->packet = packet;
109 pi->pheader = pheader;
110 set_pkt_end_ptr (pi);
111 tstamp = pi->pheader->ts.tv_sec; // Global
112 if (intr_flag != 0) {
113 check_interrupt();
115 inpacket = 1;
116 prepare_eth(pi);
117 check_vlan(pi);
118 parse_eth(pi);
120 if (pi->eth_type == ETHERNET_TYPE_IP) {
121 prepare_ip4(pi);
122 parse_ip4(pi);
123 goto packet_end;
124 } else if (pi->eth_type == ETHERNET_TYPE_IPV6) {
125 prepare_ip6(pi);
126 parse_ip6(pi);
127 goto packet_end;
128 } else if (pi->eth_type == ETHERNET_TYPE_ARP) {
129 parse_arp(pi);
130 goto packet_end;
132 config.pr_s.otherl_recv++;
133 vlog(0x3, "[*] ETHERNET TYPE : %x\n",pi->eth_hdr->eth_ip_type);
134 packet_end:
135 #ifdef DEBUG
136 if (!pi->our) vlog(0x3, "Not our network packet. Tracked, but not logged.\n");
137 #endif
138 inpacket = 0;
139 //free(pi);
140 return;
143 /* does this ip belong to our network? do we care about the packet?
145 * unfortunately pcap sends us packets in host order
146 * Return value: boolean
148 inline int filter_packet(const int af, void *ipptr)
149 //const struct in6_addr *ip_s)
151 ip6v ip_vec;
152 ip6v t;
154 int i, our = 0;
155 char output[INET_ADDRSTRLEN + 1];
156 switch (af) {
157 case AF_INET:
159 struct in6_addr *ip = (struct in6_addr *) ipptr;
160 for (i = 0; i < MAX_NETS && i < nets; i++) {
161 if (network[i].type != AF_INET)
162 continue;
163 #ifdef DEBUG_PACKET
164 u_ntop(network[i].addr, af, output);
165 dlog("Filter: %s\n", output);
166 u_ntop(network[i].mask, af, output);
167 dlog("mask: %s\n", output);
168 u_ntop(*ip, af, output);
169 dlog("ip: %s\n", output);
170 #endif
171 if((IP4ADDR(ip) & IP4ADDR(&network[i].mask))
172 == (IP4ADDR(&network[i].addr) & IP4ADDR(&network[i].mask)) ){
173 our = 1;
174 break;
176 #ifdef DEBUG_PACKET
177 else {
178 dlog("%8x %8x %8x\n", IP4ADDR(ip) & IP4ADDR(&network[i].mask), IP4ADDR(&network[i].addr) & IP4ADDR(&network[i].mask), IP4ADDR(&network[i].mask));
180 #endif
183 break;
184 case AF_INET6:
186 /* 32-bit comparison of ipv6 nets.
187 * can do better here by using 64-bit or SIMD instructions
190 * PS: use same code for ipv4 - 0 bytes and SIMD doesnt care*/
192 ip_vec.ip6 = *((struct in6_addr *)ipptr);
193 for (i = 0; i < MAX_NETS && i < nets; i++) {
194 if(network[i].type != AF_INET6)
195 continue;
196 #ifdef DEBUG_PACKET
197 u_ntop(network[i].addr, af, output);
198 dlog("net: %s\n", output);
199 u_ntop(network[i].mask, af, output);
200 dlog("mask: %s\n", output);
201 u_ntop(ip_vec.ip6, af, output);
202 dlog("ip: %s\n", output);
203 #endif
204 if (network[i].type == AF_INET6) {
205 #if(1)
206 /* apologies for the uglyness */
207 #ifdef HAVE_SSE2
208 #define compare128(x,y) __builtin_ia32_pcmpeqd128((x), (y))
209 // the builtin is only available on sse2!
210 t.v = __builtin_ia32_pcmpeqd128(
211 ip_vec.v & network[i].mask_v,
212 network[i].addr_v);
213 if (t.i[0] & t.i[1])
214 #else
215 #define compare128(x,y) memcmp(&(x),&(y),16)
216 t.v = ip_vec.v & network[i].mask_v;
217 // xor(a,b) == 0 iff a==b
218 if (!( (t.i[0] ^ network[i].addr64[0]) &
219 (t.i[1] ^ network[i].addr64[1]) ))
220 #endif
222 our = 1;
223 break;
226 #else
227 if ((ip_s.__u6_addr.__u6_addr32[0] & network[i].mask.__u6_addr.__u6_addr32[0])
228 == network[i].addr.__u6_addr.__u6_addr32[0]
229 && (ip_s.__u6_addr.__u6_addr32[1] & network[i].mask.__u6_addr.__u6_addr32[1])
230 == network[i].addr.__u6_addr.__u6_addr32[1]
231 && (ip_s.__u6_addr.__u6_addr32[2] & network[i].mask.__u6_addr.__u6_addr32[2])
232 == network[i].addr.__u6_addr.__u6_addr32[2]
233 && (ip_s.__u6_addr.__u6_addr32[3] & network[i].mask.__u6_addr.__u6_addr32[3])
234 == network[i].addr.__u6_addr.__u6_addr32[3]) {
235 our = 1;
236 break;
238 #endif
242 break;
243 default:
244 fprintf(stderr,
245 "non-ip packets of type %d aren't filtered by netmask yet\n", af);
246 our = 1;
248 #ifdef DEBUG
249 if (af == AF_INET6){
250 inet_ntop(af, (struct in6addr*) ipptr, output, MAX_NETS);
251 }else{
252 inet_ntop(af, (uint32_t*)ipptr, output, MAX_NETS);
254 if (our){
255 vlog(0x2, "Address %s is in our network.\n", output);
256 } else {
257 vlog(0x2, "Address %s is not our network.\n", output);
259 #endif
260 return our;
263 void prepare_eth (packetinfo *pi)
265 if (pi->packet + ETHERNET_HEADER_LEN > pi->end_ptr) return;
266 config.pr_s.eth_recv++;
267 pi->eth_hdr = (ether_header *) (pi->packet);
268 pi->eth_type = ntohs(pi->eth_hdr->eth_ip_type);
269 pi->eth_hlen = ETHERNET_HEADER_LEN;
270 return;
273 void parse_eth (packetinfo *pi)
275 if (!IS_CSSET(&config,CS_MAC)) return;
276 /* update_asset_arp(pi->eth_hdr->ether_src, pi);
278 uint8_t *mac = pi->eth_hdr->ether_src;
280 * XXX: how is mac matching supposed to work?
281 * answer: lookup macs on pertinent frames
282 * and hash into mac asset database
283 * mac assets are like regular assets,
284 * and contain references to other assets they involve
285 if(! pi->asset->mace)
286 mac_entry *match = match_mac(config.sig_mac, mac, 48);
287 //pi->asset->mace ;
289 print_mac(mac);
290 olog("mac matched: %s\n", match->vendor);
292 // call update_asset_mac or smth?
293 // stats?
294 //config.pr_s.eth_recv++;
296 return;
300 void check_vlan (packetinfo *pi)
302 if (pi->eth_type == ETHERNET_TYPE_8021Q) {
303 vlog(0x3, "[*] ETHERNET TYPE 8021Q\n");
304 config.pr_s.vlan_recv++;
305 pi->vlan = pi->eth_hdr->eth_8_vid;
306 pi->eth_type = ntohs(pi->eth_hdr->eth_8_ip_type);
307 pi->eth_hlen += 4;
309 /* This is b0rked - kwy and ebf fix */
310 } else if (pi->eth_type ==
311 (ETHERNET_TYPE_802Q1MT | ETHERNET_TYPE_802Q1MT2 |
312 ETHERNET_TYPE_802Q1MT3 | ETHERNET_TYPE_8021AD)) {
313 vlog(0x3, "[*] ETHERNET TYPE 802Q1MT\n");
314 pi->mvlan = pi->eth_hdr->eth_82_mvid;
315 pi->eth_type = ntohs(pi->eth_hdr->eth_82_ip_type);
316 pi->eth_hlen += 8;
318 return;
321 void prepare_ip4 (packetinfo *pi)
323 config.pr_s.ip4_recv++;
324 pi->af = AF_INET;
325 pi->ip4 = (ip4_header *) (pi->packet + pi->eth_hlen);
326 pi->packet_bytes = (pi->ip4->ip_len - (IP_HL(pi->ip4) * 4));
328 pi->our = filter_packet(pi->af, &PI_IP4SRC(pi));
329 vlog(0x3, "Got %s IPv4 Packet...\n", (pi->our?"our":"foregin"));
330 return;
333 void parse_ip4 (packetinfo *pi)
335 switch (pi->ip4->ip_p) {
336 case IP_PROTO_TCP:
337 prepare_tcp(pi);
338 if (!pi->our)
339 break;
340 parse_tcp(pi);
341 break;
342 case IP_PROTO_UDP:
343 prepare_udp(pi);
344 if (!pi->our)
345 break;
346 parse_udp(pi);
347 break;
348 case IP_PROTO_ICMP:
349 prepare_icmp(pi);
350 if (!pi->our)
351 break;
352 parse_icmp(pi);
353 break;
354 case IP_PROTO_IP4:
355 prepare_ip4ip(pi);
356 break;
357 case IP_PROTO_IP6:
358 prepare_ip4ip(pi);
359 break;
360 case IP_PROTO_GRE:
361 prepare_gre(pi);
362 parse_gre(pi);
363 break;
365 default:
366 prepare_other(pi);
367 if (!pi->our)
368 break;
369 parse_other(pi);
371 return;
374 void prepare_gre (packetinfo *pi)
376 config.pr_s.gre_recv++;
377 if((pi->pheader->caplen - pi->eth_hlen) < GRE_HDR_LEN) {
378 return;
380 if (pi->af == AF_INET) {
381 vlog(0x3, "[*] IPv4 PROTOCOL TYPE GRE:\n");
382 pi->greh = (gre_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
383 } else if (pi->af == AF_INET6) {
384 vlog(0x3, "[*] IPv6 PROTOCOL TYPE GRE:\n");
385 pi->greh = (gre_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
387 pi->proto = IP_PROTO_GRE;
388 return;
391 void parse_gre (packetinfo *pi)
393 uint16_t gre_header_len = GRE_HDR_LEN;
394 gre_sre_header *gsre = NULL;
395 uint16_t len = (pi->pheader->caplen - pi->eth_hlen);
397 update_asset(pi);
399 switch (GRE_GET_VERSION(pi->greh))
401 case GRE_VERSION_0:
402 /* Adjust header length based on content */
403 if (GRE_FLAG_ISSET_KY(pi->greh))
404 gre_header_len += GRE_KEY_LEN;
405 if (GRE_FLAG_ISSET_SQ(pi->greh))
406 gre_header_len += GRE_SEQ_LEN;
407 if (GRE_FLAG_ISSET_CHKSUM(pi->greh) || GRE_FLAG_ISSET_ROUTE(pi->greh))
408 gre_header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
409 if (gre_header_len > len) {
410 return;
412 if (GRE_FLAG_ISSET_ROUTE(pi->greh))
414 gsre = (gre_sre_header *)(pi->greh + gre_header_len);
415 if (gsre == NULL) return;
416 while (1)
418 if ((gre_header_len+GRE_SRE_HDR_LEN) > len) {
419 break;
421 gre_header_len += GRE_SRE_HDR_LEN;
423 if (gsre != NULL && (ntohs(gsre->af) == 0) && (gsre->sre_length == 0))
424 break;
426 gre_header_len += gsre->sre_length;
427 gsre = (gre_sre_header *)(pi->greh + gre_header_len);
428 if (gsre == NULL)
429 return;
432 break;
434 case GRE_VERSION_1:
435 /* GRE version 1 doenst support the fields below RFC 1701 */
436 if (GRE_FLAG_ISSET_CHKSUM(pi->greh)) {
437 return;
439 if (GRE_FLAG_ISSET_ROUTE(pi->greh)) {
440 return;
442 if (GRE_FLAG_ISSET_SSR(pi->greh)) {
443 return;
445 if (GRE_FLAG_ISSET_RECUR(pi->greh)) {
446 return;
448 if (GREV1_FLAG_ISSET_FLAGS(pi->greh)) {
449 return;
451 if (GRE_GET_PROTO(pi->greh) != GRE_PROTO_PPP) {
452 return;
454 if (!(GRE_FLAG_ISSET_KY(pi->greh))) {
455 return;
458 gre_header_len += GRE_KEY_LEN;
460 /* Adjust header length based on content */
461 if (GRE_FLAG_ISSET_SQ(pi->greh))
462 gre_header_len += GRE_SEQ_LEN;
463 if (GREV1_FLAG_ISSET_ACK(pi->greh))
464 gre_header_len += GREV1_ACK_LEN;
465 if (gre_header_len > len) {
466 return;
468 break;
470 default:
471 /* Error */
472 return;
475 prepare_greip(pi);
476 return;
479 void prepare_ip6ip (packetinfo *pi)
481 packetinfo pipi;
482 memset(&pipi, 0, sizeof(packetinfo));
483 config.pr_s.ip6ip_recv++;
484 pipi.pheader = pi->pheader;
485 pipi.packet = (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
486 pipi.end_ptr = pi->end_ptr;
487 if (pi->ip6->next == IP_PROTO_IP4) {
488 prepare_ip4(&pipi);
489 parse_ip4(&pipi);
490 return;
491 } else {
492 prepare_ip6(&pipi);
493 parse_ip6(&pipi);
494 return;
498 void prepare_greip (packetinfo *pi)
500 packetinfo pipi;
501 memset(&pipi, 0, sizeof(packetinfo));
502 pipi.pheader = pi->pheader;
503 pipi.packet = (pi->packet + pi->eth_hlen + pi->gre_hlen);
504 pipi.end_ptr = pi->end_ptr;
505 if (GRE_GET_PROTO(pi->greh) == IP_PROTO_IP4) {
506 prepare_ip4(&pipi);
507 parse_ip4(&pipi);
508 return;
509 } else if (GRE_GET_PROTO(pi->greh) == IP_PROTO_IP6) {
510 prepare_ip6(&pipi);
511 parse_ip6(&pipi);
512 return;
513 } else {
514 /* Not more implemented atm */
515 vlog(0x3, "[*] - NOT CHECKING GRE PACKAGE TYPE Other\n");
516 return;
520 void prepare_ip4ip (packetinfo *pi)
522 packetinfo pipi;
523 memset(&pipi, 0, sizeof(packetinfo));
524 config.pr_s.ip4ip_recv++;
525 pipi.pheader = pi->pheader;
526 pipi.packet = (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
527 pipi.end_ptr = pi->end_ptr;
528 if (pi->ip4->ip_p == IP_PROTO_IP4) {
529 prepare_ip4(&pipi);
530 parse_ip4(&pipi);
531 return;
532 } else {
533 prepare_ip6(&pipi);
534 parse_ip6(&pipi);
535 return;
539 void prepare_ip6 (packetinfo *pi)
541 config.pr_s.ip6_recv++;
542 pi->af = AF_INET6;
543 pi->ip6 = (ip6_header *) (pi->packet + pi->eth_hlen);
544 pi->packet_bytes = pi->ip6->len;
545 // may be dropped due to macros plus
546 //pi->ip_src = PI_IP6SRC(pi);
547 //pi->ip_dst = PI_IP6DST(pi);
548 pi->our = filter_packet(pi->af, &PI_IP6SRC(pi));
549 vlog(0x3, "Got %s IPv6 Packet...\n", (pi->our?"our":"foregin"));
550 return;
553 void parse_ip6 (packetinfo *pi)
555 switch (pi->ip6->next) {
556 case IP_PROTO_TCP:
557 prepare_tcp(pi);
558 if (!pi->our)
559 break;
560 parse_tcp(pi);
561 break;
562 case IP_PROTO_UDP:
563 prepare_udp(pi);
564 if (!pi->our)
565 break;
566 parse_udp(pi);
567 break;
568 case IP6_PROTO_ICMP:
569 prepare_icmp(pi);
570 if (!pi->our)
571 break;
572 parse_icmp(pi);
573 break;
574 case IP_PROTO_IP4:
575 prepare_ip6ip(pi);
576 break;
577 case IP_PROTO_IP6:
578 prepare_ip6ip(pi);
579 break;
581 default:
582 prepare_other(pi);
584 * if (check != 0) {
585 * olog("[*] - CHECKING OTHER PACKAGE\n");
586 * update_asset(AF_INET6,ip6->ip_src);
587 * service_other(*pi->ip4,*tcph)
588 * fp_other(ip, ttl, ipopts, len, id, ipflags, df);
589 * }else{
590 * olog("[*] - NOT CHECKING OTHER PACKAGE\n");
591 * }
593 break;
595 return;
598 void parse_arp (packetinfo *pi)
600 vlog(0x3, "[*] Got ARP packet...\n");
601 config.pr_s.arp_recv++;
602 if (!IS_CSSET(&config,CS_ARP)) return;
603 pi->af = AF_INET;
604 pi->arph = (ether_arp *) (pi->packet + pi->eth_hlen);
606 if (ntohs(pi->arph->ea_hdr.ar_op) == ARPOP_REPLY) {
607 if (filter_packet(pi->af, &pi->arph->arp_spa)) {
608 update_asset_arp(pi->arph->arp_sha, pi);
610 /* arp_check(eth_hdr,pi->pheader->ts.tv_sec); */
611 } else {
612 vlog(0x3, "[*] ARP TYPE: %d\n",ntohs(pi->arph->ea_hdr.ar_op));
616 void set_pkt_end_ptr (packetinfo *pi)
618 /* Paranoia! */
619 if (pi->pheader->len <= SNAPLENGTH) {
620 pi->end_ptr = (pi->packet + pi->pheader->len);
621 } else {
622 pi->end_ptr = (pi->packet + SNAPLENGTH);
624 return;
627 void prepare_tcp (packetinfo *pi)
629 config.pr_s.tcp_recv++;
630 if (pi->af==AF_INET) {
631 vlog(0x3, "[*] IPv4 PROTOCOL TYPE TCP:\n");
632 pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
633 pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 - (IP_HL(pi->ip4) * 4) - pi->eth_hlen);
634 pi->payload = (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4) + (TCP_OFFSET(pi->tcph) * 4));
635 } else if (pi->af==AF_INET6) {
636 vlog(0x3, "[*] IPv6 PROTOCOL TYPE TCP:\n");
637 pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
638 pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 - IP6_HEADER_LEN - pi->eth_hlen);
639 pi->payload = (pi->packet + pi->eth_hlen + IP6_HEADER_LEN + (TCP_OFFSET(pi->tcph)*4));
641 pi->proto = IP_PROTO_TCP;
642 pi->s_port = pi->tcph->src_port;
643 pi->d_port = pi->tcph->dst_port;
644 connection_tracking(pi);
645 //cx_track_simd_ipv4(pi);
646 if(config.payload)
647 dump_payload(pi->payload, (config.payload < pi->plen)?config.payload:pi->plen);
648 return;
651 void parse_tcp (packetinfo *pi)
653 update_asset(pi);
655 if (TCP_ISFLAGSET(pi->tcph, (TF_SYN))) {
656 if (!TCP_ISFLAGSET(pi->tcph, (TF_ACK))) {
657 if (IS_COSET(&config,CO_SYN)) {
658 vlog(0x3, "[*] - Got a SYN from a CLIENT: dst_port:%d\n",ntohs(pi->tcph->dst_port));
659 fp_tcp(pi, CO_SYN);
660 return;
662 } else {
663 if (IS_COSET(&config,CO_SYNACK)) {
664 vlog(0x3, "[*] Got a SYNACK from a SERVER: src_port:%d\n", ntohs(pi->tcph->src_port));
665 fp_tcp(pi, CO_SYNACK);
666 if (pi->sc != SC_SERVER)
667 reverse_pi_cxt(pi);
668 return;
673 // Check payload for known magic bytes that defines files!
675 if (pi->sc == SC_CLIENT && !ISSET_CXT_DONT_CHECK_CLIENT(pi)) {
676 if (IS_CSSET(&config,CS_TCP_CLIENT)
677 && !ISSET_DONT_CHECK_CLIENT(pi)) {
678 if (pi->af == AF_INET)
679 client_tcp4(pi, config.sig_client_tcp);
680 else
681 client_tcp6(pi, config.sig_client_tcp);
683 goto bastard_checks;
685 } else if (pi->sc == SC_SERVER && !ISSET_CXT_DONT_CHECK_SERVER(pi)) {
686 if (IS_CSSET(&config,CS_TCP_SERVER)
687 && !ISSET_DONT_CHECK_SERVICE(pi)) {
688 if (pi->af == AF_INET)
689 service_tcp4(pi, config.sig_serv_tcp);
690 else
691 service_tcp6(pi, config.sig_serv_tcp);
693 goto bastard_checks;
695 vlog(0x3, "[*] - NOT CHECKING TCP PACKAGE\n");
696 return;
698 bastard_checks:
699 if (IS_COSET(&config,CO_ACK)
700 && TCP_ISFLAGSET(pi->tcph, (TF_ACK))
701 && !TCP_ISFLAGSET(pi->tcph, (TF_SYN))
702 && !TCP_ISFLAGSET(pi->tcph, (TF_RST))
703 && !TCP_ISFLAGSET(pi->tcph, (TF_FIN))) {
704 vlog(0x3, "[*] Got a STRAY-ACK: src_port:%d\n",ntohs(pi->tcph->src_port));
705 fp_tcp(pi, CO_ACK);
706 return;
707 } else if (IS_COSET(&config,CO_FIN) && TCP_ISFLAGSET(pi->tcph, (TF_FIN))) {
708 vlog(0x3, "[*] Got a FIN: src_port:%d\n",ntohs(pi->tcph->src_port));
709 fp_tcp(pi, CO_FIN);
710 return;
711 } else if (IS_COSET(&config,CO_RST) && TCP_ISFLAGSET(pi->tcph, (TF_RST))) {
712 vlog(0x3, "[*] Got a RST: src_port:%d\n",ntohs(pi->tcph->src_port));
713 fp_tcp(pi, CO_RST);
714 return;
718 void prepare_udp (packetinfo *pi)
720 config.pr_s.udp_recv++;
721 if (pi->af==AF_INET) {
722 vlog(0x3, "[*] IPv4 PROTOCOL TYPE UDP:\n");
723 pi->udph = (udp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
724 pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
725 (IP_HL(pi->ip4) * 4) - pi->eth_hlen;
726 pi->payload = (pi->packet + pi->eth_hlen +
727 (IP_HL(pi->ip4) * 4) + UDP_HEADER_LEN);
729 } else if (pi->af==AF_INET6) {
730 vlog(0x3, "[*] IPv6 PROTOCOL TYPE UDP:\n");
731 pi->udph = (udp_header *) (pi->packet + pi->eth_hlen + + IP6_HEADER_LEN);
732 pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
733 IP6_HEADER_LEN - pi->eth_hlen;
734 pi->payload = (pi->packet + pi->eth_hlen +
735 IP6_HEADER_LEN + UDP_HEADER_LEN);
737 pi->proto = IP_PROTO_UDP;
738 pi->s_port = pi->udph->src_port;
739 pi->d_port = pi->udph->dst_port;
740 connection_tracking(pi);
741 //cx_track_simd_ipv4(pi);
742 if(config.payload)
743 dump_payload(pi->payload, (config.payload < pi->plen)?config.payload:pi->plen);
744 return;
747 void parse_udp (packetinfo *pi)
749 update_asset(pi);
750 //if (is_set_guess_upd_direction(config)) {
751 udp_guess_direction(pi); // fix DNS server transfers?
752 // Check for Passive DNS
753 static char ip_addr_s[INET6_ADDRSTRLEN];
754 u_ntop_src(pi, ip_addr_s);
755 if ( ntohs(pi->s_port) == 53 ) {
756 // For now - Proof of Concept! - Fix output way
757 if(config.cflags & CONFIG_PDNS)
758 dump_dns(pi->payload, pi->plen, stdout, "\n", ip_addr_s, pi->pheader->ts.tv_sec);
760 // if (IS_COSET(&config,CO_DNS) && (pi->sc == SC_SERVER && ntohs(pi->s_port) == 53)) passive_dns (pi);
762 if (IS_CSSET(&config,CS_UDP_SERVICES)) {
763 if (pi->af == AF_INET) {
765 if (!ISSET_DONT_CHECK_SERVICE(pi)||!ISSET_DONT_CHECK_CLIENT(pi)) {
766 // Check for UDP SERVICE
767 service_udp4(pi, config.sig_serv_udp);
769 // UPD Fingerprinting
770 if (IS_COSET(&config,CO_UDP)) fp_udp4(pi, pi->ip4, pi->udph, pi->end_ptr);
771 } else if (pi->af == AF_INET6) {
772 if (!ISSET_DONT_CHECK_SERVICE(pi)||!ISSET_DONT_CHECK_CLIENT(pi)) {
773 service_udp6(pi, config.sig_client_udp);
775 /* fp_udp(ip6, ttl, ipopts, len, id, ipflags, df); */
777 return;
778 } else {
779 vlog(0x3, "[*] - NOT CHECKING UDP PACKAGE\n");
780 return;
784 void prepare_icmp (packetinfo *pi)
786 config.pr_s.icmp_recv++;
787 if (pi->af==AF_INET) {
788 vlog(0x3, "[*] IPv4 PROTOCOL TYPE ICMP:\n");
789 pi->icmph = (icmp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
790 pi->proto = IP_PROTO_ICMP;
792 } else if (pi->af==AF_INET6) {
793 vlog(0x3, "[*] IPv6 PROTOCOL TYPE ICMP:\n");
794 pi->icmp6h = (icmp6_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
795 pi->proto = IP6_PROTO_ICMP;
797 pi->s_port = 0;
798 pi->d_port = 0;
800 * DO change ip6->hop_lmt to 0 or something
802 connection_tracking(pi);
803 return;
806 void parse_icmp (packetinfo *pi)
808 update_asset(pi);
810 if (IS_COSET(&config,CO_ICMP)) {
811 if (pi->cxt->check == 0x00) {
812 pi->cxt->check = 0x10; //for now - stop icmp fp quick
813 if (pi->af==AF_INET) {
814 fp_icmp4(pi, pi->ip4, pi->icmph, pi->end_ptr);
815 // could look for icmp spesific data in package abcde...
816 // service_icmp(*pi->ip4,*tcph
817 } else if (pi->af==AF_INET6) {
818 add_asset(pi);
819 fp_icmp6(pi, pi->ip6, pi->icmp6h, pi->end_ptr);
821 } else {
822 vlog(0x3, "[*] - NOT CHECKING ICMP PACKAGE\n");
827 void prepare_other (packetinfo *pi)
829 config.pr_s.othert_recv++;
830 if (pi->af==AF_INET) {
831 vlog(0x3, "[*] IPv4 PROTOCOL TYPE OTHER: %d\n",pi->ip4->ip_p);
833 } else if (pi->af==AF_INET6) {
834 vlog(0x3, "[*] IPv6 PROTOCOL TYPE OTHER: %d\n",pi->ip6->next);
837 pi->s_port = 0;
838 pi->d_port = 0;
839 connection_tracking(pi);
840 return;
843 void parse_other (packetinfo *pi)
845 update_asset(pi);
847 if (pi->cxt->check == 0x00) {
848 if (IS_COSET(&config,CO_OTHER)) {
849 pi->cxt->check = 0x01; // no more checks
850 // service_other(*pi->ip4,*transporth);
851 // fp_other(pi->ipX, ttl, ipopts, len, id, ipflags, df);
852 } else {
853 vlog(0x3, "[*] - NOT CHECKING *OTHER* PACKAGE\n");
858 void udp_guess_direction(packetinfo *pi)
860 /* Stupid hack :( for DNS/port 53 */
861 if (ntohs(pi->d_port) == 53) {
862 if (pi->sc == SC_CLIENT) return;
863 else pi->sc = SC_CLIENT;
865 } else if (ntohs(pi->s_port) == 53) {
866 if (pi->sc == SC_SERVER) return;
867 else pi->sc = SC_SERVER;
871 int parse_network (char *net_s, struct in6_addr *network)
873 int type;
874 char *t;
875 if (NULL != (t = strchr(net_s, ':'))) {
876 type = AF_INET6;
877 if (!inet_pton(type, net_s, network)) {
878 perror("parse_nets6");
879 return -1;
881 dlog("Network6 %-36s \t -> %08x:%08x:%08x:%08x\n",
882 net_s,
883 IP6ADDR(network)
885 } else {
886 type = AF_INET;
887 if (!inet_pton(type, net_s, &IP4ADDR(network))) {
888 perror("parse_nets");
889 return -1;
891 dlog("Network4 %16s \t-> 0x%08x\n", net_s, IP4ADDR(network));
893 return type;
896 int parse_netmask (char *f, int type, struct in6_addr *netmask)
898 char *t;
899 uint32_t mask;
900 char output[MAX_NETS];
901 // parse netmask into host order
902 if (type == AF_INET && (t = strchr(f, '.')) > f && t-f < 4) {
903 // full ipv4 netmask : dotted quads
904 inet_pton(type, f, &IP4ADDR(netmask));
905 dlog("mask 4 %s \t-> 0x%08x\n", f, IP4ADDR(netmask));
906 } else if (type == AF_INET6 && NULL != (t = strchr(f, ':'))) {
907 // full ipv6 netmasÄž
908 dlog("mask 6 %s\n", f);
909 inet_pton(type, f, netmask);
910 } else {
911 // cidr form
912 sscanf(f, "%u", &mask);
913 dlog("cidr %u \t-> ", mask);
914 if (type == AF_INET) {
915 uint32_t shift = 32 - mask;
916 if (mask)
917 IP4ADDR(netmask) = ntohl( ((unsigned int)-1 >> shift)<< shift);
918 else
919 IP4ADDR(netmask) = 0;
921 dlog("0x%08x\n", IP4ADDR(netmask));
922 } else if (type == AF_INET6) {
923 //mask = 128 - mask;
924 int j = 0;
925 memset(netmask, 0, sizeof(struct in6_addr));
927 while (mask > 8) {
928 netmask->s6_addr[j++] = 0xff;
929 mask -= 8;
931 if (mask > 0) {
932 netmask->s6_addr[j] = -1 << (8 - mask);
934 inet_ntop(type, &IP4ADDR(netmask), output, MAX_NETS);
935 dlog("mask: %s\n", output);
936 // pcap packets are in host order.
937 IP6ADDR0(netmask) = ntohl(IP6ADDR0(netmask));
938 IP6ADDR1(netmask) = ntohl(IP6ADDR1(netmask));
939 IP6ADDR2(netmask) = ntohl(IP6ADDR2(netmask));
940 IP6ADDR3(netmask) = ntohl(IP6ADDR3(netmask));
944 return 0;
947 /* parse strings of the form ip/cidr or ip/mask like:
948 * "10.10.10.10/255.255.255.128,10.10.10.10/25" and
949 * "dead:be:eef2:1aa::b5ff:fe96:37a2/64,..."
951 * an IPv6 address is 8 x 4 hex digits. missing digits are padded with zeroes.
953 void parse_nets(const char *s_net, fmask *network)
955 /* f -> for processing
956 * p -> frob pointer
957 * t -> to pointer */
958 char *f, *p, *snet;
959 int type, len, i = 0;
960 struct in6_addr network6, netmask6;
962 // snet is a mutable copy of the args,freed @ nets_end
963 len = strlen(s_net);
964 //snet = calloc(1, len);
965 snet = calloc(1, (len + 1)); /* to have \0 too :-) */
966 strncpy(snet, s_net, len);
967 f = snet;
968 while (f && 0 != (p = strchr(f, '/'))) {
969 // convert network address
970 *p = '\0';
971 type = parse_network(f, &network6);
972 if (type != AF_INET && type != AF_INET6) {
973 perror("parse_network");
974 goto nets_end;
976 // convert netmask
977 f = p + 1;
978 p = strchr(f, ',');
979 if (p) {
980 *p = '\0';
982 parse_netmask(f, type, &netmask6);
984 // poke in the gathered information
985 switch (type) {
986 case AF_INET:
987 case AF_INET6:
988 network[i].addr = network6;
989 network[i].mask = netmask6;
990 network[i].type = type;
991 break;
993 default:
994 fprintf(stderr, "parse_nets: invalid address family!\n");
995 goto nets_end;
998 nets = ++i;
1000 if (i > MAX_NETS) {
1001 elog("Max networks reached, stopped parsing at %d nets.\n", i-1);
1002 goto nets_end;
1006 // continue parsing at p, which might point to another network range
1007 f = p;
1008 if(p) f++;
1010 nets_end:
1011 free(snet);
1012 return;
1015 void game_over()
1018 if (inpacket == 0) {
1019 end_sessions(); /* Need to have correct human output when reading -r pcap */
1020 //cxt_write_all(); /* redundant ? see end_all_sessions(); */
1021 clear_asset_list();
1022 end_all_sessions();
1023 del_known_services();
1024 del_signature_lists();
1025 unload_tcp_sigs();
1026 end_logging();
1027 if(!ISSET_CONFIG_QUIET(config)){
1028 print_prads_stats();
1029 if(!config.pcap_file)
1030 print_pcap_stats();
1032 if (config.handle != NULL) pcap_close(config.handle);
1033 free_config();
1034 olog("\n[*] prads ended.\n");
1035 exit(0);
1037 intr_flag = 1;
1040 void check_interrupt()
1043 if (intr_flag == 1) {
1044 game_over();
1045 } else if (intr_flag == 2) {
1046 update_asset_list();
1047 } else if (intr_flag == 3) {
1048 set_end_sessions();
1049 } else {
1050 intr_flag = 0;
1054 void set_end_sessions()
1056 intr_flag = 3;
1058 if (inpacket == 0) {
1059 tstamp = time(NULL);
1060 end_sessions();
1061 /* if no cxtracking is turned on - dont log to disk */
1062 /* if (log_cxt == 1) log_expired_cxt(); */
1063 /* if no asset detection is turned on - dont log to disk! */
1064 /* if (log_assets == 1) update_asset_list(); */
1065 update_asset_list();
1066 intr_flag = 0;
1067 alarm(SIG_ALRM);
1071 void print_prads_stats()
1073 extern uint64_t cxtrackerid; // cxt.c
1074 olog("-- prads:\n");
1075 olog("-- Total packets received from libpcap :%12u\n",config.pr_s.got_packets);
1076 olog("-- Total Ethernet packets received :%12u\n",config.pr_s.eth_recv);
1077 olog("-- Total VLAN packets received :%12u\n",config.pr_s.vlan_recv);
1078 olog("-- Total ARP packets received :%12u\n",config.pr_s.arp_recv);
1079 olog("-- Total IPv4 packets received :%12u\n",config.pr_s.ip4_recv);
1080 olog("-- Total IPv6 packets received :%12u\n",config.pr_s.ip6_recv);
1081 olog("-- Total Other link packets received :%12u\n",config.pr_s.otherl_recv);
1082 olog("-- Total IPinIPv4 packets received :%12u\n",config.pr_s.ip4ip_recv);
1083 olog("-- Total IPinIPv6 packets received :%12u\n",config.pr_s.ip6ip_recv);
1084 olog("-- Total GRE packets received :%12u\n",config.pr_s.gre_recv);
1085 olog("-- Total TCP packets received :%12u\n",config.pr_s.tcp_recv);
1086 olog("-- Total UDP packets received :%12u\n",config.pr_s.udp_recv);
1087 olog("-- Total ICMP packets received :%12u\n",config.pr_s.icmp_recv);
1088 olog("-- Total Other transport packets received :%12u\n",config.pr_s.othert_recv);
1089 olog("--\n");
1090 olog("-- Total sessions tracked :%12lu\n", cxtrackerid);
1091 olog("-- Total assets detected :%12u\n",config.pr_s.assets);
1092 olog("-- Total TCP OS fingerprints detected :%12u\n",config.pr_s.tcp_os_assets);
1093 olog("-- Total UDP OS fingerprints detected :%12u\n",config.pr_s.udp_os_assets);
1094 olog("-- Total ICMP OS fingerprints detected :%12u\n",config.pr_s.icmp_os_assets);
1095 olog("-- Total DHCP OS fingerprints detected :%12u\n",config.pr_s.dhcp_os_assets);
1096 olog("-- Total TCP service assets detected :%12u\n",config.pr_s.tcp_services);
1097 olog("-- Total TCP client assets detected :%12u\n",config.pr_s.tcp_clients);
1098 olog("-- Total UDP service assets detected :%12u\n",config.pr_s.udp_services);
1099 olog("-- Total UDP client assets detected :%12u\n",config.pr_s.udp_clients);
1103 static void usage()
1105 olog("USAGE:\n");
1106 olog(" $ prads [options]\n");
1107 olog("\n");
1108 olog(" OPTIONS:\n");
1109 olog("\n");
1110 olog(" -i <iface> Network device <iface> (default: eth0).\n");
1111 olog(" -r <file> Read pcap <file>.\n");
1112 olog(" -c <file> Read config from <file>\n");
1113 olog(" -b <filter> Apply Berkeley packet filter <filter>.\n");
1114 olog(" -u <user> Run as user <user>.\n");
1115 olog(" -g <group> Run as group <group>.\n");
1116 olog(" -a <nets> Specify home nets (eg: '192.168.0.0/25,10.0.0.0/255.0.0.0').\n");
1117 olog(" -D Enables daemon mode.\n");
1118 //olog(" -d to logdir\n");
1119 olog(" -p <pidfile> Name of pidfile - inside chroot\n");
1120 olog(" -l <file> Log assets to <file> (default: '%s')\n", config.assetlog);
1121 olog(" -f <FIFO> Log assets to <FIFO>\n");
1122 olog(" -C <dir> Chroot into <dir> before dropping privs.\n");
1123 olog(" -XFRMSAK Flag picker: X - clear flags, F:FIN, R:RST, M:MAC, S:SYN, A:ACK, K:SYNACK\n");
1124 olog(" -UTtI Service checks: U:UDP, T:TCP-server, I:ICMP, t:TCP-cLient\n");
1125 olog(" -s <snaplen> Dump <snaplen> bytes of each payload.\n");
1126 olog(" -v Verbose output - repeat for more verbosity.\n");
1127 olog(" -q Quiet - try harder not to produce output.\n");
1128 olog(" -O Connection tracking [O]utput - per-packet!\n");
1129 olog(" -x Conne[x]ion tracking output - New, expired and ended.\n");
1130 olog(" -Z Passive DNS (Experimental).\n");
1131 olog(" -h This help message.\n");
1135 extern int optind, opterr, optopt; // getopt()
1137 /* magic main */
1138 int main(int argc, char *argv[])
1140 int32_t rc = 0;
1141 int ch = 0, verbose_already = 0;
1143 vlog(2, "%08x =? %08x, endianness: %s\n\n", 0xdeadbeef, ntohl(0xdeadbeef), (0xdead == ntohs(0xdead)?"big":"little") );
1145 memset(&config, 0, sizeof(globalconfig));
1146 set_default_config_options();
1147 bstring pconfile = bfromcstr(CONFDIR "prads.conf");
1148 //parse_config_file(pconfile);
1149 //bdestroy (pconfile);
1151 inpacket = gameover = intr_flag = 0;
1153 signal(SIGTERM, game_over);
1154 signal(SIGINT, game_over);
1155 signal(SIGQUIT, game_over);
1156 signal(SIGALRM, set_end_sessions);
1157 //signal(SIGALRM, game_over); // Use this to debug segfault when exiting
1159 // do first-pass args parse for commandline-passed config file
1160 opterr = 0;
1161 #define ARGS "C:c:b:d:Dg:hi:p:r:P:u:va:l:f:qtxs:OXFRMSAKUTIZt"
1162 while ((ch = getopt(argc, argv, ARGS)) != -1)
1163 switch (ch) {
1164 case 'c':
1165 pconfile = bfromcstr(optarg);
1166 break;
1167 case 'v':
1168 config.verbose++;
1169 break;
1170 case 'h':
1171 usage();
1172 exit(0);
1173 default:
1174 break;
1177 if(config.verbose)
1178 verbose_already = 1;
1180 parse_config_file(pconfile);
1182 // reset verbosity before 2nd coming, but only if set on cli
1183 if(verbose_already)
1184 config.verbose = 0;
1185 optind = 1;
1187 while ((ch = getopt(argc, argv, ARGS)) != -1)
1188 switch (ch) {
1189 case 'a':
1190 if(strlen(optarg) == 0)
1191 config.s_net = DEFAULT_NETS;
1192 else
1193 config.s_net = strdup(optarg);
1194 break;
1195 case 'c':
1196 pconfile = bfromcstr(optarg);
1197 break;
1198 case 'C':
1199 config.chroot_dir = strdup(optarg);
1200 break;
1201 case 'i':
1202 config.dev = strdup(optarg);
1203 break;
1204 case 'r':
1205 config.pcap_file = strdup(optarg);
1206 break;
1207 case 'b':
1208 config.bpff = strdup(optarg);
1209 break;
1210 case 'v':
1211 config.verbose++;
1212 config.cflags |= CONFIG_VERBOSE;
1213 break;
1214 case 'd':
1215 config.dpath = strdup(optarg);
1216 break;
1217 case 'h':
1218 usage();
1219 exit(0);
1220 break;
1221 case 'D':
1222 config.daemon_flag = 1;
1223 break;
1224 case 'u':
1225 config.user_name = strdup(optarg);
1226 config.drop_privs_flag = 1;
1227 break;
1228 case 'g':
1229 config.group_name = strdup(optarg);
1230 config.drop_privs_flag = 1;
1231 break;
1232 case 'p':
1233 config.pidfile = strdup(optarg);
1234 break;
1235 case 'l':
1236 config.assetlog = strdup(optarg);
1237 break;
1238 case 'f':
1239 config.fifo = strdup(optarg);
1240 break;
1241 case 's':
1242 config.payload = strtol(optarg, NULL, 0);
1243 break;
1244 case 'q':
1245 config.cflags |= CONFIG_QUIET;
1246 break;
1247 case 'O':
1248 config.cflags |= CONFIG_CONNECT;
1249 break;
1250 case 'Z':
1251 config.cflags |= CONFIG_PDNS;
1252 break;
1253 case 'x':
1254 config.cflags |= CONFIG_CXWRITE;
1255 break;
1256 case 'X':
1257 config.ctf = 0;
1258 config.cof = 0;
1259 break;
1260 case 'F':
1261 config.ctf |= CO_FIN;
1262 break;
1263 case 'R':
1264 config.ctf |= CO_RST;
1265 break;
1266 case 'M':
1267 config.cof |= CS_MAC;
1268 config.cof |= CS_ARP;
1269 break;
1270 case 'S':
1271 config.ctf |= CO_SYN;
1272 break;
1273 case 'A':
1274 config.ctf |= CO_ACK;
1275 break;
1276 case 'K':
1277 config.ctf |= CO_SYNACK;
1278 break;
1279 case 'U':
1280 config.cof |= CS_UDP_SERVICES;
1281 break;
1282 case 'T':
1283 config.cof |= CS_TCP_SERVER;
1284 break;
1285 case 'I':
1286 config.cof |= CS_ICMP;
1287 break;
1288 case 't':
1289 config.cof |= CS_TCP_CLIENT;
1290 break;
1291 case '?':
1292 elog("unrecognized argument: '%c'\n", optopt);
1293 break;
1294 default:
1295 elog("Did not recognize argument '%c'\n", ch);
1298 bdestroy (pconfile);
1299 // we're done parsing configs - now initialize prads
1301 if(config.verbose){
1302 rc = init_logging(LOG_STDOUT, NULL, config.verbose);
1303 if(rc) perror("Logging to standard out failed!");
1306 if(config.assetlog) {
1307 olog("logging to file '%s'\n", config.assetlog);
1308 rc = init_logging(LOG_FILE, config.assetlog, config.verbose);
1309 if(rc) perror("Logging to file failed!");
1311 if(config.fifo) {
1312 olog("logging to FIFO '%s'\n", config.fifo);
1313 rc = init_logging(LOG_FIFO, config.fifo, config.verbose);
1314 if(rc) perror("Logging to fifo failed!");
1316 if(config.s_net){
1317 parse_nets(config.s_net, network);
1319 olog("[*] Loading fingerprints:\n");
1320 /* helper macro to avoid duplicate code */
1321 #define load_foo(func, conf, flag, file, hash, len, dump) \
1322 if(config. conf & flag) { \
1323 int _rc; \
1324 olog(" %-11s %s\n", # flag, (config. file)); \
1325 _rc = func (config. file, & config. hash, config. len); \
1326 if(_rc) perror( #flag " load failed!"); \
1327 else if(config.verbose > 1) { \
1328 printf("[*] Dumping " #flag " signatures:\n"); \
1329 dump (config. hash, config. len); \
1330 printf("[*] " #flag " signature dump ends.\n"); \
1334 load_foo(load_mac , cof, CS_MAC, sig_file_mac, sig_mac, mac_hashsize, dump_macs);
1335 load_foo(load_sigs, ctf, CO_SYN, sig_file_syn, sig_syn, sig_hashsize, dump_sigs);
1336 load_foo(load_sigs, ctf, CO_SYNACK, sig_file_synack, sig_synack, sig_hashsize, dump_sigs);
1337 load_foo(load_sigs, ctf, CO_ACK, sig_file_ack, sig_ack, sig_hashsize, dump_sigs);
1338 load_foo(load_sigs, ctf, CO_FIN, sig_file_fin, sig_fin, sig_hashsize, dump_sigs);
1339 load_foo(load_sigs, ctf, CO_RST, sig_file_rst, sig_rst, sig_hashsize, dump_sigs);
1341 load_foo(load_servicefp_file, cof, CS_TCP_SERVER, sig_file_serv_tcp, sig_serv_tcp, sig_hashsize, dump_sig_service);
1342 load_foo(load_servicefp_file, cof, CS_UDP_SERVICES, sig_file_serv_udp, sig_serv_udp, sig_hashsize, dump_sig_service);
1343 load_foo(load_servicefp_file, cof, CS_TCP_CLIENT, sig_file_cli_tcp, sig_client_tcp, sig_hashsize, dump_sig_service);
1344 init_services();
1346 olog("\n[*] Running prads %s\n", VERSION);
1347 olog(" Using %s\n", pcap_lib_version());
1348 olog(" Using PCRE version %s\n", pcre_version());
1350 //if (config.verbose) display_config();
1351 display_config();
1353 if (config.pcap_file) {
1354 /* Read from PCAP file specified by '-r' switch. */
1355 olog("[*] Reading from file %s\n", config.pcap_file);
1356 if (!(config.handle = pcap_open_offline(config.pcap_file, config.errbuf))) {
1357 olog("[*] Unable to open %s. (%s)", config.pcap_file, config.errbuf);
1360 } else {
1362 /* * look up an available device if non specified */
1363 if (config.dev == 0x0)
1364 config.dev = pcap_lookupdev(config.errbuf);
1365 olog("[*] Device: %s\n", config.dev);
1367 if ((config.handle = pcap_open_live(config.dev, SNAPLENGTH, 1, 500, config.errbuf)) == NULL) {
1368 olog("[*] Error pcap_open_live: %s \n", config.errbuf);
1369 exit(1);
1371 /* * B0rk if we see an error... */
1372 if (strlen(config.errbuf) > 0) {
1373 elog("[*] Error errbuf: %s \n", config.errbuf);
1374 exit(1);
1377 if(config.chroot_dir){
1378 olog("[*] Chrooting to dir '%s'..\n", config.chroot_dir);
1379 if(set_chroot()){
1380 elog("[!] failed to chroot\n");
1381 exit(1);
1385 if (config.drop_privs_flag) {
1386 olog("[*] Dropping privs...\n");
1387 drop_privs();
1390 if (config.daemon_flag) {
1391 if (!is_valid_path(config.pidfile))
1392 elog("[*] Unable to create pidfile '%s'\n", config.pidfile);
1393 openlog("prads", LOG_PID | LOG_CONS, LOG_DAEMON);
1394 olog("[*] Daemonizing...\n\n");
1395 daemonize(NULL);
1400 bucket_keys_NULL();
1401 alarm(SIG_ALRM);
1403 /** segfaults on empty pcap! */
1404 if ((pcap_compile(config.handle, &config.cfilter, config.bpff, 1, config.net_mask)) == -1) {
1405 olog("[*] Error pcap_compile user_filter: %s\n", pcap_geterr(config.handle));
1406 exit(1);
1409 if (pcap_setfilter(config.handle, &config.cfilter)) {
1410 olog("[*] Unable to set pcap filter! %s", pcap_geterr(config.handle));
1413 cxt_init();
1414 olog("[*] Sniffing...\n\n");
1415 pcap_loop(config.handle, -1, got_packet, NULL);
1417 game_over();
1418 //pcap_close(config.handle);
1419 return (0);
1422 //void free_config()
1424 // if (config.dev != NULL) free (config.dev);
1425 // if (config.cfilter.bf_insns != NULL) free (config.cfilter.bf_insns);