2 ** This file is a part of PRADS.
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>
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 *********************************************************/
26 #include <sys/malloc.h>
27 #elseif !defined(__FreeBSD__)
37 #include "ipfp/ipfp.h"
38 #include "servicefp/servicefp.h"
44 //#include "output-plugins/log_init.h"
45 #include "output-plugins/log.h"
48 #define CONFDIR "/etc/prads/"
51 #define ARGS "C:c:b:d:Dg:hi:p:r:u:va:l:L:f:qtxs:OXFRMSAKUTIZtHPB"
53 /* G L O B A L S *** (or candidates for refactoring, as we say)***********/
55 extern int optind
, opterr
, optopt
; // getopt()
58 servicelist
*services
[MAX_PORTS
];
59 int inpacket
, gameover
, intr_flag
;
62 fmask network
[MAX_NETS
];
64 // static strings for comparison
65 // - this is lame and should be a flag!
66 struct tagbstring tUNKNOWN
= bsStatic("unknown");
67 bstring UNKNOWN
= & tUNKNOWN
;
69 /* I N T E R N A L P R O T O T Y P E S ***********************************/
71 void check_vlan (packetinfo
*pi
);
72 void prepare_eth (packetinfo
*pi
);
73 void prepare_ip4 (packetinfo
*pi
);
74 void prepare_ip4ip (packetinfo
*pi
);
75 void prepare_ip6 (packetinfo
*pi
);
76 void prepare_ip6ip (packetinfo
*pi
);
77 void prepare_tcp (packetinfo
*pi
);
78 void prepare_udp (packetinfo
*pi
);
79 void prepare_icmp (packetinfo
*pi
);
80 void prepare_gre (packetinfo
*pi
);
81 void prepare_greip (packetinfo
*pi
);
82 void prepare_other (packetinfo
*pi
);
83 void parse_eth (packetinfo
*pi
);
84 void parse_ip4 (packetinfo
*pi
);
85 void parse_ip6 (packetinfo
*pi
);
86 void parse_tcp (packetinfo
*pi
);
87 void parse_udp (packetinfo
*pi
);
88 void parse_icmp (packetinfo
*pi
);
89 void parse_gre (packetinfo
*pi
);
90 void parse_other (packetinfo
*pi
);
91 void parse_arp (packetinfo
*pi
);
92 int parse_network (char *net_s
, struct in6_addr
*network
);
93 int parse_netmask (char *f
, int type
, struct in6_addr
*netmask
);
94 void parse_nets(const char *s_net
, fmask
*network
);
96 void udp_guess_direction(packetinfo
*pi
);
97 void set_pkt_end_ptr (packetinfo
*pi
);
98 inline int filter_packet(const int af
, void *ip
);
100 /* F U N C T I O N S ********************************************************/
102 void got_packet(u_char
* useless
, const struct pcap_pkthdr
*pheader
,
103 const u_char
* packet
)
105 config
.pr_s
.got_packets
++;
106 packetinfo pstruct
= {0};
107 packetinfo
*pi
= &pstruct
;
110 pi
->pheader
= pheader
;
111 set_pkt_end_ptr (pi
);
112 tstamp
= pi
->pheader
->ts
.tv_sec
; // Global
113 if (intr_flag
!= 0) {
121 if (pi
->eth_type
== ETHERNET_TYPE_IP
) {
125 } else if (pi
->eth_type
== ETHERNET_TYPE_IPV6
) {
129 } else if (pi
->eth_type
== ETHERNET_TYPE_ARP
) {
133 config
.pr_s
.otherl_recv
++;
134 vlog(0x3, "[*] ETHERNET TYPE : %x\n",pi
->eth_hdr
->eth_ip_type
);
137 if (!pi
->our
) vlog(0x3, "Not our network packet. Tracked, but not logged.\n");
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)
155 char output
[INET_ADDRSTRLEN
+ 1];
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
)
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
);
171 if((IP4ADDR(ip
) & IP4ADDR(&network
[i
].mask
))
172 == (IP4ADDR(&network
[i
].addr
) & IP4ADDR(&network
[i
].mask
)) ){
178 dlog("%8x %8x %8x\n", IP4ADDR(ip
) & IP4ADDR(&network
[i
].mask
), IP4ADDR(&network
[i
].addr
) & IP4ADDR(&network
[i
].mask
), IP4ADDR(&network
[i
].mask
));
186 /* 32-bit comparison of ipv6 nets.
187 * can do better here by using 64-bit or SIMD instructions
188 * this code needs more thought and work
191 * PS: use same code for ipv4 - 0 bytes and SIMD doesnt care*/
193 // copy the in6_addr pointed to by ipptr into the vector. grr!
194 memcpy(&ip_vec
.ip6
,ipptr
, sizeof(struct in6_addr
));
195 for (i
= 0; i
< MAX_NETS
&& i
< nets
; i
++) {
196 if(network
[i
].type
!= AF_INET6
)
199 struct in6_addr tmp_netmask
;
201 IP6ADDR0(&tmp_netmask
) = htonl(IP6ADDR0(&network
[i
].mask
));
202 IP6ADDR1(&tmp_netmask
) = htonl(IP6ADDR1(&network
[i
].mask
));
203 IP6ADDR2(&tmp_netmask
) = htonl(IP6ADDR2(&network
[i
].mask
));
204 IP6ADDR3(&tmp_netmask
) = htonl(IP6ADDR3(&network
[i
].mask
));
206 u_ntop(network
[i
].addr
, af
, output
);
207 dlog("net: %s\n", output
);
208 u_ntop(tmp_netmask
, af
, output
);
209 dlog("mask: %s\n", output
);
210 u_ntop(ip_vec
.ip6
, af
, output
);
211 dlog("ip: %s\n", output
);
213 if (network
[i
].type
== AF_INET6
) {
215 /* apologies for the uglyness */
217 #define compare128(x,y) __builtin_ia32_pcmpeqd128((x), (y))
218 // the builtin is only available on sse2!
219 t
.v
= __builtin_ia32_pcmpeqd128(
220 ip_vec
.v
& network
[i
].mask_v
,
224 #define compare128(x,y) memcmp(&(x),&(y),16)
225 t
.v
= ip_vec
.v
& network
[i
].mask_v
;
226 // xor(a,b) == 0 iff a==b
227 if (!( (t
.i
[0] ^ network
[i
].addr64
[0]) &
228 (t
.i
[1] ^ network
[i
].addr64
[1]) ))
236 if ((ip_s
.__u6_addr
.__u6_addr32
[0] & network
[i
].mask
.__u6_addr
.__u6_addr32
[0])
237 == network
[i
].addr
.__u6_addr
.__u6_addr32
[0]
238 && (ip_s
.__u6_addr
.__u6_addr32
[1] & network
[i
].mask
.__u6_addr
.__u6_addr32
[1])
239 == network
[i
].addr
.__u6_addr
.__u6_addr32
[1]
240 && (ip_s
.__u6_addr
.__u6_addr32
[2] & network
[i
].mask
.__u6_addr
.__u6_addr32
[2])
241 == network
[i
].addr
.__u6_addr
.__u6_addr32
[2]
242 && (ip_s
.__u6_addr
.__u6_addr32
[3] & network
[i
].mask
.__u6_addr
.__u6_addr32
[3])
243 == network
[i
].addr
.__u6_addr
.__u6_addr32
[3]) {
254 "non-ip packets of type %d aren't filtered by netmask yet\n", af
);
259 inet_ntop(af
, (struct in6addr
*) ipptr
, output
, MAX_NETS
);
261 inet_ntop(af
, (uint32_t*)ipptr
, output
, MAX_NETS
);
264 vlog(0x2, "Address %s is in our network.\n", output
);
266 vlog(0x2, "Address %s is not our network.\n", output
);
272 void prepare_eth (packetinfo
*pi
)
274 if (pi
->packet
+ ETHERNET_HEADER_LEN
> pi
->end_ptr
) return;
275 config
.pr_s
.eth_recv
++;
276 pi
->eth_hdr
= (ether_header
*) (pi
->packet
);
277 pi
->eth_type
= ntohs(pi
->eth_hdr
->eth_ip_type
);
278 pi
->eth_hlen
= ETHERNET_HEADER_LEN
;
282 void parse_eth (packetinfo
*pi
)
284 if (!IS_CSSET(&config
,CS_MAC
)) return;
285 /* update_asset_arp(pi->eth_hdr->ether_src, pi);
287 uint8_t *mac = pi->eth_hdr->ether_src;
289 * XXX: how is mac matching supposed to work?
290 * answer: lookup macs on pertinent frames
291 * and hash into mac asset database
292 * mac assets are like regular assets,
293 * and contain references to other assets they involve
294 if(! pi->asset->mace)
295 mac_entry *match = match_mac(config.sig_mac, mac, 48);
299 olog("mac matched: %s\n", match->vendor);
301 // call update_asset_mac or smth?
303 //config.pr_s.eth_recv++;
309 void check_vlan (packetinfo
*pi
)
311 if (pi
->eth_type
== ETHERNET_TYPE_8021Q
) {
312 vlog(0x3, "[*] ETHERNET TYPE 8021Q\n");
313 config
.pr_s
.vlan_recv
++;
314 pi
->vlan
= pi
->eth_hdr
->eth_8_vid
;
315 pi
->eth_type
= ntohs(pi
->eth_hdr
->eth_8_ip_type
);
318 /* This is b0rked - kwy and ebf fix */
319 } else if (pi
->eth_type
==
320 (ETHERNET_TYPE_802Q1MT
| ETHERNET_TYPE_802Q1MT2
|
321 ETHERNET_TYPE_802Q1MT3
| ETHERNET_TYPE_8021AD
)) {
322 vlog(0x3, "[*] ETHERNET TYPE 802Q1MT\n");
323 pi
->mvlan
= pi
->eth_hdr
->eth_82_mvid
;
324 pi
->eth_type
= ntohs(pi
->eth_hdr
->eth_82_ip_type
);
330 void prepare_ip4 (packetinfo
*pi
)
332 config
.pr_s
.ip4_recv
++;
334 pi
->ip4
= (ip4_header
*) (pi
->packet
+ pi
->eth_hlen
);
335 pi
->packet_bytes
= (ntohs(pi
->ip4
->ip_len
) - (IP_HL(pi
->ip4
) * 4));
337 pi
->our
= filter_packet(pi
->af
, &PI_IP4SRC(pi
));
338 vlog(0x3, "Got %s IPv4 Packet...\n", (pi
->our
?"our":"foregin"));
342 void parse_ip4 (packetinfo
*pi
)
344 switch (pi
->ip4
->ip_p
) {
370 /* Note: fragmented IPv4 GRE packets will be
371 skipped in the following functions as the
372 interesting information for prads is in the
373 first packet and flow-assembly is not part
389 void prepare_gre (packetinfo
*pi
)
391 config
.pr_s
.gre_recv
++;
392 // do not handle fragmented IPv4 gre packets
393 if(pi
->af
== AF_INET
&& pi
->ip4
->ip_off
> 0){
396 if((pi
->pheader
->caplen
- pi
->eth_hlen
) < GRE_HDR_LEN
) {
399 if (pi
->af
== AF_INET
) {
400 vlog(0x3, "[*] IPv4 PROTOCOL TYPE GRE:\n");
401 pi
->greh
= (gre_header
*) (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4));
402 } else if (pi
->af
== AF_INET6
) {
403 vlog(0x3, "[*] IPv6 PROTOCOL TYPE GRE:\n");
404 pi
->greh
= (gre_header
*) (pi
->packet
+ pi
->eth_hlen
+ IP6_HEADER_LEN
);
406 pi
->proto
= IP_PROTO_GRE
;
410 void parse_gre (packetinfo
*pi
)
412 uint16_t gre_header_len
= GRE_HDR_LEN
;
413 gre_sre_header
*gsre
= NULL
;
414 uint16_t len
= (pi
->pheader
->caplen
- pi
->eth_hlen
);
416 // do not process invalid packets
417 if(len
< GRE_HDR_LEN
){
420 // do not process fragmented GRE packets
421 if(pi
->af
== AF_INET
&& pi
->ip4
->ip_off
> 0){
427 switch (GRE_GET_VERSION(pi
->greh
))
430 /* Adjust header length based on content */
431 if (GRE_FLAG_ISSET_KY(pi
->greh
))
432 gre_header_len
+= GRE_KEY_LEN
;
433 if (GRE_FLAG_ISSET_SQ(pi
->greh
))
434 gre_header_len
+= GRE_SEQ_LEN
;
435 if (GRE_FLAG_ISSET_CHKSUM(pi
->greh
) || GRE_FLAG_ISSET_ROUTE(pi
->greh
))
436 gre_header_len
+= GRE_CHKSUM_LEN
+ GRE_OFFSET_LEN
;
437 if (gre_header_len
> len
) {
440 if (GRE_FLAG_ISSET_ROUTE(pi
->greh
))
442 gsre
= (gre_sre_header
*)(pi
->greh
+ gre_header_len
);
443 if (gsre
== NULL
) return;
446 if ((gre_header_len
+GRE_SRE_HDR_LEN
) > len
) {
449 gre_header_len
+= GRE_SRE_HDR_LEN
;
451 if (gsre
!= NULL
&& (ntohs(gsre
->af
) == 0) && (gsre
->sre_length
== 0))
454 gre_header_len
+= gsre
->sre_length
;
455 gsre
= (gre_sre_header
*)(pi
->greh
+ gre_header_len
);
460 pi
->gre_hlen
= gre_header_len
;
464 /* GRE version 1 doenst support the fields below RFC 1701 */
465 if (GRE_FLAG_ISSET_CHKSUM(pi
->greh
)) {
468 if (GRE_FLAG_ISSET_ROUTE(pi
->greh
)) {
471 if (GRE_FLAG_ISSET_SSR(pi
->greh
)) {
474 if (GRE_FLAG_ISSET_RECUR(pi
->greh
)) {
477 if (GREV1_FLAG_ISSET_FLAGS(pi
->greh
)) {
480 if (GRE_GET_PROTO(pi
->greh
) != GRE_PROTO_PPP
) {
483 if (!(GRE_FLAG_ISSET_KY(pi
->greh
))) {
487 gre_header_len
+= GRE_KEY_LEN
;
489 /* Adjust header length based on content */
490 if (GRE_FLAG_ISSET_SQ(pi
->greh
))
491 gre_header_len
+= GRE_SEQ_LEN
;
492 if (GREV1_FLAG_ISSET_ACK(pi
->greh
))
493 gre_header_len
+= GREV1_ACK_LEN
;
494 if (gre_header_len
> len
) {
508 void prepare_ip6ip (packetinfo
*pi
)
511 memset(&pipi
, 0, sizeof(packetinfo
));
512 config
.pr_s
.ip6ip_recv
++;
513 pipi
.pheader
= pi
->pheader
;
514 pipi
.packet
= (pi
->packet
+ pi
->eth_hlen
+ IP6_HEADER_LEN
);
515 pipi
.end_ptr
= pi
->end_ptr
;
516 if (pi
->ip6
->next
== IP_PROTO_IP4
) {
527 void prepare_greip (packetinfo
*pi
)
530 memset(&pipi
, 0, sizeof(packetinfo
));
531 pipi
.pheader
= pi
->pheader
;
532 pipi
.packet
= (pi
->packet
+ pi
->eth_hlen
+ pi
->gre_hlen
);
533 pipi
.end_ptr
= pi
->end_ptr
;
534 if (GRE_GET_PROTO(pi
->greh
) == IP_PROTO_IP4
) {
538 } else if (GRE_GET_PROTO(pi
->greh
) == IP_PROTO_IP6
) {
543 /* Not more implemented atm */
544 vlog(0x3, "[*] - NOT CHECKING GRE PACKAGE TYPE Other\n");
549 void prepare_ip4ip (packetinfo
*pi
)
552 memset(&pipi
, 0, sizeof(packetinfo
));
553 config
.pr_s
.ip4ip_recv
++;
554 pipi
.pheader
= pi
->pheader
;
555 pipi
.packet
= (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4));
556 pipi
.end_ptr
= pi
->end_ptr
;
557 if (pi
->ip4
->ip_p
== IP_PROTO_IP4
) {
568 void prepare_ip6 (packetinfo
*pi
)
570 config
.pr_s
.ip6_recv
++;
572 pi
->ip6
= (ip6_header
*) (pi
->packet
+ pi
->eth_hlen
);
573 pi
->packet_bytes
= ntohs(pi
->ip6
->len
);
574 // may be dropped due to macros plus
575 //pi->ip_src = PI_IP6SRC(pi);
576 //pi->ip_dst = PI_IP6DST(pi);
577 pi
->our
= filter_packet(pi
->af
, &PI_IP6SRC(pi
));
578 vlog(0x3, "Got %s IPv6 Packet...\n", (pi
->our
?"our":"foregin"));
582 void parse_ip6 (packetinfo
*pi
)
584 switch (pi
->ip6
->next
) {
614 * olog("[*] - CHECKING OTHER PACKAGE\n");
615 * update_asset(AF_INET6,ip6->ip_src);
616 * service_other(*pi->ip4,*tcph)
617 * fp_other(ip, ttl, ipopts, len, id, ipflags, df);
619 * olog("[*] - NOT CHECKING OTHER PACKAGE\n");
627 void parse_arp (packetinfo
*pi
)
629 vlog(0x3, "[*] Got ARP packet...\n");
630 config
.pr_s
.arp_recv
++;
631 if (!IS_CSSET(&config
,CS_ARP
)) return;
633 pi
->arph
= (ether_arp
*) (pi
->packet
+ pi
->eth_hlen
);
635 if (ntohs(pi
->arph
->ea_hdr
.ar_op
) == ARPOP_REPLY
) {
636 if (filter_packet(pi
->af
, &pi
->arph
->arp_spa
)) {
637 update_asset_arp(pi
->arph
->arp_sha
, pi
);
639 /* arp_check(eth_hdr,pi->pheader->ts.tv_sec); */
641 vlog(0x3, "[*] ARP TYPE: %d\n",ntohs(pi
->arph
->ea_hdr
.ar_op
));
645 void set_pkt_end_ptr (packetinfo
*pi
)
648 if (pi
->pheader
->len
<= SNAPLENGTH
) {
649 pi
->end_ptr
= (pi
->packet
+ pi
->pheader
->len
);
651 pi
->end_ptr
= (pi
->packet
+ SNAPLENGTH
);
656 void prepare_tcp (packetinfo
*pi
)
658 config
.pr_s
.tcp_recv
++;
659 if (pi
->af
==AF_INET
) {
660 vlog(0x3, "[*] IPv4 PROTOCOL TYPE TCP:\n");
661 pi
->tcph
= (tcp_header
*) (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4));
662 pi
->plen
= (pi
->pheader
->caplen
- (TCP_OFFSET(pi
->tcph
)) * 4 - (IP_HL(pi
->ip4
) * 4) - pi
->eth_hlen
);
663 pi
->payload
= (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4) + (TCP_OFFSET(pi
->tcph
) * 4));
664 } else if (pi
->af
==AF_INET6
) {
665 vlog(0x3, "[*] IPv6 PROTOCOL TYPE TCP:\n");
666 pi
->tcph
= (tcp_header
*) (pi
->packet
+ pi
->eth_hlen
+ IP6_HEADER_LEN
);
667 pi
->plen
= (pi
->pheader
->caplen
- (TCP_OFFSET(pi
->tcph
)) * 4 - IP6_HEADER_LEN
- pi
->eth_hlen
);
668 pi
->payload
= (pi
->packet
+ pi
->eth_hlen
+ IP6_HEADER_LEN
+ (TCP_OFFSET(pi
->tcph
)*4));
670 pi
->proto
= IP_PROTO_TCP
;
671 pi
->s_port
= pi
->tcph
->src_port
;
672 pi
->d_port
= pi
->tcph
->dst_port
;
673 connection_tracking(pi
);
674 //cx_track_simd_ipv4(pi);
676 dump_payload(pi
->payload
, (config
.payload
< pi
->plen
)?config
.payload
:pi
->plen
);
680 void parse_tcp (packetinfo
*pi
)
684 if (TCP_ISFLAGSET(pi
->tcph
, (TF_SYN
))) {
685 if (!TCP_ISFLAGSET(pi
->tcph
, (TF_ACK
))) {
686 if (IS_COSET(&config
,CO_SYN
)) {
687 vlog(0x3, "[*] - Got a SYN from a CLIENT: dst_port:%d\n",ntohs(pi
->tcph
->dst_port
));
692 if (IS_COSET(&config
,CO_SYNACK
)) {
693 vlog(0x3, "[*] Got a SYNACK from a SERVER: src_port:%d\n", ntohs(pi
->tcph
->src_port
));
694 fp_tcp(pi
, CO_SYNACK
);
695 if (pi
->sc
!= SC_SERVER
)
702 // Check payload for known magic bytes that defines files!
704 if (pi
->sc
== SC_CLIENT
&& !ISSET_CXT_DONT_CHECK_CLIENT(pi
)) {
705 if (IS_CSSET(&config
,CS_TCP_CLIENT
)
706 && !ISSET_DONT_CHECK_CLIENT(pi
)) {
707 if (pi
->af
== AF_INET
)
708 client_tcp4(pi
, config
.sig_client_tcp
);
710 client_tcp6(pi
, config
.sig_client_tcp
);
714 } else if (pi
->sc
== SC_SERVER
&& !ISSET_CXT_DONT_CHECK_SERVER(pi
)) {
715 if (IS_CSSET(&config
,CS_TCP_SERVER
)
716 && !ISSET_DONT_CHECK_SERVICE(pi
)) {
717 if (pi
->af
== AF_INET
)
718 service_tcp4(pi
, config
.sig_serv_tcp
);
720 service_tcp6(pi
, config
.sig_serv_tcp
);
724 vlog(0x3, "[*] - NOT CHECKING TCP PACKAGE\n");
728 if (IS_COSET(&config
,CO_ACK
)
729 && TCP_ISFLAGSET(pi
->tcph
, (TF_ACK
))
730 && !TCP_ISFLAGSET(pi
->tcph
, (TF_SYN
))
731 && !TCP_ISFLAGSET(pi
->tcph
, (TF_RST
))
732 && !TCP_ISFLAGSET(pi
->tcph
, (TF_FIN
))) {
733 vlog(0x3, "[*] Got a STRAY-ACK: src_port:%d\n",ntohs(pi
->tcph
->src_port
));
736 } else if (IS_COSET(&config
,CO_FIN
) && TCP_ISFLAGSET(pi
->tcph
, (TF_FIN
))) {
737 vlog(0x3, "[*] Got a FIN: src_port:%d\n",ntohs(pi
->tcph
->src_port
));
740 } else if (IS_COSET(&config
,CO_RST
) && TCP_ISFLAGSET(pi
->tcph
, (TF_RST
))) {
741 vlog(0x3, "[*] Got a RST: src_port:%d\n",ntohs(pi
->tcph
->src_port
));
747 void prepare_udp (packetinfo
*pi
)
749 config
.pr_s
.udp_recv
++;
750 if (pi
->af
==AF_INET
) {
751 vlog(0x3, "[*] IPv4 PROTOCOL TYPE UDP:\n");
752 pi
->udph
= (udp_header
*) (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4));
753 pi
->plen
= pi
->pheader
->caplen
- UDP_HEADER_LEN
-
754 (IP_HL(pi
->ip4
) * 4) - pi
->eth_hlen
;
755 pi
->payload
= (pi
->packet
+ pi
->eth_hlen
+
756 (IP_HL(pi
->ip4
) * 4) + UDP_HEADER_LEN
);
758 } else if (pi
->af
==AF_INET6
) {
759 vlog(0x3, "[*] IPv6 PROTOCOL TYPE UDP:\n");
760 pi
->udph
= (udp_header
*) (pi
->packet
+ pi
->eth_hlen
+ + IP6_HEADER_LEN
);
761 pi
->plen
= pi
->pheader
->caplen
- UDP_HEADER_LEN
-
762 IP6_HEADER_LEN
- pi
->eth_hlen
;
763 pi
->payload
= (pi
->packet
+ pi
->eth_hlen
+
764 IP6_HEADER_LEN
+ UDP_HEADER_LEN
);
766 pi
->proto
= IP_PROTO_UDP
;
767 pi
->s_port
= pi
->udph
->src_port
;
768 pi
->d_port
= pi
->udph
->dst_port
;
769 connection_tracking(pi
);
770 //cx_track_simd_ipv4(pi);
772 dump_payload(pi
->payload
, (config
.payload
< pi
->plen
)?config
.payload
:pi
->plen
);
776 void parse_udp (packetinfo
*pi
)
779 //if (is_set_guess_upd_direction(config)) {
780 udp_guess_direction(pi
); // fix DNS server transfers?
781 // Check for Passive DNS
782 if ( ntohs(pi
->s_port
) == 53 || ntohs(pi
->s_port
) == 5353 ) {
783 // For now - Proof of Concept! - Fix output way
784 if(config
.cflags
& CONFIG_PDNS
) {
785 static char ip_addr_s
[INET6_ADDRSTRLEN
];
786 u_ntop_src(pi
, ip_addr_s
);
787 dump_dns(pi
->payload
, pi
->plen
, stdout
, "\n", ip_addr_s
, pi
->pheader
->ts
.tv_sec
);
790 if (IS_COSET(&config
, CO_DHCP
) && ntohs(pi
->s_port
) == 68 && ntohs(pi
->d_port
) == 67) {
791 dhcp_fingerprint(pi
); /* basic DHCP parsing*/
793 // if (IS_COSET(&config,CO_DNS) && (pi->sc == SC_SERVER && ntohs(pi->s_port) == 53)) passive_dns (pi);
795 if (IS_CSSET(&config
,CS_UDP_SERVICES
)) {
796 if (pi
->af
== AF_INET
) {
798 if (!ISSET_DONT_CHECK_SERVICE(pi
)||!ISSET_DONT_CHECK_CLIENT(pi
)) {
799 // Check for UDP SERVICE
800 service_udp4(pi
, config
.sig_serv_udp
);
802 // UPD Fingerprinting
803 if (IS_COSET(&config
,CO_UDP
)) fp_udp4(pi
, pi
->ip4
, pi
->udph
, pi
->end_ptr
);
804 } else if (pi
->af
== AF_INET6
) {
805 if (!ISSET_DONT_CHECK_SERVICE(pi
)||!ISSET_DONT_CHECK_CLIENT(pi
)) {
806 service_udp6(pi
, config
.sig_client_udp
);
808 /* fp_udp(ip6, ttl, ipopts, len, id, ipflags, df); */
812 vlog(0x3, "[*] - NOT CHECKING UDP PACKAGE\n");
817 void prepare_icmp (packetinfo
*pi
)
819 config
.pr_s
.icmp_recv
++;
820 if (pi
->af
==AF_INET
) {
821 vlog(0x3, "[*] IPv4 PROTOCOL TYPE ICMP:\n");
822 pi
->icmph
= (icmp_header
*) (pi
->packet
+ pi
->eth_hlen
+ (IP_HL(pi
->ip4
) * 4));
823 pi
->proto
= IP_PROTO_ICMP
;
825 } else if (pi
->af
==AF_INET6
) {
826 vlog(0x3, "[*] IPv6 PROTOCOL TYPE ICMP:\n");
827 pi
->icmp6h
= (icmp6_header
*) (pi
->packet
+ pi
->eth_hlen
+ IP6_HEADER_LEN
);
828 pi
->proto
= IP6_PROTO_ICMP
;
833 * DO change ip6->hop_lmt to 0 or something
835 connection_tracking(pi
);
839 void parse_icmp (packetinfo
*pi
)
843 if (IS_COSET(&config
,CO_ICMP
)) {
844 if (pi
->cxt
->check
== 0x00) {
845 pi
->cxt
->check
= 0x10; //for now - stop icmp fp quick
846 if (pi
->af
==AF_INET
) {
847 fp_icmp4(pi
, pi
->ip4
, pi
->icmph
, pi
->end_ptr
);
848 // could look for icmp spesific data in package abcde...
849 // service_icmp(*pi->ip4,*tcph
850 } else if (pi
->af
==AF_INET6
) {
852 fp_icmp6(pi
, pi
->ip6
, pi
->icmp6h
, pi
->end_ptr
);
855 vlog(0x3, "[*] - NOT CHECKING ICMP PACKAGE\n");
860 void prepare_other (packetinfo
*pi
)
862 config
.pr_s
.othert_recv
++;
863 if (pi
->af
==AF_INET
) {
864 vlog(0x3, "[*] IPv4 PROTOCOL TYPE OTHER: %d\n",pi
->ip4
->ip_p
);
866 } else if (pi
->af
==AF_INET6
) {
867 vlog(0x3, "[*] IPv6 PROTOCOL TYPE OTHER: %d\n",pi
->ip6
->next
);
872 connection_tracking(pi
);
876 void parse_other (packetinfo
*pi
)
880 if (pi
->cxt
->check
== 0x00) {
881 if (IS_COSET(&config
,CO_OTHER
)) {
882 pi
->cxt
->check
= 0x01; // no more checks
883 // service_other(*pi->ip4,*transporth);
884 // fp_other(pi->ipX, ttl, ipopts, len, id, ipflags, df);
886 vlog(0x3, "[*] - NOT CHECKING *OTHER* PACKAGE\n");
891 void udp_guess_direction(packetinfo
*pi
)
893 /* Stupid hack :( for DNS/port 53 */
894 if (ntohs(pi
->d_port
) == 53) {
895 if (pi
->sc
== SC_CLIENT
) return;
896 else pi
->sc
= SC_CLIENT
;
898 } else if (ntohs(pi
->s_port
) == 53) {
899 if (pi
->sc
== SC_SERVER
) return;
900 else pi
->sc
= SC_SERVER
;
904 int parse_network (char *net_s
, struct in6_addr
*network
)
908 if (NULL
!= (t
= strchr(net_s
, ':'))) {
910 if (!inet_pton(type
, net_s
, network
)) {
911 perror("parse_nets6");
914 dlog("Network6 %-36s \t -> %08x:%08x:%08x:%08x\n",
920 if (!inet_pton(type
, net_s
, &IP4ADDR(network
))) {
921 perror("parse_nets");
924 dlog("Network4 %16s \t-> 0x%08x\n", net_s
, IP4ADDR(network
));
929 int parse_netmask (char *f
, int type
, struct in6_addr
*netmask
)
933 char output
[MAX_NETS
];
934 // parse netmask into host order
935 if (type
== AF_INET
&& (t
= strchr(f
, '.')) > f
&& t
-f
< 4) {
936 // full ipv4 netmask : dotted quads
937 inet_pton(type
, f
, &IP4ADDR(netmask
));
938 dlog("mask 4 %s \t-> 0x%08x\n", f
, IP4ADDR(netmask
));
939 } else if (type
== AF_INET6
&& NULL
!= (t
= strchr(f
, ':'))) {
940 // full ipv6 netmasÄž
941 dlog("mask 6 %s\n", f
);
942 inet_pton(type
, f
, netmask
);
945 sscanf(f
, "%u", &mask
);
946 dlog("cidr %u \t-> ", mask
);
947 if (type
== AF_INET
) {
948 uint32_t shift
= 32 - mask
;
950 IP4ADDR(netmask
) = ntohl( ((unsigned int)-1 >> shift
)<< shift
);
952 IP4ADDR(netmask
) = 0;
954 dlog("0x%08x\n", IP4ADDR(netmask
));
955 } else if (type
== AF_INET6
) {
958 memset(netmask
, 0, sizeof(struct in6_addr
));
961 netmask
->s6_addr
[j
++] = 0xff;
965 netmask
->s6_addr
[j
] = -1 << (8 - mask
);
968 inet_ntop(type
, &IP4ADDR(netmask
), output
, MAX_NETS
);
969 dlog("mask: %s\n", output
);
971 // pcap packets are in host order.
972 IP6ADDR0(netmask
) = ntohl(IP6ADDR0(netmask
));
973 IP6ADDR1(netmask
) = ntohl(IP6ADDR1(netmask
));
974 IP6ADDR2(netmask
) = ntohl(IP6ADDR2(netmask
));
975 IP6ADDR3(netmask
) = ntohl(IP6ADDR3(netmask
));
982 /* parse strings of the form ip/cidr or ip/mask like:
983 * "10.10.10.10/255.255.255.128,10.10.10.10/25" and
984 * "dead:be:eef2:1aa::b5ff:fe96:37a2/64,..."
986 * an IPv6 address is 8 x 4 hex digits. missing digits are padded with zeroes.
988 void parse_nets(const char *s_net
, fmask
*network
)
990 /* f -> for processing
994 int type
, len
, i
= 0;
995 struct in6_addr network6
, netmask6
;
997 // snet is a mutable copy of the args,freed @ nets_end
999 //snet = calloc(1, len);
1000 snet
= calloc(1, (len
+ 1)); /* to have \0 too :-) */
1001 strncpy(snet
, s_net
, len
);
1003 while (f
&& 0 != (p
= strchr(f
, '/'))) {
1004 // convert network address
1006 type
= parse_network(f
, &network6
);
1007 if (type
!= AF_INET
&& type
!= AF_INET6
) {
1008 perror("parse_network");
1017 parse_netmask(f
, type
, &netmask6
);
1019 // poke in the gathered information
1023 network
[i
].addr
= network6
;
1024 network
[i
].mask
= netmask6
;
1025 network
[i
].type
= type
;
1029 fprintf(stderr
, "parse_nets: invalid address family!\n");
1036 elog("Max networks reached, stopped parsing at %d nets.\n", i
-1);
1041 // continue parsing at p, which might point to another network range
1053 if (inpacket
== 0) {
1054 end_sessions(); /* Need to have correct human output when reading -r pcap */
1057 del_known_services();
1058 del_signature_lists();
1061 if(!ISSET_CONFIG_QUIET(config
)){
1062 print_prads_stats();
1063 if(!config
.pcap_file
)
1066 if (config
.handle
!= NULL
) pcap_close(config
.handle
);
1067 if (ISSET_CONFIG_SYSLOG(config
)) closelog();
1069 olog("[*] prads ended.\n");
1078 olog("Reparsing config file...");
1079 parse_config_file(config
.file
);
1087 void check_interrupt()
1090 if (intr_flag
== 1) {
1092 } else if (intr_flag
== 2) {
1093 update_asset_list();
1094 } else if (intr_flag
== 3) {
1096 } else if (intr_flag
== 4) {
1103 void set_end_sessions()
1107 if (inpacket
== 0) {
1108 tstamp
= time(NULL
);
1110 /* if no cxtracking is turned on - dont log to disk */
1111 /* if (log_cxt == 1) log_expired_cxt(); */
1112 /* if no asset detection is turned on - dont log to disk! */
1113 /* if (log_assets == 1) update_asset_list(); */
1114 update_asset_list();
1118 // install self again
1119 signal(SIGUSR1
, set_end_sessions
);
1122 void print_prads_stats()
1124 extern uint64_t cxtrackerid
; // cxt.c
1125 olog("-- prads:\n");
1126 olog("-- Total packets received from libpcap :%12u\n",config
.pr_s
.got_packets
);
1127 olog("-- Total Ethernet packets received :%12u\n",config
.pr_s
.eth_recv
);
1128 olog("-- Total VLAN packets received :%12u\n",config
.pr_s
.vlan_recv
);
1129 olog("-- Total ARP packets received :%12u\n",config
.pr_s
.arp_recv
);
1130 olog("-- Total IPv4 packets received :%12u\n",config
.pr_s
.ip4_recv
);
1131 olog("-- Total IPv6 packets received :%12u\n",config
.pr_s
.ip6_recv
);
1132 olog("-- Total Other link packets received :%12u\n",config
.pr_s
.otherl_recv
);
1133 olog("-- Total IPinIPv4 packets received :%12u\n",config
.pr_s
.ip4ip_recv
);
1134 olog("-- Total IPinIPv6 packets received :%12u\n",config
.pr_s
.ip6ip_recv
);
1135 olog("-- Total GRE packets received :%12u\n",config
.pr_s
.gre_recv
);
1136 olog("-- Total TCP packets received :%12u\n",config
.pr_s
.tcp_recv
);
1137 olog("-- Total UDP packets received :%12u\n",config
.pr_s
.udp_recv
);
1138 olog("-- Total ICMP packets received :%12u\n",config
.pr_s
.icmp_recv
);
1139 olog("-- Total Other transport packets received :%12u\n",config
.pr_s
.othert_recv
);
1141 olog("-- Total sessions tracked :%12lu\n", cxtrackerid
);
1142 olog("-- Total assets detected :%12u\n",config
.pr_s
.assets
);
1143 olog("-- Total TCP OS fingerprints detected :%12u\n",config
.pr_s
.tcp_os_assets
);
1144 olog("-- Total UDP OS fingerprints detected :%12u\n",config
.pr_s
.udp_os_assets
);
1145 olog("-- Total ICMP OS fingerprints detected :%12u\n",config
.pr_s
.icmp_os_assets
);
1146 olog("-- Total DHCP OS fingerprints detected :%12u\n",config
.pr_s
.dhcp_os_assets
);
1147 olog("-- Total TCP service assets detected :%12u\n",config
.pr_s
.tcp_services
);
1148 olog("-- Total TCP client assets detected :%12u\n",config
.pr_s
.tcp_clients
);
1149 olog("-- Total UDP service assets detected :%12u\n",config
.pr_s
.udp_services
);
1150 olog("-- Total UDP client assets detected :%12u\n",config
.pr_s
.udp_clients
);
1157 olog(" $ prads [options]\n");
1159 olog(" OPTIONS:\n");
1161 olog(" -i <iface> Network device <iface> (default: eth0).\n");
1162 olog(" -r <file> Read pcap <file>.\n");
1163 olog(" -c <file> Read config from <file>\n");
1164 olog(" -b <filter> Apply Berkeley packet filter <filter>.\n");
1165 olog(" -u <user> Run as user <user> (Default: uid 1)\n");
1166 olog(" -g <group> Run as group <group> (Default: gid 1)\n");
1167 olog(" -d Do not drop privileges.\n");
1168 olog(" -a <nets> Specify home nets (eg: '192.168.0.0/25,10.0.0.0/255.0.0.0').\n");
1169 olog(" -D Daemonize.\n");
1170 olog(" -p <pidfile> Name of pidfile - inside chroot\n");
1171 olog(" -l <file> Log assets to <file> (default: '%s')\n", config
.assetlog
);
1172 olog(" -f <FIFO> Log assets to <FIFO>\n");
1173 olog(" -B Log connections to ringbuffer\n");
1174 olog(" -C <dir> Chroot into <dir> before dropping privs.\n");
1175 olog(" -XFRMSAK Flag picker: X - clear flags, F:FIN, R:RST, M:MAC, S:SYN, A:ACK, K:SYNACK\n");
1176 olog(" -UTtI Service checks: U:UDP, T:TCP-server, I:ICMP, t:TCP-cLient\n");
1177 olog(" -P DHCP fingerprinting.\n");
1178 olog(" -s <snaplen> Dump <snaplen> bytes of each payload.\n");
1179 olog(" -v Verbose output - repeat for more verbosity.\n");
1180 olog(" -q Quiet - try harder not to produce output.\n");
1181 olog(" -L <dir> log cxtracker type output to <dir> (will be owned by <uid>).\n");
1182 olog(" -O Connection tracking [O]utput - per-packet!\n");
1183 olog(" -x Conne[x]ion tracking output - New, expired and ended.\n");
1184 olog(" -Z Passive DNS (Experimental).\n");
1185 olog(" -H DHCP fingerprinting (Expermiental).\n");
1186 olog(" -h This help message.\n");
1189 int load_bpf(globalconfig
* conf
, const char* file
)
1194 struct stat statbuf
;
1195 fs
= fopen(file
, "r");
1200 if(fstat(fileno(fs
), &statbuf
)){
1201 perror("oh god my eyes!");
1205 sz
= statbuf
.st_size
;
1206 if(conf
->bpff
) free(conf
->bpff
);
1207 if(!(conf
->bpff
= calloc(sz
, 1))){
1208 perror("mem alloc");
1212 lineptr
= conf
->bpff
;
1213 // read file but ignore comments and newlines
1214 while(fgets(lineptr
, sz
-(conf
->bpff
-lineptr
), fs
)) {
1217 if(lineptr
[i
] != ' ')
1219 // scan ahead and kill comments
1220 for(i
=0;lineptr
[i
];i
++)
1222 case '#': // comment on the line
1223 lineptr
[i
] = '\n'; // end line here
1224 lineptr
[i
+1] = '\0'; // ends outer loop & string
1225 case '\n': // end-of-line
1226 case '\0': // end-of-string
1229 if(i
<=1) continue; // empty line
1230 lineptr
= lineptr
+strlen(lineptr
);
1233 olog("[*] BPF file\t\t %s (%d bytes read)\n", conf
->bpf_file
, sz
);
1234 if(config
.verbose
) olog("BPF: { %s}\n", conf
->bpff
);
1239 int prads_initialize(globalconfig
*conf
)
1241 if (conf
->bpf_file
) {
1242 if(load_bpf(conf
, conf
->bpf_file
)){
1243 elog("[!] Failed to load bpf from file.\n");
1246 if (conf
->pcap_file
) {
1248 if(stat(conf
->pcap_file
, &sb
) || !sb
.st_size
) {
1249 elog("[!] '%s' not a pcap. Bailing.\n", conf
->pcap_file
);
1253 /* Read from PCAP file specified by '-r' switch. */
1254 olog("[*] Reading from file %s\n", conf
->pcap_file
);
1255 if (!(conf
->handle
= pcap_open_offline(conf
->pcap_file
, conf
->errbuf
))) {
1256 olog("[*] Unable to open %s. (%s)\n", conf
->pcap_file
, conf
->errbuf
);
1261 if(conf
->drop_privs_flag
) {
1263 conf
->drop_privs_flag
= 0;
1264 elog("[!] Can't drop privileges, not root.\n");
1266 /* getting numerical ids before chroot call */
1267 gid
= get_gid(conf
->group_name
);
1268 uid
= get_uid(conf
->user_name
, &gid
);
1270 elog("[!] Problem finding user %s group %s\n", conf
->user_name
, conf
->group_name
);
1273 if (gid
&& getuid() == 0 && initgroups(conf
->user_name
, gid
) < 0) {
1274 elog("[!] Unable to init group names (%s/%u)\n", conf
->user_name
, gid
);
1279 /* * look up an available device if non specified */
1280 if (conf
->dev
== 0x0)
1281 conf
->dev
= pcap_lookupdev(conf
->errbuf
);
1285 elog("[*] Error looking up device: '%s', try setting device with -i flag.\n", conf
->errbuf
);
1289 olog("[*] Device: %s\n", conf
->dev
);
1291 if ((conf
->handle
= pcap_open_live(conf
->dev
, SNAPLENGTH
, 1, 500, conf
->errbuf
)) == NULL
) {
1292 elog("[!] Error pcap_open_live: %s \n", conf
->errbuf
);
1295 /* * B0rk if we see an error... */
1296 if (strlen(conf
->errbuf
) > 0) {
1297 elog("[*] Error errbuf: %s \n", conf
->errbuf
);
1301 if(conf
->chroot_dir
){
1303 olog("[*] Chrooting to dir '%s'..\n", conf
->chroot_dir
);
1305 elog("[!] failed to chroot\n");
1309 /* gotta create/chown pidfile before dropping privs */
1311 touch_pid_file(conf
->pidfile
, uid
, gid
);
1313 if (conf
->drop_privs_flag
&& ( uid
|| gid
)) {
1314 olog("[*] Dropping privileges to %s:%s...\n",
1315 conf
->user_name
?conf
->user_name
:"", conf
->group_name
?conf
->group_name
:"");
1316 drop_privs(uid
, gid
);
1318 /* NOTE: we init sancp-style conntrack-logging after dropping privs,
1319 * because the logs need rotation after dropping privs */
1320 if(config
.cxtlogdir
[0] != '\0'){
1321 static char log_prefix
[PATH_MAX
];
1322 snprintf(log_prefix
, PATH_MAX
, "%sstats.%s",
1323 config
.cxtlogdir
, config
.dev
? config
.dev
: "pcap");
1324 int rc
= init_logging(LOG_SGUIL
, log_prefix
, 0);
1326 perror("Logging to sguil output failed!");
1330 if (!is_valid_path(conf
->pidfile
)){
1331 elog("[!] Pidfile '%s' is not writable.\n", conf
->pidfile
);
1335 if (conf
->daemon_flag
) {
1336 olog("[*] Daemonizing...\n");
1339 if (conf
->pidfile
) {
1341 if((rc
=create_pid_file(conf
->pidfile
))) {
1342 elog("[!] pidfile error, wrong permissions or prads already running? %s: %s\n", conf
->pidfile
, strerror(rc
));
1350 void prads_version(void)
1352 olog("[*] prads %s\n", VERSION
);
1353 olog(" Using %s\n", pcap_lib_version());
1354 olog(" Using PCRE version %s\n", pcre_version());
1358 int main(int argc
, char *argv
[])
1361 int ch
= 0, verbose_already
= 0;
1363 vlog(2, "%08x =? %08x, endianness: %s\n\n", 0xdeadbeef, ntohl(0xdeadbeef), (0xdead == ntohs(0xdead)?"big":"little") );
1365 memset(&config
, 0, sizeof(globalconfig
));
1366 set_default_config_options(&config
);
1368 inpacket
= gameover
= intr_flag
= 0;
1370 signal(SIGTERM
, game_over
);
1371 signal(SIGINT
, game_over
);
1372 signal(SIGQUIT
, game_over
);
1373 signal(SIGALRM
, set_end_sessions
);
1374 signal(SIGHUP
, reparse_conf
);
1375 signal(SIGUSR1
, set_end_sessions
);
1377 signal(SIGUSR1
, cxt_log_buckets
);
1380 // do first-pass args parse for commandline-passed config file
1382 while ((ch
= getopt(argc
, argv
, ARGS
)) != -1)
1385 config
.file
= optarg
;
1391 config
.cflags
|= CONFIG_QUIET
;
1401 verbose_already
= 1;
1403 parse_config_file(config
.file
);
1405 // reset verbosity before 2nd coming, but only if set on cli
1411 if(parse_args(&config
, argc
, argv
, ARGS
) != 0){
1415 // we're done parsing configs - now initialize prads
1416 if(ISSET_CONFIG_SYSLOG(config
)) {
1417 openlog("prads", LOG_PID
| LOG_CONS
, LOG_DAEMON
);
1419 if (config
.ringbuffer
) {
1420 rc
= init_logging(LOG_RINGBUFFER
, NULL
, config
.cflags
);
1422 perror("Logging to ringbuffer failed!");
1424 if (config
.cflags
& (CONFIG_VERBOSE
| CONFIG_CXWRITE
| CONFIG_CONNECT
)) {
1425 rc
= init_logging(LOG_STDOUT
, NULL
, config
.cflags
);
1426 if(rc
) perror("Logging to standard out failed!");
1428 if(config
.assetlog
) {
1429 olog("logging to file '%s'\n", config
.assetlog
);
1430 rc
= init_logging(LOG_FILE
, config
.assetlog
, config
.cflags
);
1431 if(rc
) perror("Logging to file failed!");
1434 olog("logging to FIFO '%s'\n", config
.fifo
);
1435 rc
= init_logging(LOG_FIFO
, config
.fifo
, config
.cflags
);
1436 if(rc
) perror("Logging to fifo failed!");
1438 /* moved NOTE: cxtlog is inited in prads_initialize, after dropping privs */
1440 parse_nets(config
.s_net
, network
);
1442 olog("[*] Loading fingerprints:\n");
1443 /* helper macro to avoid duplicate code */
1444 #define load_foo(func, conf, flag, file, hash, len, dump) \
1445 if(config. conf & flag) { \
1447 olog(" %-11s %s\n", # flag, (config. file)); \
1448 _rc = func (config. file, & config. hash, config. len); \
1449 if(_rc) perror( #flag " load failed!"); \
1450 else if(config.verbose > 1) { \
1451 printf("[*] Dumping " #flag " signatures:\n"); \
1452 dump (config. hash, config. len); \
1453 printf("[*] " #flag " signature dump ends.\n"); \
1457 load_foo(load_mac
, cof
, CS_MAC
, sig_file_mac
, sig_mac
, mac_hashsize
, dump_macs
);
1458 load_foo(load_sigs
, ctf
, CO_SYN
, sig_file_syn
, sig_syn
, sig_hashsize
, dump_sigs
);
1459 load_foo(load_sigs
, ctf
, CO_SYNACK
, sig_file_synack
, sig_synack
, sig_hashsize
, dump_sigs
);
1460 load_foo(load_sigs
, ctf
, CO_ACK
, sig_file_ack
, sig_ack
, sig_hashsize
, dump_sigs
);
1461 load_foo(load_sigs
, ctf
, CO_FIN
, sig_file_fin
, sig_fin
, sig_hashsize
, dump_sigs
);
1462 load_foo(load_sigs
, ctf
, CO_RST
, sig_file_rst
, sig_rst
, sig_hashsize
, dump_sigs
);
1463 load_foo(load_dhcp_sigs
, ctf
, CO_DHCP
, sig_file_dhcp
, sig_dhcp
, sig_hashsize
, dump_dhcp_sigs
);
1464 load_foo(load_servicefp_file
, cof
, CS_TCP_SERVER
, sig_file_serv_tcp
, sig_serv_tcp
, sig_hashsize
, dump_sig_service
);
1465 load_foo(load_servicefp_file
, cof
, CS_UDP_SERVICES
, sig_file_serv_udp
, sig_serv_udp
, sig_hashsize
, dump_sig_service
);
1466 load_foo(load_servicefp_file
, cof
, CS_TCP_CLIENT
, sig_file_cli_tcp
, sig_client_tcp
, sig_hashsize
, dump_sig_service
);
1469 display_config(&config
);
1471 prads_initialize(&config
);
1475 /** segfaults on empty pcap! */
1476 struct bpf_program cfilter
; /**/
1477 if ((pcap_compile(config
.handle
, &cfilter
, config
.bpff
, 1, config
.net_mask
)) == -1) {
1478 olog("[*] Error pcap_compile user_filter: %s\n", pcap_geterr(config
.handle
));
1482 if (pcap_setfilter(config
.handle
, &cfilter
)) {
1483 olog("[*] Unable to set pcap filter! %s", pcap_geterr(config
.handle
));
1485 pcap_freecode(&cfilter
);
1488 olog("[*] Sniffing...\n");
1489 pcap_loop(config
.handle
, -1, got_packet
, NULL
);