code cleanup: drastically reduce the amout of globals and put code in the right places
[prads.git] / src / prads.c
blob6eeb07261187d8f4cee05114fec318ecd0c886c3
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 "output-plugins/log_init.h"
44 #include "output-plugins/log.h"
46 #ifndef CONFDIR
47 #define CONFDIR "/etc/prads/"
48 #endif
50 /* G L O B A L S *** (or candidates for refactoring, as we say)***********/
51 globalconfig config;
52 time_t tstamp;
53 servicelist *services[MAX_PORTS];
54 signature *sig_serv_tcp = NULL;
55 signature *sig_serv_udp = NULL;
56 signature *sig_client_tcp = NULL;
57 signature *sig_client_udp = NULL;
58 int inpacket, gameover, intr_flag;
59 int nets = 1;
61 struct fmask network[MAX_NETS];
63 // static strings for comparison
64 // - this is lame and should be a flag!
65 struct tagbstring tUNKNOWN = bsStatic("unknown");
66 bstring UNKNOWN = & tUNKNOWN;
68 /* I N T E R N A L P R O T O T Y P E S ***********************************/
69 static void usage();
70 void check_vlan (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_tcp (packetinfo *pi);
77 void prepare_udp (packetinfo *pi);
78 void prepare_icmp (packetinfo *pi);
79 void prepare_gre (packetinfo *pi);
80 void prepare_greip (packetinfo *pi);
81 void prepare_other (packetinfo *pi);
82 void parse_eth (packetinfo *pi);
83 void parse_ip4 (packetinfo *pi);
84 void parse_ip6 (packetinfo *pi);
85 void parse_tcp (packetinfo *pi);
86 void parse_udp (packetinfo *pi);
87 void parse_icmp (packetinfo *pi);
88 void parse_gre (packetinfo *pi);
89 void parse_other (packetinfo *pi);
90 void parse_arp (packetinfo *pi);
91 int parse_network (char *net_s, struct in6_addr *network);
92 int parse_netmask (char *f, int type, struct in6_addr *netmask);
93 void parse_nets(const char *s_net, struct fmask *network);
95 void udp_guess_direction(packetinfo *pi);
96 void set_pkt_end_ptr (packetinfo *pi);
97 inline int filter_packet(const int af, void *ip);
99 /* F U N C T I O N S ********************************************************/
101 void got_packet(u_char * useless, const struct pcap_pkthdr *pheader,
102 const u_char * packet)
104 config.pr_s.got_packets++;
105 packetinfo pstruct = {0};
106 packetinfo *pi = &pstruct;
107 // memset(&pi, 0, sizeof(packetinfo));
108 //pi = (packetinfo *) calloc(1, sizeof(packetinfo));
109 pi->our = 1;
110 pi->packet = packet;
111 pi->pheader = pheader;
112 set_pkt_end_ptr (pi);
113 tstamp = pi->pheader->ts.tv_sec; // Global
114 if (intr_flag != 0) {
115 check_interrupt();
117 inpacket = 1;
118 prepare_eth(pi);
119 check_vlan(pi);
120 parse_eth(pi);
122 if (pi->eth_type == ETHERNET_TYPE_IP) {
123 prepare_ip4(pi);
124 parse_ip4(pi);
125 goto packet_end;
126 } else if (pi->eth_type == ETHERNET_TYPE_IPV6) {
127 prepare_ip6(pi);
128 parse_ip6(pi);
129 goto packet_end;
130 } else if (pi->eth_type == ETHERNET_TYPE_ARP) {
131 parse_arp(pi);
132 goto packet_end;
134 config.pr_s.otherl_recv++;
135 vlog(0x3, "[*] ETHERNET TYPE : %x\n",pi->eth_hdr->eth_ip_type);
136 packet_end:
137 #ifdef DEBUG
138 if (!pi->our) vlog(0x3, "Not our network packet. Tracked, but not logged.\n");
139 #endif
140 inpacket = 0;
141 //free(pi);
142 return;
145 /* does this ip belong to our network? do we care about the packet?
147 * unfortunately pcap sends us packets in host order
148 * Return value: boolean
150 inline int filter_packet(const int af, void *ipptr)
151 //const struct in6_addr *ip_s)
153 ip6v ip_vec;
154 ip6v t;
156 int i, our = 0;
157 char output[MAX_NETS];
158 switch (af) {
159 case AF_INET:
161 uint32_t *ip = (uint32_t *) ipptr;
162 for (i = 0; i < MAX_NETS && i < nets; i++) {
163 if (network[i].type != AF_INET)
164 continue;
165 #ifdef DEBUG_PACKET
166 inet_ntop(af, &network[i].addr.__u6_addr.__u6_addr32[0], output, MAX_NETS);
167 vlog(0x2, "Filter: %s\n", output);
168 inet_ntop(af, &network[i].mask.__u6_addr.__u6_addr32[0], output, MAX_NETS);
169 vlog(0x2, "mask: %s\n", output);
170 inet_ntop(af, ip, output, MAX_NETS);
171 vlog(0x2, "ip: %s\n", output);
172 #endif
173 if((*ip & IP4ADDR(&network[i].mask))
174 == IP4ADDR(&network[i].addr)){
175 our = 1;
176 break;
180 break;
181 case AF_INET6:
183 /* 32-bit comparison of ipv6 nets.
184 * can do better here by using 64-bit or SIMD instructions
187 * PS: use same code for ipv4 - 0 bytes and SIMD doesnt care*/
189 ip_vec.ip6 = *((struct in6_addr *)ipptr);
190 for (i = 0; i < MAX_NETS && i < nets; i++) {
191 if(network[i].type != AF_INET6)
192 continue;
193 #ifdef DEBUG_PACKET
194 inet_ntop(af, &network[i].addr, output, MAX_NETS);
195 dlog("net: %s\n", output);
196 inet_ntop(af, &network[i].mask, output, MAX_NETS);
197 dlog("mask: %s\n", output);
198 inet_ntop(af, &PI_IP6SRC(pi), output, MAX_NETS);
199 dlog("ip: %s\n", output);
200 #endif
201 if (network[i].type == AF_INET6) {
202 #if(1)
203 /* apologies for the uglyness */
204 #ifdef HAVE_SSE2
205 #define compare128(x,y) __builtin_ia32_pcmpeqd128((x), (y))
206 // the builtin is only available on sse2!
207 t.v = __builtin_ia32_pcmpeqd128(
208 ip_vec.v & network[i].mask_v,
209 network[i].addr_v);
210 if (t.i[0] & t.i[1])
211 #else
212 #define compare128(x,y) memcmp(&(x),&(y),16)
213 t.v = ip_vec.v & network[i].mask_v;
214 // xor(a,b) == 0 iff a==b
215 if (!( (t.i[0] ^ network[i].addr64[0]) &
216 (t.i[1] ^ network[i].addr64[1]) ))
217 #endif
219 our = 1;
220 break;
223 #else
224 if ((ip_s.__u6_addr.__u6_addr32[0] & network[i].mask.__u6_addr.__u6_addr32[0])
225 == network[i].addr.__u6_addr.__u6_addr32[0]
226 && (ip_s.__u6_addr.__u6_addr32[1] & network[i].mask.__u6_addr.__u6_addr32[1])
227 == network[i].addr.__u6_addr.__u6_addr32[1]
228 && (ip_s.__u6_addr.__u6_addr32[2] & network[i].mask.__u6_addr.__u6_addr32[2])
229 == network[i].addr.__u6_addr.__u6_addr32[2]
230 && (ip_s.__u6_addr.__u6_addr32[3] & network[i].mask.__u6_addr.__u6_addr32[3])
231 == network[i].addr.__u6_addr.__u6_addr32[3]) {
232 our = 1;
233 break;
235 #endif
239 break;
240 default:
241 fprintf(stderr,
242 "non-ip packets of type %d aren't filtered by netmask yet\n", af);
243 our = 1;
245 #ifdef DEBUG
246 if (af == AF_INET6){
247 inet_ntop(af, (struct in6addr*) ipptr, output, MAX_NETS);
248 }else{
249 inet_ntop(af, (uint32_t*)ipptr, output, MAX_NETS);
251 if (our){
252 vlog(0x2, "Address %s is in our network.\n", output);
253 } else {
254 vlog(0x2, "Address %s is not our network.\n", output);
256 #endif
257 return our;
260 void prepare_eth (packetinfo *pi)
262 if (pi->packet + ETHERNET_HEADER_LEN > pi->end_ptr) return;
263 config.pr_s.eth_recv++;
264 pi->eth_hdr = (ether_header *) (pi->packet);
265 pi->eth_type = ntohs(pi->eth_hdr->eth_ip_type);
266 pi->eth_hlen = ETHERNET_HEADER_LEN;
267 return;
270 void parse_eth (packetinfo *pi)
272 if (!IS_CSSET(&config,CS_MAC)) return;
273 /* update_asset_arp(pi->eth_hdr->ether_src, pi);
275 uint8_t *mac = pi->eth_hdr->ether_src;
277 * XXX: how is mac matching supposed to work?
278 * answer: lookup macs on pertinent frames
279 * and hash into mac asset database
280 * mac assets are like regular assets,
281 * and contain references to other assets they involve
282 if(! pi->asset->mace)
283 mac_entry *match = match_mac(config.sig_mac, mac, 48);
284 //pi->asset->mace ;
286 print_mac(mac);
287 olog("mac matched: %s\n", match->vendor);
289 // call update_asset_mac or smth?
290 // stats?
291 //config.pr_s.eth_recv++;
293 return;
297 void check_vlan (packetinfo *pi)
299 if (pi->eth_type == ETHERNET_TYPE_8021Q) {
300 vlog(0x3, "[*] ETHERNET TYPE 8021Q\n");
301 config.pr_s.vlan_recv++;
302 pi->vlan = pi->eth_hdr->eth_8_vid;
303 pi->eth_type = ntohs(pi->eth_hdr->eth_8_ip_type);
304 pi->eth_hlen += 4;
306 /* This is b0rked - kwy and ebf fix */
307 } else if (pi->eth_type ==
308 (ETHERNET_TYPE_802Q1MT | ETHERNET_TYPE_802Q1MT2 |
309 ETHERNET_TYPE_802Q1MT3 | ETHERNET_TYPE_8021AD)) {
310 vlog(0x3, "[*] ETHERNET TYPE 802Q1MT\n");
311 pi->mvlan = pi->eth_hdr->eth_82_mvid;
312 pi->eth_type = ntohs(pi->eth_hdr->eth_82_ip_type);
313 pi->eth_hlen += 8;
315 return;
318 void prepare_ip4 (packetinfo *pi)
320 config.pr_s.ip4_recv++;
321 pi->af = AF_INET;
322 pi->ip4 = (ip4_header *) (pi->packet + pi->eth_hlen);
323 pi->packet_bytes = (pi->ip4->ip_len - (IP_HL(pi->ip4) * 4));
325 pi->our = filter_packet(pi->af, &PI_IP4SRC(pi));
326 vlog(0x3, "Got %s IPv4 Packet...\n", (pi->our?"our":"foregin"));
327 return;
330 void parse_ip4 (packetinfo *pi)
332 switch (pi->ip4->ip_p) {
333 case IP_PROTO_TCP:
334 prepare_tcp(pi);
335 if (!pi->our)
336 break;
337 parse_tcp(pi);
338 break;
339 case IP_PROTO_UDP:
340 prepare_udp(pi);
341 if (!pi->our)
342 break;
343 parse_udp(pi);
344 break;
345 case IP_PROTO_ICMP:
346 prepare_icmp(pi);
347 if (!pi->our)
348 break;
349 parse_icmp(pi);
350 break;
351 case IP_PROTO_IP4:
352 prepare_ip4ip(pi);
353 break;
354 case IP_PROTO_IP6:
355 prepare_ip4ip(pi);
356 break;
357 case IP_PROTO_GRE:
358 prepare_gre(pi);
359 parse_gre(pi);
360 break;
362 default:
363 prepare_other(pi);
364 if (!pi->our)
365 break;
366 parse_other(pi);
368 return;
371 void prepare_gre (packetinfo *pi)
373 config.pr_s.gre_recv++;
374 if((pi->pheader->caplen - pi->eth_hlen) < GRE_HDR_LEN) {
375 return;
377 if (pi->af == AF_INET) {
378 vlog(0x3, "[*] IPv4 PROTOCOL TYPE GRE:\n");
379 pi->greh = (gre_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
380 } else if (pi->af == AF_INET6) {
381 vlog(0x3, "[*] IPv6 PROTOCOL TYPE GRE:\n");
382 pi->greh = (gre_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
384 pi->proto = IP_PROTO_GRE;
385 return;
388 void parse_gre (packetinfo *pi)
390 uint16_t gre_header_len = GRE_HDR_LEN;
391 gre_sre_header *gsre = NULL;
392 uint16_t len = (pi->pheader->caplen - pi->eth_hlen);
394 update_asset(pi);
396 switch (GRE_GET_VERSION(pi->greh))
398 case GRE_VERSION_0:
399 /* Adjust header length based on content */
400 if (GRE_FLAG_ISSET_KY(pi->greh))
401 gre_header_len += GRE_KEY_LEN;
402 if (GRE_FLAG_ISSET_SQ(pi->greh))
403 gre_header_len += GRE_SEQ_LEN;
404 if (GRE_FLAG_ISSET_CHKSUM(pi->greh) || GRE_FLAG_ISSET_ROUTE(pi->greh))
405 gre_header_len += GRE_CHKSUM_LEN + GRE_OFFSET_LEN;
406 if (gre_header_len > len) {
407 return;
409 if (GRE_FLAG_ISSET_ROUTE(pi->greh))
411 gsre = (gre_sre_header *)(pi->greh + gre_header_len);
412 if (gsre == NULL) return;
413 while (1)
415 if ((gre_header_len+GRE_SRE_HDR_LEN) > len) {
416 break;
418 gre_header_len += GRE_SRE_HDR_LEN;
420 if (gsre != NULL && (ntohs(gsre->af) == 0) && (gsre->sre_length == 0))
421 break;
423 gre_header_len += gsre->sre_length;
424 gsre = (gre_sre_header *)(pi->greh + gre_header_len);
425 if (gsre == NULL)
426 return;
429 break;
431 case GRE_VERSION_1:
432 /* GRE version 1 doenst support the fields below RFC 1701 */
433 if (GRE_FLAG_ISSET_CHKSUM(pi->greh)) {
434 return;
436 if (GRE_FLAG_ISSET_ROUTE(pi->greh)) {
437 return;
439 if (GRE_FLAG_ISSET_SSR(pi->greh)) {
440 return;
442 if (GRE_FLAG_ISSET_RECUR(pi->greh)) {
443 return;
445 if (GREV1_FLAG_ISSET_FLAGS(pi->greh)) {
446 return;
448 if (GRE_GET_PROTO(pi->greh) != GRE_PROTO_PPP) {
449 return;
451 if (!(GRE_FLAG_ISSET_KY(pi->greh))) {
452 return;
455 gre_header_len += GRE_KEY_LEN;
457 /* Adjust header length based on content */
458 if (GRE_FLAG_ISSET_SQ(pi->greh))
459 gre_header_len += GRE_SEQ_LEN;
460 if (GREV1_FLAG_ISSET_ACK(pi->greh))
461 gre_header_len += GREV1_ACK_LEN;
462 if (gre_header_len > len) {
463 return;
465 break;
467 default:
468 /* Error */
469 return;
472 prepare_greip(pi);
473 return;
476 void prepare_ip6ip (packetinfo *pi)
478 packetinfo pipi;
479 memset(&pipi, 0, sizeof(packetinfo));
480 config.pr_s.ip6ip_recv++;
481 pipi.pheader = pi->pheader;
482 pipi.packet = (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
483 pipi.end_ptr = pi->end_ptr;
484 if (pi->ip6->next == IP_PROTO_IP4) {
485 prepare_ip4(&pipi);
486 parse_ip4(&pipi);
487 return;
488 } else {
489 prepare_ip6(&pipi);
490 parse_ip6(&pipi);
491 return;
495 void prepare_greip (packetinfo *pi)
497 packetinfo pipi;
498 memset(&pipi, 0, sizeof(packetinfo));
499 pipi.pheader = pi->pheader;
500 pipi.packet = (pi->packet + pi->eth_hlen + pi->gre_hlen);
501 pipi.end_ptr = pi->end_ptr;
502 if (GRE_GET_PROTO(pi->greh) == IP_PROTO_IP4) {
503 prepare_ip4(&pipi);
504 parse_ip4(&pipi);
505 return;
506 } else if (GRE_GET_PROTO(pi->greh) == IP_PROTO_IP6) {
507 prepare_ip6(&pipi);
508 parse_ip6(&pipi);
509 return;
510 } else {
511 /* Not more implemented atm */
512 vlog(0x3, "[*] - NOT CHECKING GRE PACKAGE TYPE Other\n");
513 return;
516 void prepare_ip4ip (packetinfo *pi)
518 packetinfo pipi;
519 memset(&pipi, 0, sizeof(packetinfo));
520 config.pr_s.ip4ip_recv++;
521 pipi.pheader = pi->pheader;
522 pipi.packet = (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
523 pipi.end_ptr = pi->end_ptr;
524 if (pi->ip4->ip_p == IP_PROTO_IP4) {
525 prepare_ip4(&pipi);
526 parse_ip4(&pipi);
527 return;
528 } else {
529 prepare_ip6(&pipi);
530 parse_ip6(&pipi);
531 return;
535 void prepare_ip6 (packetinfo *pi)
537 config.pr_s.ip6_recv++;
538 pi->af = AF_INET6;
539 pi->ip6 = (ip6_header *) (pi->packet + pi->eth_hlen);
540 pi->packet_bytes = pi->ip6->len;
541 // may be dropped due to macros plus
542 //pi->ip_src = PI_IP6SRC(pi);
543 //pi->ip_dst = PI_IP6DST(pi);
544 pi->our = filter_packet(pi->af, &PI_IP6SRC(pi));
545 vlog(0x3, "Got %s IPv6 Packet...\n", (pi->our?"our":"foregin"));
546 return;
549 void parse_ip6 (packetinfo *pi)
551 switch (pi->ip6->next) {
552 case IP_PROTO_TCP:
553 prepare_tcp(pi);
554 if (!pi->our)
555 break;
556 parse_tcp(pi);
557 break;
558 case IP_PROTO_UDP:
559 prepare_udp(pi);
560 if (!pi->our)
561 break;
562 parse_udp(pi);
563 break;
564 case IP6_PROTO_ICMP:
565 prepare_icmp(pi);
566 if (!pi->our)
567 break;
568 parse_icmp(pi);
569 break;
570 case IP_PROTO_IP4:
571 prepare_ip6ip(pi);
572 break;
573 case IP_PROTO_IP6:
574 prepare_ip6ip(pi);
575 break;
577 default:
578 prepare_other(pi);
580 * if (check != 0) {
581 * olog("[*] - CHECKING OTHER PACKAGE\n");
582 * update_asset(AF_INET6,ip6->ip_src);
583 * service_other(*pi->ip4,*tcph)
584 * fp_other(ip, ttl, ipopts, len, id, ipflags, df);
585 * }else{
586 * olog("[*] - NOT CHECKING OTHER PACKAGE\n");
587 * }
589 break;
591 return;
594 void parse_arp (packetinfo *pi)
596 vlog(0x3, "[*] Got ARP packet...\n");
597 config.pr_s.arp_recv++;
598 if (!IS_CSSET(&config,CS_ARP)) return;
599 pi->af = AF_INET;
600 pi->arph = (ether_arp *) (pi->packet + pi->eth_hlen);
602 if (ntohs(pi->arph->ea_hdr.ar_op) == ARPOP_REPLY) {
603 if (filter_packet(pi->af, &pi->arph->arp_spa)) {
604 update_asset_arp(pi->arph->arp_sha, pi);
606 /* arp_check(eth_hdr,pi->pheader->ts.tv_sec); */
607 } else {
608 vlog(0x3, "[*] ARP TYPE: %d\n",ntohs(pi->arph->ea_hdr.ar_op));
612 void set_pkt_end_ptr (packetinfo *pi)
614 /* Paranoia! */
615 if (pi->pheader->len <= SNAPLENGTH) {
616 pi->end_ptr = (pi->packet + pi->pheader->len);
617 } else {
618 pi->end_ptr = (pi->packet + SNAPLENGTH);
620 return;
623 void prepare_tcp (packetinfo *pi)
625 config.pr_s.tcp_recv++;
626 if (pi->af==AF_INET) {
627 vlog(0x3, "[*] IPv4 PROTOCOL TYPE TCP:\n");
628 pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
629 pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 - (IP_HL(pi->ip4) * 4) - pi->eth_hlen);
630 pi->payload = (char *)(pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4) + (TCP_OFFSET(pi->tcph) * 4));
631 } else if (pi->af==AF_INET6) {
632 vlog(0x3, "[*] IPv6 PROTOCOL TYPE TCP:\n");
633 pi->tcph = (tcp_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
634 pi->plen = (pi->pheader->caplen - (TCP_OFFSET(pi->tcph)) * 4 - IP6_HEADER_LEN - pi->eth_hlen);
635 pi->payload = (char *)(pi->packet + pi->eth_hlen + IP6_HEADER_LEN + (TCP_OFFSET(pi->tcph)*4));
637 pi->proto = IP_PROTO_TCP;
638 pi->s_port = pi->tcph->src_port;
639 pi->d_port = pi->tcph->dst_port;
640 connection_tracking(pi);
641 //cx_track_simd_ipv4(pi);
642 return;
645 void parse_tcp (packetinfo *pi)
647 update_asset(pi);
649 if (TCP_ISFLAGSET(pi->tcph, (TF_SYN))) {
650 if (!TCP_ISFLAGSET(pi->tcph, (TF_ACK))) {
651 if (IS_COSET(&config,CO_SYN)) {
652 vlog(0x3, "[*] - Got a SYN from a CLIENT: dst_port:%d\n",ntohs(pi->tcph->dst_port));
653 fp_tcp(pi, CO_SYN);
654 return;
656 } else {
657 if (IS_COSET(&config,CO_SYNACK)) {
658 vlog(0x3, "[*] Got a SYNACK from a SERVER: src_port:%d\n", ntohs(pi->tcph->src_port));
659 fp_tcp(pi, CO_SYNACK);
660 if (pi->sc != SC_SERVER) reverse_pi_cxt(pi);
661 return;
666 // Check payload for known magic bytes that defines files!
668 if (pi->sc == SC_CLIENT && !ISSET_CXT_DONT_CHECK_CLIENT(pi)) {
669 if (IS_CSSET(&config,CS_TCP_CLIENT)
670 && !ISSET_DONT_CHECK_CLIENT(pi)) {
671 if (pi->af == AF_INET) client_tcp4(pi);
672 else client_tcp6(pi);
674 goto bastard_checks;
676 } else if (pi->sc == SC_SERVER && !ISSET_CXT_DONT_CHECK_SERVER(pi)) {
677 if (IS_CSSET(&config,CS_TCP_SERVER)
678 && !ISSET_DONT_CHECK_SERVICE(pi)) {
679 if (pi->af == AF_INET) service_tcp4(pi);
680 else service_tcp6(pi);
682 goto bastard_checks;
684 vlog(0x3, "[*] - NOT CHECKING TCP PACKAGE\n");
685 return;
687 bastard_checks:
688 if (IS_COSET(&config,CO_ACK)
689 && TCP_ISFLAGSET(pi->tcph, (TF_ACK))
690 && !TCP_ISFLAGSET(pi->tcph, (TF_SYN))
691 && !TCP_ISFLAGSET(pi->tcph, (TF_RST))
692 && !TCP_ISFLAGSET(pi->tcph, (TF_FIN))) {
693 vlog(0x3, "[*] Got a STRAY-ACK: src_port:%d\n",ntohs(pi->tcph->src_port));
694 fp_tcp(pi, CO_ACK);
695 return;
696 } else if (IS_COSET(&config,CO_FIN) && TCP_ISFLAGSET(pi->tcph, (TF_FIN))) {
697 vlog(0x3, "[*] Got a FIN: src_port:%d\n",ntohs(pi->tcph->src_port));
698 fp_tcp(pi, CO_FIN);
699 return;
700 } else if (IS_COSET(&config,CO_RST) && TCP_ISFLAGSET(pi->tcph, (TF_RST))) {
701 vlog(0x3, "[*] Got a RST: src_port:%d\n",ntohs(pi->tcph->src_port));
702 fp_tcp(pi, CO_RST);
703 return;
707 void prepare_udp (packetinfo *pi)
709 config.pr_s.udp_recv++;
710 if (pi->af==AF_INET) {
711 vlog(0x3, "[*] IPv4 PROTOCOL TYPE UDP:\n");
712 pi->udph = (udp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
713 pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
714 (IP_HL(pi->ip4) * 4) - pi->eth_hlen;
715 pi->payload = (char *)(pi->packet + pi->eth_hlen +
716 (IP_HL(pi->ip4) * 4) + UDP_HEADER_LEN);
718 } else if (pi->af==AF_INET6) {
719 vlog(0x3, "[*] IPv6 PROTOCOL TYPE UDP:\n");
720 pi->udph = (udp_header *) (pi->packet + pi->eth_hlen + + IP6_HEADER_LEN);
721 pi->plen = pi->pheader->caplen - UDP_HEADER_LEN -
722 IP6_HEADER_LEN - pi->eth_hlen;
723 pi->payload = (char *)(pi->packet + pi->eth_hlen +
724 IP6_HEADER_LEN + UDP_HEADER_LEN);
726 pi->proto = IP_PROTO_UDP;
727 pi->s_port = pi->udph->src_port;
728 pi->d_port = pi->udph->dst_port;
729 connection_tracking(pi);
730 //cx_track_simd_ipv4(pi);
731 return;
734 void parse_udp (packetinfo *pi)
736 update_asset(pi);
737 //if (is_set_guess_upd_direction(config)) {
738 udp_guess_direction(pi); // fix DNS server transfers?
739 // Check for Passive DNS
740 // if (IS_COSET(&config,CO_DNS) && (pi->sc == SC_SERVER && ntohs(pi->s_port) == 53)) passive_dns (pi);
742 if (IS_CSSET(&config,CS_UDP_SERVICES)) {
743 if (pi->af == AF_INET) {
745 if (!ISSET_DONT_CHECK_SERVICE(pi)||!ISSET_DONT_CHECK_CLIENT(pi)) {
746 // Check for UDP SERVICE
747 service_udp4(pi);
749 // UPD Fingerprinting
750 if (IS_COSET(&config,CO_UDP)) fp_udp4(pi, pi->ip4, pi->udph, pi->end_ptr);
751 } else if (pi->af == AF_INET6) {
752 if (!ISSET_DONT_CHECK_SERVICE(pi)||!ISSET_DONT_CHECK_CLIENT(pi)) {
753 service_udp6(pi);
755 /* fp_udp(ip6, ttl, ipopts, len, id, ipflags, df); */
757 return;
758 } else {
759 vlog(0x3, "[*] - NOT CHECKING UDP PACKAGE\n");
760 return;
764 void prepare_icmp (packetinfo *pi)
766 config.pr_s.icmp_recv++;
767 if (pi->af==AF_INET) {
768 vlog(0x3, "[*] IPv4 PROTOCOL TYPE ICMP:\n");
769 pi->icmph = (icmp_header *) (pi->packet + pi->eth_hlen + (IP_HL(pi->ip4) * 4));
770 pi->proto = IP_PROTO_ICMP;
772 } else if (pi->af==AF_INET6) {
773 vlog(0x3, "[*] IPv6 PROTOCOL TYPE ICMP:\n");
774 pi->icmp6h = (icmp6_header *) (pi->packet + pi->eth_hlen + IP6_HEADER_LEN);
775 pi->proto = IP6_PROTO_ICMP;
777 pi->s_port = 0;
778 pi->d_port = 0;
780 * DO change ip6->hop_lmt to 0 or something
782 connection_tracking(pi);
783 return;
786 void parse_icmp (packetinfo *pi)
788 update_asset(pi);
790 if (IS_COSET(&config,CO_ICMP)) {
791 if (pi->cxt->check == 0x00) {
792 pi->cxt->check = 0x10; //for now - stop icmp fp quick
793 if (pi->af==AF_INET) {
794 fp_icmp4(pi, pi->ip4, pi->icmph, pi->end_ptr);
795 // could look for icmp spesific data in package abcde...
796 // service_icmp(*pi->ip4,*tcph
797 } else if (pi->af==AF_INET6) {
798 add_asset(pi);
799 fp_icmp6(pi, pi->ip6, pi->icmp6h, pi->end_ptr);
801 } else {
802 vlog(0x3, "[*] - NOT CHECKING ICMP PACKAGE\n");
807 void prepare_other (packetinfo *pi)
809 config.pr_s.othert_recv++;
810 if (pi->af==AF_INET) {
811 vlog(0x3, "[*] IPv4 PROTOCOL TYPE OTHER: %d\n",pi->ip4->ip_p);
813 } else if (pi->af==AF_INET6) {
814 vlog(0x3, "[*] IPv6 PROTOCOL TYPE OTHER: %d\n",pi->ip6->next);
817 pi->s_port = 0;
818 pi->d_port = 0;
819 connection_tracking(pi);
820 return;
823 void parse_other (packetinfo *pi)
825 update_asset(pi);
827 if (pi->cxt->check == 0x00) {
828 if (IS_COSET(&config,CO_OTHER)) {
829 pi->cxt->check = 0x01; // no more checks
830 // service_other(*pi->ip4,*transporth);
831 // fp_other(pi->ipX, ttl, ipopts, len, id, ipflags, df);
832 } else {
833 vlog(0x3, "[*] - NOT CHECKING *OTHER* PACKAGE\n");
838 void udp_guess_direction(packetinfo *pi)
840 /* Stupid hack :( for DNS/port 53 */
841 if (ntohs(pi->d_port) == 53) {
842 if (pi->sc == SC_CLIENT) return;
843 else pi->sc = SC_CLIENT;
845 } else if (ntohs(pi->s_port) == 53) {
846 if (pi->sc == SC_SERVER) return;
847 else pi->sc = SC_SERVER;
851 int parse_network (char *net_s, struct in6_addr *network)
853 int type;
854 char *t;
855 if (NULL != (t = strchr(net_s, ':'))) {
856 type = AF_INET6;
857 if (!inet_pton(type, net_s, network)) {
858 perror("parse_nets6");
859 return -1;
861 olog("Network6 %-36s \t -> %08x:%08x:%08x:%08x\n",
862 net_s,
863 IP6ADDR(network)
865 } else {
866 type = AF_INET;
867 if (!inet_pton(type, net_s, &IP4ADDR(network))) {
868 perror("parse_nets");
869 return -1;
871 olog("Network4 %16s \t-> 0x%08x\n", net_s, IP4ADDR(network));
873 return type;
876 int parse_netmask (char *f, int type, struct in6_addr *netmask)
878 char *t;
879 uint32_t mask;
880 char output[MAX_NETS];
881 // parse netmask into host order
882 if (type == AF_INET && (t = strchr(f, '.')) > f && t-f < 4) {
883 // full ipv4 netmask : dotted quads
884 inet_pton(type, f, &IP4ADDR(netmask));
885 olog("mask 4 %s \t-> 0x%08x\n", f, IP4ADDR(netmask));
886 } else if (type == AF_INET6 && NULL != (t = strchr(f, ':'))) {
887 // full ipv6 netmasÄž
888 olog("mask 6 %s\n", f);
889 inet_pton(type, f, netmask);
890 } else {
891 // cidr form
892 sscanf(f, "%u", &mask);
893 olog("cidr %u \t-> ", mask);
894 if (type == AF_INET) {
895 uint32_t shift = 32 - mask;
896 if (mask)
897 IP4ADDR(netmask) = ntohl( ((unsigned int)-1 >> shift)<< shift);
898 else
899 IP4ADDR(netmask) = 0;
901 olog("0x%08x\n", IP4ADDR(netmask));
902 } else if (type == AF_INET6) {
903 //mask = 128 - mask;
904 int j = 0;
905 memset(netmask, 0, sizeof(struct in6_addr));
907 while (mask > 8) {
908 netmask->s6_addr[j++] = 0xff;
909 mask -= 8;
911 if (mask > 0) {
912 netmask->s6_addr[j] = -1 << (8 - mask);
914 inet_ntop(type, &IP4ADDR(netmask), output, MAX_NETS);
915 olog("mask: %s\n", output);
916 // pcap packets are in host order.
917 IP6ADDR0(netmask) = ntohl(IP6ADDR0(netmask));
918 IP6ADDR1(netmask) = ntohl(IP6ADDR1(netmask));
919 IP6ADDR2(netmask) = ntohl(IP6ADDR2(netmask));
920 IP6ADDR3(netmask) = ntohl(IP6ADDR3(netmask));
924 return 0;
927 /* parse strings of the form ip/cidr or ip/mask like:
928 * "10.10.10.10/255.255.255.128,10.10.10.10/25" and
929 * "dead:be:eef2:1aa::b5ff:fe96:37a2/64,..."
931 * an IPv6 address is 8 x 4 hex digits. missing digits are padded with zeroes.
933 void parse_nets(const char *s_net, struct fmask *network)
935 /* f -> for processing
936 * p -> frob pointer
937 * t -> to pointer */
938 char *f, *p, *snet;
939 int type, len, i = 0;
940 struct in6_addr network6, netmask6;
942 // snet is a mutable copy of the args,freed @ nets_end
943 len = strlen(s_net);
944 //snet = calloc(1, len);
945 snet = calloc(1, (len + 1)); /* to have \0 too :-) */
946 strncpy(snet, s_net, len);
947 f = snet;
948 while (f && 0 != (p = strchr(f, '/'))) {
949 // convert network address
950 *p = '\0';
951 type = parse_network(f, &network6);
952 if (type != AF_INET && type != AF_INET6) {
953 perror("parse_network");
954 goto nets_end;
956 // convert netmask
957 f = p + 1;
958 p = strchr(f, ',');
959 if (p) {
960 *p = '\0';
962 parse_netmask(f, type, &netmask6);
964 // poke in the gathered information
965 switch (type) {
966 case AF_INET:
967 case AF_INET6:
968 network[i].addr = network6;
969 network[i].mask = netmask6;
970 network[i].type = type;
971 break;
973 default:
974 fprintf(stderr, "parse_nets: invalid address family!\n");
975 goto nets_end;
978 nets = ++i;
980 if (i > MAX_NETS) {
981 elog("Max networks reached, stopped parsing at %d nets.\n", i-1);
982 goto nets_end;
986 // continue parsing at p, which might point to another network range
987 f = p;
988 if(p) f++;
990 nets_end:
991 free(snet);
992 return;
995 void game_over()
998 if (inpacket == 0) {
999 //update_asset_list();
1000 clear_asset_list();
1001 end_all_sessions();
1002 free_queue();
1003 del_known_services();
1004 del_signature_lists();
1005 unload_tcp_sigs();
1006 end_logging();
1007 print_prads_stats();
1008 print_pcap_stats();
1009 if (config.handle != NULL) pcap_close(config.handle);
1010 free_config(); // segfault here !
1011 printf("\nprads ended\n");
1012 exit(0);
1014 intr_flag = 1;
1017 void check_interrupt()
1020 if (intr_flag == 1) {
1021 game_over();
1022 } else if (intr_flag == 2) {
1023 update_asset_list();
1024 } else if (intr_flag == 3) {
1025 set_end_sessions();
1026 } else {
1027 intr_flag = 0;
1031 void set_end_sessions()
1033 intr_flag = 3;
1035 if (inpacket == 0) {
1036 tstamp = time(NULL);
1037 end_sessions();
1038 /* if no cxtracking is turned on - dont log to disk */
1039 /* if (log_cxt == 1) log_expired_cxt(); */
1040 /* if no asset detection is turned on - dont log to disk! */
1041 /* if (log_assets == 1) update_asset_list(); */
1042 update_asset_list();
1043 intr_flag = 0;
1044 alarm(CHECK_TIMEOUT);
1048 void print_prads_stats()
1050 extern uint64_t cxtrackerid; // cxt.c
1051 printf("\n-- prads:");
1052 printf("\n-- Total packets received from libpcap :%12u",config.pr_s.got_packets);
1053 printf("\n-- Total Ethernet packets received :%12u",config.pr_s.eth_recv);
1054 printf("\n-- Total VLAN packets received :%12u",config.pr_s.vlan_recv);
1055 printf("\n-- Total ARP packets received :%12u",config.pr_s.arp_recv);
1056 printf("\n-- Total IPv4 packets received :%12u",config.pr_s.ip4_recv);
1057 printf("\n-- Total IPv6 packets received :%12u",config.pr_s.ip6_recv);
1058 printf("\n-- Total Other link packets received :%12u",config.pr_s.otherl_recv);
1059 printf("\n-- Total IPinIPv4 packets received :%12u",config.pr_s.ip4ip_recv);
1060 printf("\n-- Total IPinIPv6 packets received :%12u",config.pr_s.ip6ip_recv);
1061 printf("\n-- Total GRE packets received :%12u",config.pr_s.gre_recv);
1062 printf("\n-- Total TCP packets received :%12u",config.pr_s.tcp_recv);
1063 printf("\n-- Total UDP packets received :%12u",config.pr_s.udp_recv);
1064 printf("\n-- Total ICMP packets received :%12u",config.pr_s.icmp_recv);
1065 printf("\n-- Total Other transport packets received :%12u",config.pr_s.othert_recv);
1066 printf("\n--");
1067 printf("\n-- Total sessions tracked :%12lu", cxtrackerid);
1068 printf("\n-- Total assets detected :%12u",config.pr_s.assets);
1069 printf("\n-- Total TCP OS fingerprints detected :%12u",config.pr_s.tcp_os_assets);
1070 printf("\n-- Total UDP OS fingerprints detected :%12u",config.pr_s.udp_os_assets);
1071 printf("\n-- Total ICMP OS fingerprints detected :%12u",config.pr_s.icmp_os_assets);
1072 printf("\n-- Total DHCP OS fingerprints detected :%12u",config.pr_s.dhcp_os_assets);
1073 printf("\n-- Total TCP service assets detected :%12u",config.pr_s.tcp_services);
1074 printf("\n-- Total TCP client assets detected :%12u",config.pr_s.tcp_clients);
1075 printf("\n-- Total UDP service assets detected :%12u",config.pr_s.udp_services);
1076 printf("\n-- Total UDP client assets detected :%12u",config.pr_s.udp_clients);
1080 static void usage()
1082 olog("USAGE:\n");
1083 olog(" $ prads [options]\n");
1084 olog("\n");
1085 olog(" OPTIONS:\n");
1086 olog("\n");
1087 olog(" -i <iface> Network device <iface> (default: eth0).\n");
1088 olog(" -r <file> Read pcap <file>.\n");
1089 olog(" -c <file> Read config from <file>\n");
1090 olog(" -b <filter> Apply Berkeley packet filter <filter>.\n");
1091 //olog(" -d to logdir\n");
1092 olog(" -u <user> Run as user <user>.\n");
1093 olog(" -g <group> Run as group <group>.\n");
1094 olog(" -a <nets> Specify home nets (eg: '192.168.0.0/25,10.0.0.0/255.0.0.0').\n");
1095 olog(" -D Enables daemon mode.\n");
1096 olog(" -p <pidfile> Name of pidfile\n");
1097 olog(" -P <path> Pid lives in <path>\n");
1098 olog(" -l <file> Log assets to <file> (default: '%s')\n", config.assetlog);
1099 olog(" -f <FIFO> Log assets to <FIFO>");
1100 olog(" -C <dir> Chroot into <dir> before dropping privs.\n");
1101 olog(" -h This help message.\n");
1102 olog(" -v Verbose.\n");
1106 extern int optind, opterr, optopt; // getopt()
1108 /* magic main */
1109 int main(int argc, char *argv[])
1111 int32_t rc = 0;
1112 int ch = 0, verbose_already = 0;
1114 vlog(2, "%08x =? %08x, endianness: %s\n\n", 0xdeadbeef, ntohl(0xdeadbeef), (0xdead == ntohs(0xdead)?"big":"little") );
1116 memset(&config, 0, sizeof(globalconfig));
1117 set_default_config_options();
1118 bstring pconfile = bfromcstr(CONFDIR "prads.conf");
1119 //parse_config_file(pconfile);
1120 //bdestroy (pconfile);
1122 inpacket = gameover = intr_flag = 0;
1124 signal(SIGTERM, game_over);
1125 signal(SIGINT, game_over);
1126 signal(SIGQUIT, game_over);
1127 signal(SIGALRM, set_end_sessions);
1128 //signal(SIGALRM, game_over); // Use this to debug segfault when exiting
1130 // do first-pass args parse for commandline-passed config file
1131 opterr = 0;
1132 #define ARGS "C:c:b:d:Dg:hi:p:r:P:u:va:l:f:"
1133 while ((ch = getopt(argc, argv, ARGS)) != -1)
1134 switch (ch) {
1135 case 'c':
1136 pconfile = bfromcstr(optarg);
1137 break;
1138 case 'v':
1139 config.verbose++;
1140 break;
1141 case 'h':
1142 usage();
1143 exit(0);
1144 default:
1145 break;
1148 if(config.verbose)
1149 verbose_already = 1;
1151 parse_config_file(pconfile);
1153 // reset verbosity before 2nd coming, but only if set on cli
1154 if(verbose_already)
1155 config.verbose = 0;
1156 optind = 1;
1158 while ((ch = getopt(argc, argv, ARGS)) != -1)
1159 switch (ch) {
1160 case 'a':
1161 config.s_net = strdup(optarg);
1162 break;
1163 case 'c':
1164 pconfile = bfromcstr(optarg);
1165 break;
1166 case 'C':
1167 config.chroot_dir = strdup(optarg);
1168 break;
1169 case 'i':
1170 config.dev = strdup(optarg);
1171 break;
1172 case 'r':
1173 config.pcap_file = blk2bstr(optarg, strlen(optarg));
1174 break;
1175 case 'b':
1176 config.bpff = strdup(optarg);
1177 break;
1178 case 'v':
1179 config.verbose++;
1180 break;
1181 case 'd':
1182 config.dpath = strdup(optarg);
1183 break;
1184 case 'h':
1185 usage();
1186 exit(0);
1187 break;
1188 case 'D':
1189 config.daemon_flag = 1;
1190 break;
1191 case 'u':
1192 config.user_name = strdup(optarg);
1193 config.drop_privs_flag = 1;
1194 break;
1195 case 'g':
1196 config.group_name = strdup(optarg);
1197 config.drop_privs_flag = 1;
1198 break;
1199 case 'p':
1200 config.pidfile = strdup(optarg);
1201 break;
1202 case 'P':
1203 config.pidpath = strdup(optarg);
1204 break;
1205 case 'l':
1206 config.assetlog = strdup(optarg);
1207 break;
1208 case 'f':
1209 config.fifo = strdup(optarg);
1210 break;
1211 case '?':
1212 elog("unrecognized argument: '%c'\n", optopt);
1213 break;
1214 default:
1215 elog("Did not recognize argument '%c'\n", ch);
1218 bdestroy (pconfile);
1219 // we're done parsing configs - now initialize prads
1221 if(config.verbose){
1222 rc = init_logging(LOG_STDOUT, NULL, config.verbose);
1223 if(rc) perror("Logging to standard out failed!");
1226 if(config.assetlog) {
1227 olog("logging to file '%s'\n", config.assetlog);
1228 rc = init_logging(LOG_FILE, config.assetlog, config.verbose);
1229 if(rc) perror("Logging to file failed!");
1231 if(config.fifo) {
1232 olog("logging to FIFO '%s'\n", config.fifo);
1233 rc = init_logging(LOG_FIFO, config.fifo, config.verbose);
1234 if(rc) perror("Logging to fifo failed!");
1237 if(config.s_net)
1238 parse_nets(config.s_net, network);
1240 if(config.ctf & CS_MAC){
1241 olog("[*] Loading MAC fingerprints from file %s\n", config.sig_file_mac);
1242 rc = load_mac(config.sig_file_mac, &config.sig_mac, 0);
1243 if(rc) perror("mac loadage failed!");
1246 if(config.ctf & CO_SYN){
1247 olog("[*] Loading SYN fingerprints\n");
1248 rc = load_sigs(config.sig_file_syn, &config.sig_syn, config.sig_hashsize);
1249 if(rc) perror("syn loadage failed!");
1250 if(config.verbose > 1)
1251 dump_sigs(config.sig_syn, config.sig_hashsize);
1253 if(config.ctf & CO_SYNACK){
1254 olog("[*] Loading SYNACK fingerprints\n");
1255 rc = load_sigs(config.sig_file_synack, &config.sig_synack, config.sig_hashsize);
1256 if(rc) perror("synack loadage failed!");
1257 if(config.verbose > 1)
1258 dump_sigs(config.sig_synack, config.sig_hashsize);
1260 if(config.ctf & CO_ACK){
1261 olog("[*] Loading STRAY-ACK fingerprints\n");
1262 rc = load_sigs(config.sig_file_ack, &config.sig_ack, config.sig_hashsize);
1263 if(rc) perror("stray-ack loadage failed!");
1264 if(config.verbose > 1)
1265 dump_sigs(config.sig_ack, config.sig_hashsize);
1267 if(config.ctf & CO_FIN){
1268 olog("[*] Loading FIN fingerprints\n");
1269 rc = load_sigs(config.sig_file_fin, &config.sig_fin, config.sig_hashsize);
1270 if(rc) perror("fin loadage failed!");
1271 if(config.verbose > 1)
1272 dump_sigs(config.sig_fin, config.sig_hashsize);
1274 if(config.ctf & CO_RST){
1275 olog("[*] Loading RST fingerprints\n");
1276 rc = load_sigs(config.sig_file_rst, &config.sig_rst, config.sig_hashsize);
1277 if(rc) perror("rst loadage failed!");
1278 if(config.verbose > 1)
1279 dump_sigs(config.sig_rst, config.sig_hashsize);
1282 olog("\n[*] Running prads %s\n", VERSION);
1283 olog("[*] Using %s\n", pcap_lib_version());
1284 olog("[*] Using PCRE version %s\n", pcre_version());
1286 //if (config.verbose) display_config();
1287 display_config();
1289 // should be config file too
1290 load_servicefp_file(1, CONFDIR "tcp-service.sig");
1291 load_servicefp_file(2, CONFDIR "udp-service.sig");
1292 load_servicefp_file(3, CONFDIR "tcp-clients.sig");
1293 //load_servicefp_file(4, CONFDIR "udp-client.sig");
1294 init_services();
1296 if (config.pcap_file) {
1297 /* Read from PCAP file specified by '-r' switch. */
1298 olog("[*] Reading from file %s\n", bdata(config.pcap_file));
1299 if (!(config.handle = pcap_open_offline(bdata(config.pcap_file), config.errbuf))) {
1300 olog("[*] Unable to open %s. (%s)", bdata(config.pcap_file), config.errbuf);
1303 } else {
1305 if (getuid()) {
1306 olog("[*] You must be root..\n");
1307 return (1);
1311 * look up an available device if non specified
1313 if (config.dev == 0x0)
1314 config.dev = pcap_lookupdev(config.errbuf);
1315 olog("[*] Device: %s\n", config.dev);
1317 if ((config.handle = pcap_open_live(config.dev, SNAPLENGTH, 1, 500, config.errbuf)) == NULL) {
1318 olog("[*] Error pcap_open_live: %s \n", config.errbuf);
1319 exit(1);
1320 } //else if ((pcap_compile(config.handle, &config.cfilter, config.bpff, 1, config.net_mask)) == -1) {
1321 // olog("[*] Error pcap_compile user_filter: %s\n",
1322 // pcap_geterr(config.handle));
1323 // exit(1);
1327 * B0rk if we see an error...
1329 if (strlen(config.errbuf) > 0) {
1330 elog("[*] Error errbuf: %s \n", config.errbuf);
1331 exit(1);
1334 if(config.chroot_dir){
1335 olog("[*] Chrooting to dir '%s'..\n", config.chroot_dir);
1336 if(set_chroot()){
1337 elog("[!] failed to chroot\n");
1338 exit(1);
1342 if (config.drop_privs_flag) {
1343 olog("[*] Dropping privs...\n");
1344 drop_privs();
1347 if (config.daemon_flag) {
1348 if (!is_valid_path(config.pidpath))
1349 elog
1350 ("[*] PID path \"%s\" is bad, check privilege.", config.pidpath);
1351 openlog("prads", LOG_PID | LOG_CONS, LOG_DAEMON);
1352 olog("[*] Daemonizing...\n\n");
1353 daemonize(NULL);
1358 bucket_keys_NULL();
1359 alarm(CHECK_TIMEOUT);
1361 if ((pcap_compile(config.handle, &config.cfilter, config.bpff, 1, config.net_mask)) == -1) {
1362 olog("[*] Error pcap_compile user_filter: %s\n", pcap_geterr(config.handle));
1363 exit(1);
1366 if (pcap_setfilter(config.handle, &config.cfilter)) {
1367 olog("[*] Unable to set pcap filter! %s", pcap_geterr(config.handle));
1370 cxt_init();
1371 olog("[*] Sniffing...\n\n");
1372 pcap_loop(config.handle, -1, got_packet, NULL);
1374 game_over();
1375 //pcap_close(config.handle);
1376 return (0);
1379 //void free_config()
1381 // if (config.dev != NULL) free (config.dev);
1382 // if (config.cfilter.bf_insns != NULL) free (config.cfilter.bf_insns);