├── Makefile ├── README ├── edd.h └── edd.c /Makefile: -------------------------------------------------------------------------------- 1 | #Makefile 2 | 3 | CC=gcc 4 | LDFLAGS=-lpcap -lm 5 | CFLAGS=-O3 6 | DCFLAGS=-g 7 | PCFLAGS='-g -pg' 8 | ifneq (${DEBUG},) 9 | CFLAGS = -g -DDEBUG 10 | endif 11 | 12 | OBJECTS = edd.o 13 | 14 | 15 | all: edd 16 | 17 | edd: $(OBJECTS) 18 | $(CC) $(OCFLAGS) -o $@ $(OBJECTS) $(LDFLAGS) 19 | 20 | debug: 21 | ${MAKE} DEBUG=y 22 | 23 | profile: 24 | ${MAKE} CFLAGS+=${PCFLAGS} 25 | 26 | clean: 27 | -rm -v $(OBJECTS) 28 | -rm edd 29 | 30 | indent: 31 | find -type f -name '*.[ch]' | xargs indent -kr -i4 -cdb -sc -sob -ss -ncs -ts8 -nut 32 | 33 | # oldschool header file dependency checking. 34 | deps: 35 | -rm -f deps.d 36 | for i in *.c; do gcc -MM $$i >> deps.d; done 37 | 38 | ifneq ($(wildcard deps.d),) 39 | include deps.d 40 | endif 41 | 42 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | edd: Entropy DDoS Detector 2 | 3 | * Author: comotion@users.sf.net 4 | * Idea by breno.silva@gmail.com 5 | http://lists.openinfosecfoundation.org/pipermail/oisf-wg-portscan/2009-October/000023.html 6 | * Thanks to ebf0 (http://www.gamelinux.org/) whose support code is good enough 7 | * License? If U have the code U have the GPL... >:-P 8 | 9 | Entropy H(P1) + H(P2) + ... + H(Pi) > H(P1P2..Pi) => DDOS 10 | 11 | 12 | Pseudo code: 13 | # can segment into destport or src:port:dst:port 14 | for each packet 15 | count set bits 16 | count packet bits 17 | sum_entropy = Entropy(packet); 18 | track window of n last packets{ 19 | increase set & total bit values 20 | if(H(window) > H(p1p2..pwin) 21 | => DDOS! 22 | } 23 | 24 | /* calculate the simple entropy of a packet, ie 25 | * assume all bits are equiprobable and randomly distributed 26 | * 27 | * needs work: do this with pure, positive ints? 28 | * tresholds? markov chains? averaging? 29 | * SIMD bitcounts? 30 | * 31 | * check this with our friend the kolmogorov 32 | */ 33 | 34 | Special: 35 | - uses simplistic approximation of Entropy: bits set 36 | - uses very fast implementation of bitcount (lookup table or parallel) 37 | - counts Entropy for all packets, does not segment on port 38 | 39 | -------------------------------------------------------------------------------- /edd.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** This file is a part of edd. 3 | ** 4 | ** Copyright (C) 2009, Kacper Wysocki 5 | ** 6 | ** This program is free software; you can redistribute it and/or modify 7 | ** it under the terms of the GNU General Public License as published by 8 | ** the Free Software Foundation; either version 2 of the License, or 9 | ** (at your option) any later version. 10 | ** 11 | ** This program is distributed in the hope that it will be useful, 12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ** GNU General Public License for more details. 15 | ** 16 | ** You should have received a copy of the GNU General Public License 17 | ** along with this program; if not, write to the Free Software 18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | ** 20 | */ 21 | 22 | /* D E F I N E S *****************************************************/ 23 | #define BIN_NAME "edd" 24 | #define VERSION "0.0.1" 25 | #define SNAPLENGTH 1600 26 | 27 | #define ETHERNET_TYPE_IP 0x0800 28 | #define ETHERNET_TYPE_ARP 0x0806 29 | #define ETHERNET_TYPE_IPV6 0x86dd 30 | #define ETHERNET_TYPE_8021Q 0x8100 31 | #define ETHERNET_TYPE_802Q1MT 0x9100 32 | #define ETHERNET_TYPE_802Q1MT2 0x9200 33 | #define ETHERNET_TYPE_802Q1MT3 0x9300 34 | #define ETHERNET_TYPE_8021AD 0x88a8 35 | 36 | #define IP_PROTO_TCP 6 37 | #define IP_PROTO_UDP 17 38 | #define IP_PROTO_ICMP 1 39 | #define IP6_PROTO_ICMP 58 40 | 41 | #define IP4_HEADER_LEN 20 42 | #define IP6_HEADER_LEN 40 43 | #define TCP_HEADER_LEN 20 44 | #define UDP_HEADER_LEN 8 45 | #define ICMP_HEADER_LEN 4 46 | #define ETHERNET_HEADER_LEN 14 47 | #define ETHERNET_8021Q_HEADER_LEN 18 48 | #define ETHERNET_802Q1MT_HEADER_LEN 22 49 | 50 | #define TF_FIN 0x01 51 | #define TF_SYN 0x02 52 | #define TF_RST 0x04 53 | #define TF_PUSH 0x08 54 | #define TF_ACK 0x10 55 | #define TF_URG 0x20 56 | #define TF_ECE 0x40 57 | #define TF_CWR 0x80 58 | #define TF_SYNACK 0x12 59 | #define TF_NORESERVED (TF_FIN|TF_SYN|TF_RST|TF_PUSH|TF_ACK|TF_URG) 60 | #define TF_FLAGS (TF_FIN|TF_SYN|TF_RST|TF_ACK|TF_URG|TF_ECE|TF_CWR) 61 | 62 | #define SUCCESS 0 63 | #define ERROR 1 64 | #define STDBUF 1024 65 | 66 | /* D A T A S T R U C T U R E S *********************************************/ 67 | 68 | /* 69 | * Ethernet header 70 | */ 71 | 72 | typedef struct _ether_header { 73 | u_char ether_dst[6]; /* destination MAC */ 74 | u_char ether_src[6]; /* source MAC */ 75 | 76 | union 77 | { 78 | struct etht 79 | { 80 | u_short ether_type; /* ethernet type (normal) */ 81 | } etht; 82 | 83 | struct qt 84 | { 85 | u_short eth_t_8021; /* ethernet type/802.1Q tag */ 86 | u_short eth_t_8_vid; 87 | u_short eth_t_8_type; 88 | } qt; 89 | 90 | struct qot 91 | { 92 | u_short eth_t_80212; /* ethernet type/802.1QinQ */ 93 | u_short eth_t_82_mvid; 94 | u_short eth_t_82_8021; 95 | u_short eth_t_82_vid; 96 | u_short eth_t_82_type; 97 | } qot; 98 | } vlantag; 99 | 100 | #define eth_ip_type vlantag.etht.ether_type 101 | 102 | #define eth_8_type vlantag.qt.eth_t_8021 103 | #define eth_8_vid vlantag.qt.eth_t_8_vid 104 | #define eth_8_ip_type vlantag.qt.eth_t_8_type 105 | 106 | #define eth_82_type vlantag.qot.eth_t_80212 107 | #define eth_82_mvid vlantag.qot.eth_t_82_mvid 108 | #define eth_82_8021 vlantag.qot.eth_t_82_8021 109 | #define eth_82_vid vlantag.qot.eth_t_82_vid 110 | #define eth_82_ip_type vlantag.qot.eth_t_82_type 111 | 112 | } ether_header; 113 | 114 | /* 115 | * IPv4 header 116 | */ 117 | 118 | typedef struct _ip4_header { 119 | uint8_t ip_vhl; /* version << 4 | header length >> 2 */ 120 | uint8_t ip_tos; /* type of service */ 121 | uint16_t ip_len; /* total length */ 122 | uint16_t ip_id; /* identification */ 123 | uint16_t ip_off; /* fragment offset field */ 124 | uint8_t ip_ttl; /* time to live */ 125 | uint8_t ip_p; /* protocol */ 126 | uint16_t ip_csum; /* checksum */ 127 | uint32_t ip_src; /* source address */ 128 | uint32_t ip_dst; /* dest address */ 129 | } ip4_header; 130 | 131 | #define IP_RF 0x8000 /* reserved fragment flag */ 132 | #define IP_DF 0x4000 /* dont fragment flag */ 133 | #define IP_MF 0x2000 /* more fragments flag */ 134 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 135 | #define IP_HL(ip4_header) (((ip4_header)->ip_vhl) & 0x0f) 136 | #define IP_V(ip4_header) (((ip4_header)->ip_vhl) >> 4) 137 | 138 | /* 139 | * IPv6 header 140 | */ 141 | 142 | typedef struct _ip6_header { 143 | uint32_t vcl; /* version, class, and label */ 144 | uint16_t len; /* length of the payload */ 145 | uint8_t next; /* next header 146 | * Uses the same flags as 147 | * the IPv4 protocol field */ 148 | uint8_t hop_lmt; /* hop limit */ 149 | struct in6_addr ip_src; /* source address */ 150 | struct in6_addr ip_dst; /* dest address */ 151 | } ip6_header; 152 | 153 | /* 154 | * TCP header 155 | */ 156 | 157 | typedef struct _tcp_header { 158 | uint16_t src_port; /* source port */ 159 | uint16_t dst_port; /* destination port */ 160 | uint32_t t_seq; /* sequence number */ 161 | uint32_t t_ack; /* acknowledgement number */ 162 | uint8_t t_offx2; /* data offset, rsvd */ 163 | uint8_t t_flags; /* tcp flags */ 164 | uint16_t t_win; /* window */ 165 | uint16_t t_csum; /* checksum */ 166 | uint16_t t_urgp; /* urgent pointer */ 167 | } tcp_header; 168 | 169 | #define TCP_OFFSET(tcp_header) (((tcp_header)->t_offx2 & 0xf0) >> 4) 170 | #define TCP_X2(tcp_header) ((tcp_header)->t_offx2 & 0x0f) 171 | #define TCP_ISFLAGSET(tcp_header, flags) (((tcp_header)->t_flags & (flags)) == (flags)) 172 | 173 | /* 174 | * UDP header 175 | */ 176 | 177 | typedef struct _udp_header { 178 | uint16_t src_port; /* source port */ 179 | uint16_t dst_port; /* destination port */ 180 | uint16_t len; /* length of the payload */ 181 | uint16_t csum; /* checksum */ 182 | } udp_header; 183 | 184 | /* 185 | * ICMP header 186 | */ 187 | 188 | typedef struct _icmp_header { 189 | uint8_t type; 190 | uint8_t code; 191 | uint16_t csum; 192 | union 193 | { 194 | uint8_t pptr; 195 | 196 | struct in_addr gwaddr; 197 | 198 | struct idseq 199 | { 200 | uint16_t id; 201 | uint16_t seq; 202 | } idseq; 203 | 204 | int sih_void; 205 | 206 | struct pmtu 207 | { 208 | uint16_t ipm_void; 209 | uint16_t nextmtu; 210 | } pmtu; 211 | 212 | struct rtradv 213 | { 214 | uint8_t num_addrs; 215 | uint8_t wpa; 216 | uint16_t lifetime; 217 | } rtradv; 218 | } icmp_hun; 219 | 220 | #define s_icmp_pptr icmp_hun.pptr 221 | #define s_icmp_gwaddr icmp_hun.gwaddr 222 | #define s_icmp_id icmp_hun.idseq.id 223 | #define s_icmp_seq icmp_hun.idseq.seq 224 | #define s_icmp_void icmp_hun.sih_void 225 | #define s_icmp_pmvoid icmp_hun.pmtu.ipm_void 226 | #define s_icmp_nextmtu icmp_hun.pmtu.nextmtu 227 | #define s_icmp_num_addrs icmp_hun.rtradv.num_addrs 228 | #define s_icmp_wpa icmp_hun.rtradv.wpa 229 | #define s_icmp_lifetime icmp_hun.rtradv.lifetime 230 | 231 | union 232 | { 233 | /* timestamp */ 234 | struct ts 235 | { 236 | uint32_t otime; 237 | uint32_t rtime; 238 | uint32_t ttime; 239 | } ts; 240 | 241 | /* IP header for unreach */ 242 | struct ih_ip 243 | { 244 | ip4_header *ip; 245 | /* options and then 64 bits of data */ 246 | } ip; 247 | 248 | struct ra_addr 249 | { 250 | uint32_t addr; 251 | uint32_t preference; 252 | } radv; 253 | 254 | uint32_t mask; 255 | 256 | char data[1]; 257 | 258 | } icmp_dun; 259 | #define s_icmp_otime icmp_dun.ts.otime 260 | #define s_icmp_rtime icmp_dun.ts.rtime 261 | #define s_icmp_ttime icmp_dun.ts.ttime 262 | #define s_icmp_ip icmp_dun.ih_ip 263 | #define s_icmp_radv icmp_dun.radv 264 | #define s_icmp_mask icmp_dun.mask 265 | #define s_icmp_data icmp_dun.data 266 | } icmp_header; 267 | 268 | typedef struct _icmp6_header { 269 | uint8_t type; /* type field */ 270 | uint8_t code; /* code field */ 271 | uint16_t csum; /* checksum field */ 272 | union 273 | { 274 | uint32_t icmp6_data32[1]; /* type-specific field */ 275 | uint16_t icmp6_data16[2]; /* type-specific field */ 276 | uint8_t icmp6_data8[4]; /* type-specific field */ 277 | } icmp6_data; 278 | #define icmp6_id icmp6_data.icmp6_data16[0] /* echo request/reply */ 279 | #define icmp6_seq icmp6_data.icmp6_data16[1] /* echo request/reply */ 280 | } icmp6_header; 281 | 282 | #define ICMP6_UNREACH 1 283 | #define ICMP6_BIG 2 284 | #define ICMP6_TIME 3 285 | #define ICMP6_PARAMS 4 286 | #define ICMP6_ECHO 128 287 | #define ICMP6_REPLY 129 288 | 289 | /* Minus 1 due to the 'body' field */ 290 | #define ICMP6_MIN_HEADER_LEN (sizeof(ICMP6Hdr) ) 291 | 292 | /* P R O T O T Y P E S ******************************************************/ 293 | 294 | -------------------------------------------------------------------------------- /edd.c: -------------------------------------------------------------------------------- 1 | /* ppacket. Detect DDOS thru entropy 2 | * 3 | * Author: comotion@users.sf.net 4 | * Idea by breno.silva@gmail.com 5 | http://lists.openinfosecfoundation.org/pipermail/oisf-wg-portscan/2009-October/000023.html 6 | * Thanks to ebf0 (http://www.gamelinux.org/) whose support code is good enough. 7 | * License? If U have the code U have the GPL... >:-P 8 | 9 | Entropy H(P1) + H(P2) + ... + H(Pi) > H(P1P2..Pi) => DDOS 10 | 11 | 12 | Pseudo code: 13 | for each packet 14 | count set bits 15 | count packet bits 16 | sum_entropy = Entropy(packet); 17 | track window of n last packets{ 18 | increase set & total bit values 19 | if(H(window) > H(p1p2..pwin) 20 | => DDOS! 21 | } 22 | done 23 | 24 | # can segment into destport or src:port:dst:port 25 | TODO: identify involved services/hosts/networks. 26 | foreach port in window 27 | do entropy counts per port 28 | foreach dst:port in window 29 | do entropy counts per host:port 30 | do entropy counts per host 31 | foreach src in window 32 | do entropy counts per src 33 | foreach TCP(syn,rst,fin) in window 34 | do entropy counts per class 35 | foreach data packet 36 | do entropy counts on data 37 | register src: dst:port 38 | graph entropy values / bits of entropy 39 | 40 | + better ways to compute entropy (see simple_entropy()) 41 | -> tresholds, markov chains, averaging, compression: huffman window or PPZ 42 | */ 43 | 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include "edd.h" 64 | 65 | static int verbose, inpacket, intr_flag, use_syslog; 66 | 67 | time_t timecnt,tstamp; 68 | pcap_t *handle; 69 | static char *dev,*chroot_dir; 70 | static char *group_name, *user_name, *true_pid_name; 71 | static char *pidfile = "edd.pid"; 72 | static char *pidpath = "/var/run"; 73 | static int verbose, inpacket, intr_flag, use_syslog; 74 | static int profile_packet; 75 | 76 | 77 | /* our window of packets */ 78 | //#define P_WINDOW 0xFF // 256 79 | #define DEFAULT_WINDOW 0xFF 80 | #define DEFAULT_TRESH 1200.0 81 | static double tresh = DEFAULT_TRESH; 82 | static uint32_t p_window = DEFAULT_WINDOW; 83 | static uint32_t *p_set; 84 | static uint32_t *p_tot; 85 | static double *p_entropy; 86 | static uint32_t head = 0, tail = 0; 87 | static uint32_t b_tot = 0, b_set = 0; 88 | 89 | void game_over() { 90 | fprintf(stderr, "it is over my friend\n"); 91 | if ( inpacket == 0 ) { 92 | pcap_close(handle); 93 | exit (0); 94 | } 95 | intr_flag = 1; 96 | } 97 | 98 | /* For each byte, for each bit: count bits. Kernighan style */ 99 | inline uint32_t count_bits(const u_char *packet, const uint32_t p_len) 100 | { 101 | const uint32_t *ptr = (uint32_t *) packet; 102 | const uint32_t *end = (uint32_t *) (packet + p_len); 103 | uint32_t v; // count the number of bits set in v 104 | uint8_t c; // c accumulates the total bits set in v 105 | uint32_t set_bits = 0; 106 | while (ptr < end){ 107 | v = *ptr++; 108 | for (c = 0; v; c++) { 109 | v &= v - 1; // clear the least significant bit set 110 | } 111 | set_bits += c; 112 | } 113 | return set_bits; 114 | } 115 | 116 | /* count bits in parallel 117 | * How? With magick bit patterns. 118 | * Thx go to http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel 119 | * The B array, expressed as binary, is: 120 | 0x1235467A = 01110101 00010010 10001010 11101101 121 | B[0] = 0x55555555 = 01010101 01010101 01010101 01010101 122 | B[1] = 0x33333333 = 00110011 00110011 00110011 00110011 123 | B[2] = 0x0F0F0F0F = 00001111 00001111 00001111 00001111 124 | B[3] = 0x00FF00FF = 00000000 11111111 00000000 11111111 125 | B[4] = 0x0000FFFF = 00000000 00000000 11111111 11111111 126 | 127 | We can adjust the method for larger integer sizes by continuing with the patterns for the Binary Magic Numbers, B and S. If there are k bits, then we need the arrays S and B to be ceil(lg(k)) elements long, and we must compute the same number of expressions for c as S or B are long. For a 32-bit v, 16 operations are used. 128 | */ 129 | inline uint32_t count_bits_p(const u_char *packet, const uint32_t p_len) 130 | { 131 | uint32_t v, c, set_bits = 0; 132 | static const int S[] = { 1, 2, 4, 8, 16}; 133 | static const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF}; 134 | 135 | const uint32_t *ptr = (uint32_t *) packet; 136 | const uint32_t *end = (uint32_t *) (packet + p_len); 137 | while(end > ptr){ 138 | v = *ptr++; 139 | c = v - ((v >> 1) & B[0]); 140 | c = ((c >> S[1]) & B[1]) + (c & B[1]); 141 | c = ((c >> S[2]) + c) & B[2]; 142 | c = ((c >> S[3]) + c) & B[3]; 143 | c = ((c >> S[4]) + c) & B[4]; 144 | set_bits += c; 145 | } 146 | return set_bits; 147 | } 148 | 149 | /* this algo does 4 bytes at a time. Note! what about garbage padding? */ 150 | uint32_t count_bits_pp(const u_char *packet, const uint32_t p_len) 151 | { 152 | uint32_t v, set_bits = 0; 153 | const uint32_t *ptr = (uint32_t *) packet; 154 | const uint32_t *end = (uint32_t *) (packet + p_len); 155 | 156 | while(end > ptr){ 157 | v = *ptr++; 158 | //fprintf(stderr, "%08p ", v); 159 | v = v - ((v >> 1) & 0x55555555); // reuse input as temporary 160 | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp 161 | set_bits += ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count 162 | } 163 | /* last N<4 bytes */ 164 | //uint8_t mod = p_len % 4; 165 | //set_bits += count_bits((uint8_t*)ptr,p_len % 4); 166 | //fprintf(stderr, "\n"); 167 | return set_bits; 168 | } 169 | 170 | /* same dog, except use 64bit datatype*/ 171 | uint32_t count_bits_64(const u_char *packet, const uint32_t p_len) 172 | { 173 | uint64_t v, set_bits = 0; 174 | const uint64_t *ptr = (uint64_t *) packet; 175 | const uint64_t *end = (uint64_t *) (packet + p_len); 176 | 177 | while(end > ptr){ 178 | v = *ptr++; 179 | //fprintf(stderr, "%08p ", v); 180 | v = v - ((v >> 1) & 0x5555555555555555); // reuse input as temporary 181 | v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333); // temp 182 | v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0F; 183 | set_bits += (v * 0x0101010101010101) >> (sizeof(v) - 1) * CHAR_BIT; // count 184 | } 185 | //set_bits += count_bits_p((uint8_t *)ptr, p_len % 4); 186 | //fprintf(stderr, "\n"); 187 | return set_bits; 188 | } 189 | 190 | /* this can be generalized if we have a 64bit or 128 bit type T 191 | v = v - ((v >> 1) & (T)~(T)0/3); // temp 192 | v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp 193 | v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp 194 | c = (T)(v * ((T)~(T)0/255)) >> (sizeof(v) - 1) * CHAR_BIT; // count 195 | */ 196 | 197 | /* simplistic bit-by-bit implementation */ 198 | inline uint32_t count_bits_kw(const u_char *packet, const uint32_t p_len) 199 | { 200 | uint32_t tmp; 201 | uint32_t set_bits = 0; 202 | // byte for byte 203 | const u_char *ptr = packet; 204 | while(ptr != packet + p_len){ 205 | tmp = *ptr; 206 | while(tmp){ 207 | // isolate bit 208 | set_bits += tmp & 0x1; 209 | tmp >>= 1; 210 | } 211 | ptr++; 212 | } 213 | return set_bits; 214 | } 215 | 216 | 217 | /* count bits by lookup table */ 218 | static const unsigned char BitsSetTable256[256] = 219 | { 220 | # define B2(n) n, n+1, n+1, n+2 221 | # define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2) 222 | # define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2) 223 | B6(0), B6(1), B6(1), B6(2) 224 | }; 225 | /* 226 | // To initially generate the table algorithmically: 227 | BitsSetTable256[0] = 0; 228 | for (int i = 0; i < 256; i++) 229 | { 230 | BitsSetTable256[i] = (i & 1) + BitsSetTable256[i / 2]; 231 | } 232 | */ 233 | 234 | 235 | inline uint32_t count_bits_t1(const u_char *packet, const uint32_t p_len){ 236 | 237 | uint32_t v, set_bits = 0; 238 | const uint32_t *ptr = (uint32_t *) packet; 239 | const uint32_t *end = (uint32_t *) (packet + p_len); 240 | 241 | while(end >= ptr){ 242 | v = *ptr++; // count the number of bits set in 32-bit value v 243 | 244 | // Option 1: 245 | set_bits += BitsSetTable256[v & 0xff] + 246 | BitsSetTable256[(v >> 8) & 0xff] + 247 | BitsSetTable256[(v >> 16) & 0xff] + 248 | BitsSetTable256[v >> 24]; 249 | } 250 | return set_bits; 251 | } 252 | 253 | inline uint32_t count_bits_t2(const u_char *packet, const uint32_t p_len){ 254 | 255 | uint32_t v, set_bits = 0; 256 | const uint32_t *ptr = (uint32_t *) packet; 257 | const uint32_t *end = (uint32_t *) (packet + p_len); 258 | unsigned char *p; 259 | 260 | while(end >= ptr){ 261 | v = *ptr++; // count the number of bits set in 32-bit value v 262 | //unsigned int c; // c is the total bits set in v 263 | 264 | // Option 2: 265 | p = (unsigned char *) &v; 266 | set_bits += BitsSetTable256[p[0]] + 267 | BitsSetTable256[p[1]] + 268 | BitsSetTable256[p[2]] + 269 | BitsSetTable256[p[3]]; 270 | } 271 | return set_bits; 272 | } 273 | 274 | 275 | /* Could do algo selection based on best performance */ 276 | void packet_profiler (const u_char *packet, const uint32_t p_len) 277 | { 278 | volatile uint64_t S, s, e; 279 | const uint32_t p_bits = p_len*8; 280 | __asm__ __volatile__("cpuid: rdtsc;" : "=A" (s) :: "ebx", "ecx", "memory"); 281 | uint32_t set_bits = count_bits_pp(packet, p_len); 282 | __asm__ volatile("rdtsc":"=A"(e)); 283 | printf("== %8llu == PP\n", e-s); 284 | 285 | __asm__ volatile("rdtsc":"=A"(s)); 286 | set_bits = count_bits_64(packet, p_len); 287 | __asm__ volatile("rdtsc":"=A"(e)); 288 | printf("== %8llu == 64\n", e-s); 289 | 290 | __asm__ volatile("rdtsc":"=A"(s)); 291 | set_bits = count_bits_t1(packet, p_len); 292 | __asm__ volatile("rdtsc":"=A"(e)); 293 | printf("== %8llu == T1\n", e-s); 294 | 295 | __asm__ volatile("rdtsc":"=A"(s)); 296 | set_bits = count_bits_t2(packet, p_len); 297 | __asm__ volatile("rdtsc":"=A"(e)); 298 | printf("== %8llu == T2\n", e-s); 299 | 300 | __asm__ volatile("rdtsc":"=A"(s)); 301 | set_bits = count_bits_p(packet, p_len); 302 | __asm__ volatile("rdtsc":"=A"(e)); 303 | printf("== %8llu == P \n", e-s); 304 | 305 | __asm__ volatile("rdtsc":"=A"(s)); 306 | set_bits = count_bits(packet, p_len); 307 | __asm__ volatile("rdtsc":"=A"(e)); 308 | printf("== %8llu == KR\n", e-s); 309 | 310 | __asm__ volatile("rdtsc":"=A"(s)); 311 | set_bits = count_bits_kw(packet, p_len); 312 | __asm__ volatile("rdtsc":"=A"(e)); 313 | printf("== %8llu == KW\n", e-s); 314 | } 315 | 316 | /* calculate the simple entropy of a packet, ie 317 | * assume all bits are equiprobable and randomly distributed 318 | * 319 | * needs work: do this with pure, positive ints? 320 | * log(x/y) = log(x) - log (y) : (-set/total)=(log(set)-log(total) 321 | * tresholds? markov chains? averaging? 322 | * 323 | * check this with our friend the kolmogorov 324 | * 325 | * Basis for this entropy: just guessing: 326 | * Entropy(set_bits) - Entropy (unset_bits) + E(total) 327 | */ 328 | 329 | double simple_entropy(double set_bits, double total_bits) 330 | { 331 | 332 | /* oldscool 333 | return total_bits * (( -set_bits / total_bits )*log2(set_bits/total_bits) 334 | - (1 - (set_bits / total_bits) * log2(1 - (set_bits/total_bits)))) 335 | + log2(total_bits); 336 | */ 337 | 338 | return 339 | ( -set_bits )*(log2(set_bits)-log2(total_bits)) 340 | - 341 | ( total_bits - set_bits) * ( log2 (total_bits - set_bits) - log2(total_bits) ) //log2(1 - (set_bits/total_bits)) 342 | + log2(total_bits) ; 343 | } 344 | 345 | static uint32_t packet_count; 346 | 347 | void got_packet_profile (u_char *useless,const struct pcap_pkthdr *pheader, const u_char *packet) 348 | { 349 | static char flag; 350 | if ( intr_flag != 0 ) { game_over(); } 351 | inpacket = 1; 352 | const uint32_t p_len = ((pheader->len > SNAPLENGTH)?SNAPLENGTH:pheader->len); 353 | 354 | packet_profiler(packet, p_len); 355 | } 356 | 357 | void got_packet (u_char *useless,const struct pcap_pkthdr *pheader, const u_char *packet) 358 | { 359 | static char flag; 360 | if ( intr_flag != 0 ) { game_over(); } 361 | inpacket = 1; 362 | tstamp = time(NULL); 363 | const uint32_t p_len = ((pheader->len > SNAPLENGTH)?SNAPLENGTH:pheader->len); 364 | const uint32_t bits = p_len*8; 365 | 366 | uint32_t set = count_bits_64(packet, p_len); 367 | 368 | p_tot[head] = bits; 369 | p_set[head] = set; 370 | p_entropy[head] = simple_entropy(set, bits); 371 | 372 | packet_count++; 373 | //printf("[%lu] %lu/%lu, E(%f)\n", head, set, bits, p_entropy[head]); 374 | if (packet_count >= p_window) { 375 | // we have some packets for analysis 376 | uint32_t k, total_set = 0, total_bits = 0; 377 | double sum_entropy = 0; 378 | for(k = 0; k < p_window; k++){ 379 | total_set += p_set[k]; 380 | total_bits+= p_tot[k]; 381 | sum_entropy += p_entropy[k]; 382 | } 383 | double joint_entropy = simple_entropy(total_set, total_bits); 384 | if(tresh < sum_entropy - joint_entropy ){ 385 | if (!flag) 386 | fprintf(stderr, "ddos attack!!! Entropy(%f) < Total_Entropy(%f) over %lu bits\n", 387 | joint_entropy, sum_entropy, total_bits); 388 | flag = 1; 389 | }else{ 390 | if (flag) 391 | fprintf(stdout, "no news, Entropy(%f) >= Total_Entropy(%f) over %lu bits\n", 392 | joint_entropy, sum_entropy, total_bits); 393 | flag = 0; 394 | } 395 | } 396 | 397 | head = (head + 1) % p_window; 398 | 399 | 400 | ether_header *eth_hdr; 401 | eth_hdr = (ether_header *) (packet); 402 | u_short eth_type; 403 | eth_type = ntohs(eth_hdr->eth_ip_type); 404 | int eth_header_len; 405 | eth_header_len = ETHERNET_HEADER_LEN; 406 | 407 | /* sample code from cxtracker 408 | 409 | u_short p_bytes; 410 | if ( eth_type == ETHERNET_TYPE_8021Q ) { 411 | // printf("[*] ETHERNET TYPE 8021Q\n"); 412 | eth_type = ntohs(eth_hdr->eth_8_ip_type); 413 | eth_header_len +=4; 414 | } 415 | 416 | else if ( eth_type == (ETHERNET_TYPE_802Q1MT|ETHERNET_TYPE_802Q1MT2|ETHERNET_TYPE_802Q1MT3|ETHERNET_TYPE_8021AD) ) { 417 | // printf("[*] ETHERNET TYPE 802Q1MT\n"); 418 | eth_type = ntohs(eth_hdr->eth_82_ip_type); 419 | eth_header_len +=8; 420 | } 421 | 422 | if ( eth_type == ETHERNET_TYPE_IP ) { 423 | // printf("[*] Got IPv4 Packet...\n"); 424 | ip4_header *ip4; 425 | ip4 = (ip4_header *) (packet + eth_header_len); 426 | p_bytes = (ip4->ip_len - (IP_HL(ip4)*4)); 427 | struct in6_addr ip_src, ip_dst; 428 | ip_src.s6_addr32[0] = ip4->ip_src; 429 | ip_src.s6_addr32[1] = 0; 430 | ip_src.s6_addr32[2] = 0; 431 | ip_src.s6_addr32[3] = 0; 432 | ip_dst.s6_addr32[0] = ip4->ip_dst; 433 | ip_dst.s6_addr32[1] = 0; 434 | ip_dst.s6_addr32[2] = 0; 435 | ip_dst.s6_addr32[3] = 0; 436 | 437 | if ( ip4->ip_p == IP_PROTO_TCP ) { 438 | tcp_header *tcph; 439 | tcph = (tcp_header *) (packet + eth_header_len + (IP_HL(ip4)*4)); 440 | // printf("[*] IPv4 PROTOCOL TYPE TCP:\n"); 441 | cx_track(ip_src, tcph->src_port, ip_dst, tcph->dst_port, ip4->ip_p, p_bytes, tcph->t_flags, tstamp, AF_INET); 442 | inpacket = 0; 443 | return; 444 | } 445 | else if (ip4->ip_p == IP_PROTO_UDP) { 446 | udp_header *udph; 447 | udph = (udp_header *) (packet + eth_header_len + (IP_HL(ip4)*4)); 448 | // printf("[*] IPv4 PROTOCOL TYPE UDP:\n"); 449 | cx_track(ip_src, udph->src_port, ip_dst, udph->dst_port, ip4->ip_p, p_bytes, 0, tstamp, AF_INET); 450 | inpacket = 0; 451 | return; 452 | } 453 | else if (ip4->ip_p == IP_PROTO_ICMP) { 454 | icmp_header *icmph; 455 | icmph = (icmp_header *) (packet + eth_header_len + (IP_HL(ip4)*4)); 456 | // printf("[*] IP PROTOCOL TYPE ICMP\n"); 457 | cx_track(ip_src, icmph->s_icmp_id, ip_dst, icmph->s_icmp_id, ip4->ip_p, p_bytes, 0, tstamp, AF_INET); 458 | inpacket = 0; 459 | return; 460 | } 461 | else { 462 | // printf("[*] IPv4 PROTOCOL TYPE OTHER: %d\n",ip4->ip_p); 463 | cx_track(ip_src, ip4->ip_p, ip_dst, ip4->ip_p, ip4->ip_p, p_bytes, 0, tstamp, AF_INET); 464 | inpacket = 0; 465 | return; 466 | } 467 | } 468 | 469 | else if ( eth_type == ETHERNET_TYPE_IPV6) { 470 | // printf("[*] Got IPv6 Packet...\n"); 471 | ip6_header *ip6; 472 | ip6 = (ip6_header *) (packet + eth_header_len); 473 | if ( ip6->next == IP_PROTO_TCP ) { 474 | tcp_header *tcph; 475 | tcph = (tcp_header *) (packet + eth_header_len + IP6_HEADER_LEN); 476 | // printf("[*] IPv6 PROTOCOL TYPE TCP:\n"); 477 | cx_track(ip6->ip_src, tcph->src_port, ip6->ip_dst, tcph->dst_port, ip6->next, ip6->len, tcph->t_flags, tstamp, AF_INET6); 478 | inpacket = 0; 479 | return; 480 | } 481 | else if (ip6->next == IP_PROTO_UDP) { 482 | udp_header *udph; 483 | udph = (udp_header *) (packet + eth_header_len + IP6_HEADER_LEN); 484 | // printf("[*] IPv6 PROTOCOL TYPE UDP:\n"); 485 | cx_track(ip6->ip_src, udph->src_port, ip6->ip_dst, udph->dst_port, ip6->next, ip6->len, 0, tstamp, AF_INET6); 486 | inpacket = 0; 487 | return; 488 | } 489 | else if (ip6->next == IP6_PROTO_ICMP) { 490 | icmp6_header *icmph; 491 | icmph = (icmp6_header *) (packet + eth_header_len + IP6_HEADER_LEN); 492 | // printf("[*] IPv6 PROTOCOL TYPE ICMP\n"); 493 | cx_track(ip6->ip_src, ip6->hop_lmt, ip6->ip_dst, ip6->hop_lmt, ip6->next, ip6->len, 0, tstamp, AF_INET6); 494 | inpacket = 0; 495 | return; 496 | } 497 | else { 498 | // printf("[*] IPv6 PROTOCOL TYPE OTHER: %d\n",ip6->next); 499 | cx_track(ip6->ip_src, ip6->next, ip6->ip_dst, ip6->next, ip6->next, ip6->len, 0, tstamp, AF_INET6); 500 | inpacket = 0; 501 | return; 502 | } 503 | } 504 | */ 505 | inpacket = 0; 506 | return; 507 | } 508 | 509 | 510 | void test_it(){ 511 | /* test it! */ 512 | uint8_t b[18]; 513 | memset((void*) b, 1, 17); 514 | b[17]= 0x11; // the faulty bits 515 | 516 | printf("KnR %lu\n", count_bits(b,17)); 517 | printf("KaW %lu\n", count_bits_kw(b,17)); 518 | printf("PaP %lu\n", count_bits_pp(b,17)); 519 | printf("JaP %lu\n", count_bits_p(b,17)); 520 | printf("P64 %lu\n", count_bits_64(b,17)); 521 | printf("T 1 %lu\n", count_bits_t1(b,17)); 522 | printf("T 2 %lu\n", count_bits_t2(b,17)); 523 | 524 | printf("weirdness test: %lu %lu %lu %lu %lu %lu\n", 525 | count_bits_pp(b,17), 526 | count_bits_pp(b,17), 527 | count_bits_pp(b,17), 528 | count_bits_pp(b,17), 529 | count_bits_pp(b,17), 530 | count_bits_pp(b,17)); 531 | } 532 | 533 | 534 | static void usage() { 535 | printf("edd: Entropy DDoS Detection\n\n"); 536 | printf("USAGE:\n"); 537 | printf(" $ %s [options]\n", BIN_NAME); 538 | printf("\n"); 539 | printf(" OPTIONS:\n"); 540 | printf("\n"); 541 | printf(" -i : network device (default: eth0)\n"); 542 | printf(" -r : read pcap file\n"); 543 | printf(" -w : packet window size (default: %u)\n", DEFAULT_WINDOW); 544 | printf(" -b : berkeley packet filter\n"); 545 | printf(" -e : treshold value (default : %f)\n", DEFAULT_TRESH); 546 | printf(" -u : user\n"); 547 | printf(" -g : group\n"); 548 | printf(" -D : enables daemon mode\n"); 549 | printf(" -T : dir to chroot into\n"); 550 | printf(" -h : this help message\n"); 551 | printf(" -t : profile counter algoritms\n"); 552 | printf(" -E : test edd\n"); 553 | printf(" -v : verbose\n\n"); 554 | } 555 | 556 | static int set_chroot(void) { 557 | char *absdir; 558 | char *logdir; 559 | int abslen; 560 | 561 | /* logdir = get_abs_path(logpath); */ 562 | 563 | /* change to the directory */ 564 | if ( chdir(chroot_dir) != 0 ) { 565 | printf("set_chroot: Can not chdir to \"%s\": %s\n",chroot_dir,strerror(errno)); 566 | } 567 | 568 | /* always returns an absolute pathname */ 569 | absdir = getcwd(NULL, 0); 570 | abslen = strlen(absdir); 571 | 572 | /* make the chroot call */ 573 | if ( chroot(absdir) < 0 ) { 574 | printf("Can not chroot to \"%s\": absolute: %s: %s\n",chroot_dir,absdir,strerror(errno)); 575 | } 576 | 577 | if ( chdir("/") < 0 ) { 578 | printf("Can not chdir to \"/\" after chroot: %s\n",strerror(errno)); 579 | } 580 | 581 | return 0; 582 | } 583 | 584 | static int drop_privs(void) { 585 | struct group *gr; 586 | struct passwd *pw; 587 | char *endptr; 588 | int i; 589 | int do_setuid = 0; 590 | int do_setgid = 0; 591 | unsigned long groupid = 0; 592 | unsigned long userid = 0; 593 | 594 | if ( group_name != NULL ) { 595 | do_setgid = 1; 596 | if( isdigit(group_name[0]) == 0 ) { 597 | gr = getgrnam(group_name); 598 | groupid = gr->gr_gid; 599 | } 600 | else { 601 | groupid = strtoul(group_name, &endptr, 10); 602 | } 603 | } 604 | 605 | if ( user_name != NULL ) { 606 | do_setuid = 1; 607 | do_setgid = 1; 608 | if ( isdigit(user_name[0]) == 0 ) { 609 | pw = getpwnam(user_name); 610 | userid = pw->pw_uid; 611 | } else { 612 | userid = strtoul(user_name, &endptr, 10); 613 | pw = getpwuid(userid); 614 | } 615 | 616 | if ( group_name == NULL ) { 617 | groupid = pw->pw_gid; 618 | } 619 | } 620 | 621 | if ( do_setgid ) { 622 | if ( (i = setgid(groupid)) < 0 ) { 623 | printf("Unable to set group ID: %s", strerror(i)); 624 | } 625 | } 626 | 627 | endgrent(); 628 | endpwent(); 629 | 630 | if ( do_setuid ) { 631 | if (getuid() == 0 && initgroups(user_name, groupid) < 0 ) { 632 | printf("Unable to init group names (%s/%lu)", user_name, groupid); 633 | } 634 | if ( (i = setuid(userid)) < 0 ) { 635 | printf("Unable to set user ID: %s\n", strerror(i)); 636 | } 637 | } 638 | return 0; 639 | } 640 | 641 | static int is_valid_path(char *path) { 642 | struct stat st; 643 | 644 | if ( path == NULL ) { 645 | return 0; 646 | } 647 | if ( stat(path, &st) != 0 ) { 648 | return 0; 649 | } 650 | if ( !S_ISDIR(st.st_mode) || access(path, W_OK) == -1 ) { 651 | return 0; 652 | } 653 | return 1; 654 | } 655 | 656 | static int create_pid_file(char *path, char *filename) { 657 | char filepath[STDBUF]; 658 | char *fp = NULL; 659 | char *fn = NULL; 660 | char pid_buffer[12]; 661 | struct flock lock; 662 | int rval; 663 | int fd; 664 | 665 | memset(filepath, 0, STDBUF); 666 | 667 | if ( !filename ) { 668 | fn = pidfile; 669 | } 670 | else { 671 | fn = filename; 672 | } 673 | 674 | if ( !path ) { 675 | fp = pidpath; 676 | } 677 | else { 678 | fp = path; 679 | } 680 | 681 | if ( is_valid_path(fp) ) { 682 | snprintf(filepath, STDBUF-1, "%s/%s", fp, fn); 683 | } 684 | else { 685 | printf("PID path \"%s\" isn't a writeable directory!", fp); 686 | } 687 | 688 | true_pid_name = strdup(filename); 689 | 690 | if ( (fd = open(filepath, O_CREAT | O_WRONLY, 691 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1 ) { 692 | return ERROR; 693 | } 694 | 695 | /* pid file locking */ 696 | lock.l_type = F_WRLCK; 697 | lock.l_start = 0; 698 | lock.l_whence = SEEK_SET; 699 | lock.l_len = 0; 700 | 701 | if ( fcntl(fd, F_SETLK, &lock) == -1 ) { 702 | if ( errno == EACCES || errno == EAGAIN ) { 703 | rval = ERROR; 704 | } 705 | else { 706 | rval = ERROR; 707 | } 708 | close(fd); 709 | return rval; 710 | } 711 | 712 | snprintf(pid_buffer, sizeof(pid_buffer), "%d\n", (int) getpid()); 713 | if ( ftruncate(fd, 0) != 0 ) { return ERROR; } 714 | if ( write(fd, pid_buffer, strlen(pid_buffer)) != 0 ) { return ERROR; } 715 | return SUCCESS; 716 | } 717 | int daemonize() { 718 | pid_t pid; 719 | int fd; 720 | 721 | pid = fork(); 722 | 723 | if ( pid > 0 ) { 724 | exit(0); /* parent */ 725 | } 726 | 727 | use_syslog = 1; 728 | if ( pid < 0 ) { 729 | return ERROR; 730 | } 731 | 732 | /* new process group */ 733 | setsid(); 734 | 735 | /* close file handles */ 736 | if ( (fd = open("/dev/null", O_RDWR)) >= 0 ) { 737 | dup2(fd, 0); 738 | dup2(fd, 1); 739 | dup2(fd, 2); 740 | if ( fd > 2 ) { 741 | close(fd); 742 | } 743 | } 744 | 745 | if ( pidfile ) { 746 | return create_pid_file(pidpath, pidfile); 747 | } 748 | 749 | return SUCCESS; 750 | } 751 | 752 | int main(int argc, char *argv[]) { 753 | 754 | int ch, fromfile, setfilter, version, drop_privs_flag, daemon_flag, chroot_flag; 755 | int use_syslog = 0; 756 | struct in_addr addr; 757 | struct bpf_program cfilter; 758 | char *bpff, errbuf[PCAP_ERRBUF_SIZE], *user_filter; 759 | char *net_ip_string; 760 | bpf_u_int32 net_mask; 761 | char *pcapfile = NULL; 762 | ch = fromfile = setfilter = version = drop_privs_flag = daemon_flag = 0; 763 | dev = "eth0"; 764 | bpff = ""; 765 | chroot_dir = "/tmp/"; 766 | inpacket = intr_flag = chroot_flag = 0; 767 | timecnt = time(NULL); 768 | 769 | signal(SIGTERM, game_over); 770 | signal(SIGINT, game_over); 771 | signal(SIGQUIT, game_over); 772 | //signal(SIGHUP, dump_active); 773 | //signal(SIGALRM, set_end_sessions); 774 | 775 | while ((ch = getopt(argc, argv, "b:d:w:e:tDET:g:hi:p:r:P:u:v")) != -1) 776 | switch (ch) { 777 | case 'i': 778 | dev = strdup(optarg); 779 | break; 780 | case 'b': 781 | bpff = strdup(optarg); 782 | break; 783 | case 'w': 784 | p_window = strtol(optarg, NULL, 0); 785 | break; 786 | case 'e': 787 | tresh = strtod(optarg, NULL); 788 | break; 789 | case 'v': 790 | verbose = 1; 791 | break; 792 | case 'r': 793 | pcapfile = strdup(optarg); 794 | break; 795 | case 'h': 796 | usage(); 797 | exit(0); 798 | break; 799 | case 't': 800 | profile_packet = 1; 801 | break; 802 | case 'E': 803 | test_it(); 804 | break; 805 | case 'D': 806 | daemon_flag = 1; 807 | break; 808 | case 'T': 809 | chroot_flag = 1; 810 | break; 811 | case 'u': 812 | user_name = strdup(optarg); 813 | drop_privs_flag = 1; 814 | break; 815 | case 'g': 816 | group_name = strdup(optarg); 817 | drop_privs_flag = 1; 818 | break; 819 | case 'p': 820 | pidfile = strdup(optarg); 821 | break; 822 | case 'P': 823 | pidpath = strdup(optarg); 824 | break; 825 | default: 826 | exit(1); 827 | break; 828 | } 829 | 830 | printf("%s - The Entropy DDoS Detector - version %s\n", BIN_NAME, VERSION); 831 | 832 | 833 | errbuf[0] = '\0'; 834 | if (pcapfile) { 835 | printf("[*] reading from file %s\n", pcapfile); 836 | if((handle = pcap_open_offline(pcapfile, errbuf)) == NULL) { 837 | printf("[*] Error pcap_open_offline: %s \n", errbuf); 838 | exit(1); 839 | } 840 | } else { 841 | 842 | if (getuid()) { 843 | printf("[*] You must be root..\n"); 844 | usage(); 845 | return (1); 846 | } 847 | 848 | /* look up an availible device if non specified */ 849 | if (dev == 0x0) dev = pcap_lookupdev(errbuf); 850 | printf("[*] Device: %s\n", dev); 851 | 852 | if ((handle = pcap_open_live(dev, SNAPLENGTH, 1, 500, errbuf)) == NULL) { 853 | printf("[*] Error pcap_open_live: %s \n", errbuf); 854 | pcap_close(handle); 855 | exit(1); 856 | } 857 | 858 | } 859 | if ((pcap_compile(handle, &cfilter, bpff, 1, net_mask)) == -1) { 860 | printf("[*] Error pcap_compile user_filter '%s' : %s\n", bpff, pcap_geterr(handle)); 861 | pcap_close(handle); 862 | exit(1); 863 | } 864 | 865 | if(pcap_setfilter(handle, &cfilter)) { 866 | printf("[*] Error in pcap_setfilter: %s\n", pcap_geterr(handle)); 867 | exit(1); 868 | } 869 | //pcap_freecode(&cfilter); // filter code not needed after setfilter 870 | 871 | /* B0rk if we see an error... */ 872 | if (strlen(errbuf) > 0) { 873 | printf("[*] Error errbuf: %s \n", errbuf); 874 | pcap_close(handle); 875 | exit(1); 876 | } 877 | 878 | if ( chroot_flag == 1 ) { 879 | set_chroot(); 880 | } 881 | 882 | if(daemon_flag) { 883 | if(!is_valid_path(pidpath)){ 884 | printf("[*] PID path \"%s\" is bad, check privilege.",pidpath); 885 | exit(1); 886 | } 887 | openlog("ppacket", LOG_PID | LOG_CONS, LOG_DAEMON); 888 | printf("[*] Daemonizing...\n\n"); 889 | daemonize(NULL); 890 | } 891 | 892 | if(drop_privs_flag) { 893 | printf("[*] Dropping privs...\n\n"); 894 | drop_privs(); 895 | } 896 | 897 | p_set = calloc(p_window, sizeof(uint32_t)); 898 | p_tot = calloc(p_window, sizeof(uint32_t)); 899 | p_entropy = calloc(p_window, sizeof(uint32_t)); 900 | //alarm(TIMEOUT); 901 | printf("[*] Charging ddos detector.. need to fill %u-size window of packets.\n\n", p_window+1); 902 | if(profile_packet) { 903 | pcap_loop(handle,-1,got_packet_profile, NULL); 904 | }else { 905 | pcap_loop(handle,-1,got_packet,NULL); 906 | } 907 | 908 | pcap_close(handle); 909 | return(0); 910 | } 911 | --------------------------------------------------------------------------------