1 #include <sys/types.h>
2 #include <stdint.h>
3 #include "fast_library.h"
4 #include <arpa/inet.h>
5 #include <stdlib.h> // atoi
6 #include <netinet/in.h>
7 #include <sys/ioctl.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <netdb.h>
12 #include <net/if.h>
13 #include <sys/socket.h>
14 #include <fstream>
15 #include <iostream>
16 
17 #include "log4cpp/Category.hh"
18 #include "log4cpp/Appender.hh"
19 #include "log4cpp/FileAppender.hh"
20 #include "log4cpp/OstreamAppender.hh"
21 #include "log4cpp/Layout.hh"
22 #include "log4cpp/BasicLayout.hh"
23 #include "log4cpp/PatternLayout.hh"
24 #include "log4cpp/Priority.hh"
25 
26 #include <boost/asio.hpp>
27 
28 #if defined(__APPLE__)
29 #include <libkern/OSByteOrder.h>
30 // Source: https://gist.github.com/pavel-odintsov/d13684600423d1c5e64e
31 #define be64toh(x) OSSwapBigToHostInt64(x)
32 #define htobe64(x) OSSwapHostToBigInt64(x)
33 #endif
34 
35 // For be64toh and htobe64
36 #if defined(__FreeBSD__) || defined(__DragonFly__)
37 #include <sys/endian.h>
38 #endif
39 
40 boost::regex regular_expression_cidr_pattern("^\\d+\\.\\d+\\.\\d+\\.\\d+\\/\\d+$");
41 boost::regex regular_expression_host_pattern("^\\d+\\.\\d+\\.\\d+\\.\\d+$");
42 
43 // convert string to integer
convert_string_to_integer(std::string line)44 int convert_string_to_integer(std::string line) {
45     return atoi(line.c_str());
46 }
47 
48 // Type safe versions of ntohl, ntohs with type control
fast_ntoh(uint16_t value)49 uint16_t fast_ntoh(uint16_t value) {
50     return ntohs(value);
51 }
52 
fast_ntoh(uint32_t value)53 uint32_t fast_ntoh(uint32_t value) {
54     return ntohl(value);
55 }
56 
57 // network (big endian) byte order to host byte order
fast_ntoh(uint64_t value)58 uint64_t fast_ntoh(uint64_t value) {
59     return be64toh(value);
60 }
61 
62 // Type safe version of htonl, htons
fast_hton(uint16_t value)63 uint16_t fast_hton(uint16_t value) {
64     return htons(value);
65 }
66 
fast_hton(uint32_t value)67 uint32_t fast_hton(uint32_t value) {
68     return htonl(value);
69 }
70 
fast_hton(uint64_t value)71 uint64_t fast_hton(uint64_t value) {
72     // host to big endian (network byte order)
73     return htobe64(value);
74 }
75 
76 
convert_ip_as_string_to_uint(std::string ip)77 uint32_t convert_ip_as_string_to_uint(std::string ip) {
78     struct in_addr ip_addr;
79     inet_aton(ip.c_str(), &ip_addr);
80 
81     // in network byte order
82     return ip_addr.s_addr;
83 }
84 
convert_ip_as_uint_to_string(uint32_t ip_as_integer)85 std::string convert_ip_as_uint_to_string(uint32_t ip_as_integer) {
86     struct in_addr ip_addr;
87     ip_addr.s_addr = ip_as_integer;
88     return (std::string)inet_ntoa(ip_addr);
89 }
90 
91 // convert integer to string
convert_int_to_string(int value)92 std::string convert_int_to_string(int value) {
93     std::stringstream out;
94     out << value;
95 
96     return out.str();
97 }
98 
99 // BE AWARE! WE USE NON STANDARD SUBNET_T HERE! WE USE NON CIDR MASK HERE!
convert_subnet_from_string_to_binary(std::string subnet_cidr)100 subnet_t convert_subnet_from_string_to_binary(std::string subnet_cidr) {
101     std::vector<std::string> subnet_as_string;
102     split(subnet_as_string, subnet_cidr, boost::is_any_of("/"), boost::token_compress_on);
103 
104     unsigned int cidr = convert_string_to_integer(subnet_as_string[1]);
105 
106     uint32_t subnet_as_int = convert_ip_as_string_to_uint(subnet_as_string[0]);
107 
108     uint32_t netmask_as_int = convert_cidr_to_binary_netmask(cidr);
109 
110     return std::make_pair(subnet_as_int, netmask_as_int);
111 }
112 
convert_subnet_from_string_to_binary_with_cidr_format(std::string subnet_cidr)113 subnet_t convert_subnet_from_string_to_binary_with_cidr_format(std::string subnet_cidr) {
114     std::vector<std::string> subnet_as_string;
115     split(subnet_as_string, subnet_cidr, boost::is_any_of("/"), boost::token_compress_on);
116 
117     unsigned int cidr = convert_string_to_integer(subnet_as_string[1]);
118 
119     uint32_t subnet_as_int = convert_ip_as_string_to_uint(subnet_as_string[0]);
120 
121     return std::make_pair(subnet_as_int, cidr);
122 }
123 
copy_networks_from_string_form_to_binary(std::vector<std::string> networks_list_as_string,std::vector<subnet_t> & our_networks)124 void copy_networks_from_string_form_to_binary(std::vector<std::string> networks_list_as_string,
125                                               std::vector<subnet_t>& our_networks) {
126     for (std::vector<std::string>::iterator ii = networks_list_as_string.begin();
127          ii != networks_list_as_string.end(); ++ii) {
128 
129         subnet_t current_subnet = convert_subnet_from_string_to_binary(*ii);
130         our_networks.push_back(current_subnet);
131     }
132 }
133 
convert_subnet_to_string(subnet_t my_subnet)134 std::string convert_subnet_to_string(subnet_t my_subnet) {
135     std::stringstream buffer;
136 
137     buffer<<convert_ip_as_uint_to_string(my_subnet.first)<<"/"<<my_subnet.second;
138 
139     return buffer.str();
140 }
141 
142 // extract 24 from 192.168.1.1/24
get_cidr_mask_from_network_as_string(std::string network_cidr_format)143 unsigned int get_cidr_mask_from_network_as_string(std::string network_cidr_format) {
144     std::vector<std::string> subnet_as_string;
145     split(subnet_as_string, network_cidr_format, boost::is_any_of("/"), boost::token_compress_on);
146 
147     if (subnet_as_string.size() != 2) {
148         return 0;
149     }
150 
151     return convert_string_to_integer(subnet_as_string[1]);
152 }
153 
154 
print_time_t_in_fastnetmon_format(time_t current_time)155 std::string print_time_t_in_fastnetmon_format(time_t current_time) {
156     struct tm* timeinfo;
157     char buffer[80];
158 
159     timeinfo = localtime(&current_time);
160 
161     strftime(buffer, sizeof(buffer), "%d_%m_%y_%H:%M:%S", timeinfo);
162 
163     return std::string(buffer);
164 }
165 
166 // extract 192.168.1.1 from 192.168.1.1/24
get_net_address_from_network_as_string(std::string network_cidr_format)167 std::string get_net_address_from_network_as_string(std::string network_cidr_format) {
168     std::vector<std::string> subnet_as_string;
169     split(subnet_as_string, network_cidr_format, boost::is_any_of("/"), boost::token_compress_on);
170 
171     if (subnet_as_string.size() != 2) {
172         return 0;
173     }
174 
175     return subnet_as_string[0];
176 }
177 
178 
get_printable_protocol_name(unsigned int protocol)179 std::string get_printable_protocol_name(unsigned int protocol) {
180     std::string proto_name;
181 
182     switch (protocol) {
183     case IPPROTO_TCP:
184         proto_name = "tcp";
185         break;
186     case IPPROTO_UDP:
187         proto_name = "udp";
188         break;
189     case IPPROTO_ICMP:
190         proto_name = "icmp";
191         break;
192     default:
193         proto_name = "unknown";
194         break;
195     }
196 
197     return proto_name;
198 }
199 
convert_cidr_to_binary_netmask(unsigned int cidr)200 uint32_t convert_cidr_to_binary_netmask(unsigned int cidr) {
201     uint32_t binary_netmask = 0xFFFFFFFF;
202     binary_netmask = binary_netmask << (32 - cidr);
203     // htonl from host byte order to network
204     // ntohl from network byte order to host
205 
206     // We need network byte order at output
207     return htonl(binary_netmask);
208 }
209 
210 
is_cidr_subnet(std::string subnet)211 bool is_cidr_subnet(std::string subnet) {
212     boost::cmatch what;
213 
214     return regex_match(subnet.c_str(), what, regular_expression_cidr_pattern);
215 }
216 
is_v4_host(std::string host)217 bool is_v4_host(std::string host) {
218     boost::cmatch what;
219 
220     return regex_match(host.c_str(), what, regular_expression_host_pattern);
221 }
222 
223 // check file existence
file_exists(std::string path)224 bool file_exists(std::string path) {
225     FILE* check_file = fopen(path.c_str(), "r");
226     if (check_file) {
227         fclose(check_file);
228         return true;
229     } else {
230         return false;
231     }
232 }
233 
folder_exists(std::string path)234 bool folder_exists(std::string path) {
235     if (access(path.c_str(), 0) == 0) {
236         struct stat status;
237         stat(path.c_str(), &status);
238 
239         if (status.st_mode & S_IFDIR) {
240             return true;
241         }
242     }
243 
244     return false;
245 }
246 
247 #define BIG_CONSTANT(x) (x##LLU)
248 
249 /*
250 
251     // calculate hash
252     unsigned int seed = 11;
253     uint64_t hash = MurmurHash64A(&current_packet, sizeof(current_packet), seed);
254 
255 */
256 
257 // https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash2.cpp
258 // 64-bit hash for 64-bit platforms
MurmurHash64A(const void * key,int len,uint64_t seed)259 uint64_t MurmurHash64A(const void* key, int len, uint64_t seed) {
260     const uint64_t m = BIG_CONSTANT(0xc6a4a7935bd1e995);
261     const int r = 47;
262 
263     uint64_t h = seed ^ (len * m);
264 
265     const uint64_t* data = (const uint64_t*)key;
266     const uint64_t* end = data + (len / 8);
267 
268     while (data != end) {
269         uint64_t k = *data++;
270 
271         k *= m;
272         k ^= k >> r;
273         k *= m;
274 
275         h ^= k;
276         h *= m;
277     }
278 
279     const unsigned char* data2 = (const unsigned char*)data;
280 
281     switch (len & 7) {
282     case 7:
283         h ^= uint64_t(data2[6]) << 48;
284     case 6:
285         h ^= uint64_t(data2[5]) << 40;
286     case 5:
287         h ^= uint64_t(data2[4]) << 32;
288     case 4:
289         h ^= uint64_t(data2[3]) << 24;
290     case 3:
291         h ^= uint64_t(data2[2]) << 16;
292     case 2:
293         h ^= uint64_t(data2[1]) << 8;
294     case 1:
295         h ^= uint64_t(data2[0]);
296         h *= m;
297     };
298 
299     h ^= h >> r;
300     h *= m;
301     h ^= h >> r;
302 
303     return h;
304 }
305 
306 // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
timeval_subtract(struct timeval * result,struct timeval * x,struct timeval * y)307 int timeval_subtract(struct timeval* result, struct timeval* x, struct timeval* y) {
308     /* Perform the carry for the later subtraction by updating y. */
309     if (x->tv_usec < y->tv_usec) {
310         int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
311         y->tv_usec -= 1000000 * nsec;
312         y->tv_sec += nsec;
313     }
314 
315     if (x->tv_usec - y->tv_usec > 1000000) {
316         int nsec = (x->tv_usec - y->tv_usec) / 1000000;
317         y->tv_usec += 1000000 * nsec;
318         y->tv_sec -= nsec;
319     }
320 
321     /* Compute the time remaining to wait. tv_usec is certainly positive. */
322     result->tv_sec = x->tv_sec - y->tv_sec;
323     result->tv_usec = x->tv_usec - y->tv_usec;
324 
325     /* Return 1 if result is negative. */
326     return x->tv_sec < y->tv_sec;
327 }
328 
print_tcp_flags(uint8_t flag_value)329 std::string print_tcp_flags(uint8_t flag_value) {
330     if (flag_value == 0) {
331         return "-";
332     }
333 
334     // cod from pfring.h
335     // (tcp->fin * TH_FIN_MULTIPLIER) + (tcp->syn * TH_SYN_MULTIPLIER) +
336     // (tcp->rst * TH_RST_MULTIPLIER) + (tcp->psh * TH_PUSH_MULTIPLIER) +
337     // (tcp->ack * TH_ACK_MULTIPLIER) + (tcp->urg * TH_URG_MULTIPLIER);
338 
339     /*
340         // Required for decoding tcp flags
341         #define TH_FIN_MULTIPLIER   0x01
342         #define TH_SYN_MULTIPLIER   0x02
343         #define TH_RST_MULTIPLIER   0x04
344         #define TH_PUSH_MULTIPLIER  0x08
345         #define TH_ACK_MULTIPLIER   0x10
346         #define TH_URG_MULTIPLIER   0x20
347     */
348 
349     std::vector<std::string> all_flags;
350 
351     if (extract_bit_value(flag_value, TCP_FIN_FLAG_SHIFT)) {
352         all_flags.push_back("fin");
353     }
354 
355     if (extract_bit_value(flag_value, TCP_SYN_FLAG_SHIFT)) {
356         all_flags.push_back("syn");
357     }
358 
359     if (extract_bit_value(flag_value, TCP_RST_FLAG_SHIFT)) {
360         all_flags.push_back("rst");
361     }
362 
363     if (extract_bit_value(flag_value, TCP_PSH_FLAG_SHIFT)) {
364         all_flags.push_back("psh");
365     }
366 
367     if (extract_bit_value(flag_value, TCP_ACK_FLAG_SHIFT)) {
368         all_flags.push_back("ack");
369     }
370 
371     if (extract_bit_value(flag_value, TCP_URG_FLAG_SHIFT)) {
372         all_flags.push_back("urg");
373     }
374 
375 
376     std::ostringstream flags_as_string;
377 
378     if (all_flags.empty()) {
379         return "-";
380     }
381 
382     // concatenate all vector elements with comma
383     std::copy(all_flags.begin(), all_flags.end() - 1, std::ostream_iterator<std::string>(flags_as_string, ","));
384 
385     // add last element
386     flags_as_string << all_flags.back();
387 
388     return flags_as_string.str();
389 }
390 
split_strings_to_vector_by_comma(std::string raw_string)391 std::vector <std::string> split_strings_to_vector_by_comma(std::string raw_string) {
392     std::vector<std::string> splitted_strings;
393     boost::split(splitted_strings, raw_string, boost::is_any_of(","), boost::token_compress_on);
394 
395     return splitted_strings;
396 }
397 
398 // http://stackoverflow.com/questions/14528233/bit-masking-in-c-how-to-get-first-bit-of-a-byte
extract_bit_value(uint8_t num,int bit)399 int extract_bit_value(uint8_t num, int bit) {
400     if (bit > 0 && bit <= 8) {
401         return ((num >> (bit - 1)) & 1);
402     } else {
403         return 0;
404     }
405 }
406 
407 // Overloaded version with 16 bit integer support
extract_bit_value(uint16_t num,int bit)408 int extract_bit_value(uint16_t num, int bit) {
409     if (bit > 0 && bit <= 16) {
410         return ((num >> (bit - 1)) & 1);
411     } else {
412         return 0;
413     }
414 }
415 
set_bit_value(uint8_t & num,int bit)416 int set_bit_value(uint8_t& num, int bit) {
417     if (bit > 0 && bit <= 8) {
418         num = num | 1 << (bit - 1);
419 
420         return 1;
421     } else {
422         return 0;
423     }
424 }
425 
set_bit_value(uint16_t & num,int bit)426 int set_bit_value(uint16_t& num, int bit) {
427     if (bit > 0 && bit <= 16) {
428         num = num | 1 << (bit - 1);
429 
430         return 1;
431     } else {
432         return 0;
433     }
434 }
435 
clear_bit_value(uint8_t & num,int bit)436 int clear_bit_value(uint8_t& num, int bit) {
437     if (bit > 0 && bit <= 8) {
438         num = num & ~(1 << (bit - 1) );
439 
440         return 1;
441     } else {
442         return 0;
443     }
444 }
445 
446 // http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c-c
clear_bit_value(uint16_t & num,int bit)447 int clear_bit_value(uint16_t& num, int bit) {
448     if (bit > 0 && bit <= 16) {
449         num = num & ~(1 << (bit - 1) );
450 
451         return 1;
452     } else {
453         return 0;
454     }
455 }
456 
print_simple_packet(simple_packet packet)457 std::string print_simple_packet(simple_packet packet) {
458     std::stringstream buffer;
459 
460     if (packet.ts.tv_sec == 0) {
461         // PF_RING and netmap do not generate timestamp for all packets because it's very CPU
462         // intensive operation
463         // But we want pretty attack report and fill it there
464         gettimeofday(&packet.ts, NULL);
465     }
466 
467     buffer << convert_timeval_to_date(packet.ts) << " ";
468 
469     std::string source_ip_as_string = "";
470     std::string  destination_ip_as_string = "";
471 
472     if (packet.ip_protocol_version == 4) {
473         source_ip_as_string = convert_ip_as_uint_to_string(packet.src_ip);
474         destination_ip_as_string = convert_ip_as_uint_to_string(packet.dst_ip);
475     } else if (packet.ip_protocol_version == 6) {
476         source_ip_as_string = print_ipv6_address(packet.src_ipv6);
477         destination_ip_as_string = print_ipv6_address(packet.dst_ipv6);
478     } else {
479         // WTF?
480     }
481 
482     buffer << source_ip_as_string << ":" << packet.source_port << " > "
483            << destination_ip_as_string << ":" << packet.destination_port
484            << " protocol: " << get_printable_protocol_name(packet.protocol);
485 
486     // Print flags only for TCP
487     if (packet.protocol == IPPROTO_TCP) {
488         buffer << " flags: " << print_tcp_flags(packet.flags);
489     }
490 
491     buffer << " frag: " << packet.ip_fragmented << " ";
492 
493     buffer << " ";
494     buffer << "packets: " << packet.number_of_packets << " ";
495     buffer << "size: " << packet.length << " bytes ";
496 
497     // We should cast it to integer because otherwise it will be interpreted as char
498     buffer << "ttl: " << unsigned(packet.ttl) << " ";
499     buffer << "sample ratio: " << packet.sample_ratio << " ";
500 
501     buffer << " \n";
502 
503     return buffer.str();
504 }
505 
convert_timeval_to_date(struct timeval tv)506 std::string convert_timeval_to_date(struct timeval tv) {
507     time_t nowtime = tv.tv_sec;
508     struct tm* nowtm = localtime(&nowtime);
509 
510     char tmbuf[64];
511     char buf[64];
512 
513     strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm);
514 
515 #if defined(__APPLE__)
516     snprintf(buf, sizeof(buf), "%s.%06d", tmbuf, tv.tv_usec);
517 #else
518     snprintf(buf, sizeof(buf), "%s.%06ld", tmbuf, tv.tv_usec);
519 #endif
520 
521     return std::string(buf);
522 }
523 
524 
convert_speed_to_mbps(uint64_t speed_in_bps)525 uint64_t convert_speed_to_mbps(uint64_t speed_in_bps) {
526     return uint64_t((double)speed_in_bps / 1024 / 1024 * 8);
527 }
528 
get_protocol_name_by_number(unsigned int proto_number)529 std::string get_protocol_name_by_number(unsigned int proto_number) {
530     struct protoent* proto_ent = getprotobynumber(proto_number);
531     std::string proto_name = proto_ent->p_name;
532     return proto_name;
533 }
534 
535 // exec command in shell
exec(std::string cmd)536 std::vector<std::string> exec(std::string cmd) {
537     std::vector<std::string> output_list;
538 
539     FILE* pipe = popen(cmd.c_str(), "r");
540     if (!pipe) return output_list;
541 
542     char buffer[256];
543     while (!feof(pipe)) {
544         if (fgets(buffer, 256, pipe) != NULL) {
545             size_t newbuflen = strlen(buffer);
546 
547             // remove newline at the end
548             if (buffer[newbuflen - 1] == '\n') {
549                 buffer[newbuflen - 1] = '\0';
550             }
551 
552             output_list.push_back(buffer);
553         }
554     }
555 
556     pclose(pipe);
557     return output_list;
558 }
559 
print_pid_to_file(pid_t pid,std::string pid_path)560 bool print_pid_to_file(pid_t pid, std::string pid_path) {
561     std::ofstream pid_file;
562 
563     pid_file.open(pid_path.c_str(), std::ios::trunc);
564     if (pid_file.is_open()) {
565         pid_file << pid << "\n";
566         pid_file.close();
567 
568         return true;
569     } else {
570         return false;
571     }
572 }
573 
read_pid_from_file(pid_t & pid,std::string pid_path)574 bool read_pid_from_file(pid_t& pid, std::string pid_path) {
575     std::fstream pid_file(pid_path.c_str(), std::ios_base::in);
576 
577     if (pid_file.is_open()) {
578         pid_file >> pid;
579         pid_file.close();
580 
581         return true;
582     } else {
583         return false;
584     }
585 }
586 
store_data_to_graphite(unsigned short int graphite_port,std::string graphite_host,graphite_data_t graphite_data)587 bool store_data_to_graphite(unsigned short int graphite_port, std::string graphite_host, graphite_data_t graphite_data) {
588     // Do not bother Graphite if we do not have any metrics here
589     if (graphite_data.size() == 0) {
590         return true;
591     }
592 
593     int client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
594 
595     if (client_sockfd < 0) {
596         return false;
597     }
598 
599     struct sockaddr_in serv_addr;
600     memset(&serv_addr, 0, sizeof(serv_addr));
601 
602     serv_addr.sin_family = AF_INET;
603     serv_addr.sin_port = htons(graphite_port);
604 
605     int pton_result = inet_pton(AF_INET, graphite_host.c_str(), &serv_addr.sin_addr);
606 
607     if (pton_result <= 0) {
608         close(client_sockfd);
609         return false;
610     }
611 
612     int connect_result = connect(client_sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
613 
614     if (connect_result < 0) {
615         close(client_sockfd);
616         return false;
617     }
618 
619     std::stringstream buffer;
620     time_t current_time = time(NULL);
621     for (graphite_data_t::iterator itr = graphite_data.begin(); itr != graphite_data.end(); ++itr) {
622         buffer << itr->first << " " << itr->second << " " << current_time << "\n";
623     }
624 
625     std::string buffer_as_string = buffer.str();
626 
627     int write_result = write(client_sockfd, buffer_as_string.c_str(), buffer_as_string.size());
628 
629     close(client_sockfd);
630 
631     if (write_result > 0) {
632         return true;
633     } else {
634         return false;
635     }
636 }
637 
638 
639 // Get list of all available interfaces on the server
get_interfaces_list()640 interfaces_list_t get_interfaces_list() {
641     interfaces_list_t interfaces_list;
642 
643     // Format: 1: eth0: < ....
644     boost::regex interface_name_pattern("^\\d+:\\s+(\\w+):.*?$");
645 
646     std::vector<std::string> output_list = exec("ip -o link show");
647 
648     if (output_list.empty()) {
649         return interfaces_list;
650     }
651 
652     for (std::vector<std::string>::iterator iter = output_list.begin(); iter != output_list.end(); ++iter) {
653         boost::match_results<std::string::const_iterator> regex_results;
654 
655         if (boost::regex_match(*iter, regex_results, interface_name_pattern)) {
656             // std::cout<<"Interface: "<<regex_results[1]<<std::endl;
657             interfaces_list.push_back(regex_results[1]);
658         }
659     }
660 
661     return interfaces_list;
662 }
663 
664 // Get all IPs for interface: main IP and aliases
get_ip_list_for_interface(std::string interface)665 ip_addresses_list_t get_ip_list_for_interface(std::string interface) {
666     ip_addresses_list_t ip_list;
667 
668     std::vector<std::string> output_list = exec("ip address show dev " + interface);
669 
670     if (output_list.empty()) {
671         return ip_list;
672     }
673 
674     boost::regex interface_alias_pattern("^\\s+inet\\s+(\\d+\\.\\d+\\.\\d+\\.\\d+).*?$");
675     // inet 188.40.35.142
676 
677     for (std::vector<std::string>::iterator iter = output_list.begin(); iter != output_list.end(); ++iter) {
678         boost::match_results<std::string::const_iterator> regex_results;
679 
680         if (boost::regex_match(*iter, regex_results, interface_alias_pattern)) {
681             ip_list.push_back(regex_results[1]);
682             // std::cout<<"IP: "<<regex_results[1]<<std::endl;
683         }
684     }
685 
686     return ip_list;
687 }
688 
get_local_ip_v4_addresses_list()689 ip_addresses_list_t get_local_ip_v4_addresses_list() {
690     ip_addresses_list_t ip_list;
691 
692     std::vector<std::string> list_of_ignored_interfaces;
693     list_of_ignored_interfaces.push_back("lo");
694     list_of_ignored_interfaces.push_back("venet0");
695 
696     interfaces_list_t interfaces_list = get_interfaces_list();
697 
698     if (interfaces_list.empty()) {
699         return ip_list;
700     }
701 
702     for (interfaces_list_t::iterator iter = interfaces_list.begin(); iter != interfaces_list.end(); ++iter) {
703         std::vector<std::string>::iterator iter_exclude_list =
704         std::find(list_of_ignored_interfaces.begin(), list_of_ignored_interfaces.end(), *iter);
705 
706         // Skip ignored interface
707         if (iter_exclude_list != list_of_ignored_interfaces.end()) {
708             continue;
709         }
710 
711         // std::cout<<*iter<<std::endl;
712         ip_addresses_list_t ip_list_on_interface = get_ip_list_for_interface(*iter);
713 
714         // Append list
715         ip_list.insert(ip_list.end(), ip_list_on_interface.begin(), ip_list_on_interface.end());
716     }
717 
718     return ip_list;
719 }
720 
convert_prefix_to_string_representation(prefix_t * prefix)721 std::string convert_prefix_to_string_representation(prefix_t* prefix) {
722     std::string address = convert_ip_as_uint_to_string(prefix->add.sin.s_addr);
723 
724     return address + "/" + convert_int_to_string(prefix->bitlen);
725 }
726 
find_subnet_by_ip_in_string_format(patricia_tree_t * patricia_tree,std::string ip)727 std::string find_subnet_by_ip_in_string_format(patricia_tree_t* patricia_tree, std::string ip) {
728     patricia_node_t* found_patrica_node = NULL;
729 
730     // Convert IP to integer
731     uint32_t client_ip = convert_ip_as_string_to_uint(ip);
732 
733     prefix_t prefix_for_check_adreess;
734     prefix_for_check_adreess.add.sin.s_addr = client_ip;
735     prefix_for_check_adreess.family = AF_INET;
736     prefix_for_check_adreess.bitlen = 32;
737 
738     found_patrica_node = patricia_search_best2(patricia_tree, &prefix_for_check_adreess, 1);
739 
740     if (found_patrica_node != NULL) {
741        return convert_prefix_to_string_representation(found_patrica_node->prefix);
742     } else {
743        return "";
744     }
745 }
746 
747 // It could not be on start or end of the line
748 boost::regex  ipv6_address_compression_algorithm("(0000:){2,}");
749 
print_ipv6_address(struct in6_addr & ipv6_address)750 std::string print_ipv6_address(struct in6_addr& ipv6_address) {
751     char buffer[128];
752 
753     // For short print
754     uint8_t* b = ipv6_address.s6_addr;
755 
756     sprintf(buffer, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
757         b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12],
758         b[13], b[14], b[15]);
759 
760     std::string buffer_string(buffer);
761 
762     // Compress IPv6 address
763     std::string result = boost::regex_replace(buffer_string, ipv6_address_compression_algorithm, ":", boost::format_first_only);
764 
765     return result;
766 }
767 
get_packet_direction_ipv6(patricia_tree_t * lookup_tree,struct in6_addr src_ipv6,struct in6_addr dst_ipv6)768 direction get_packet_direction_ipv6(patricia_tree_t* lookup_tree, struct in6_addr src_ipv6, struct in6_addr dst_ipv6) {
769     direction packet_direction;
770 
771     bool our_ip_is_destination = false;
772     bool our_ip_is_source = false;
773 
774     prefix_t prefix_for_check_address;
775     prefix_for_check_address.family = AF_INET6;
776     prefix_for_check_address.bitlen = 128;
777 
778     patricia_node_t* found_patrica_node = NULL;
779     prefix_for_check_address.add.sin6 = dst_ipv6;
780 
781     found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_address, 1);
782 
783     if (found_patrica_node) {
784         our_ip_is_destination = true;
785     }
786 
787     found_patrica_node = NULL;
788     prefix_for_check_address.add.sin6 = src_ipv6;
789 
790     found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_address, 1);
791 
792     if (found_patrica_node) {
793         our_ip_is_source = true;
794     }
795 
796     if (our_ip_is_source && our_ip_is_destination) {
797         packet_direction = INTERNAL;
798     } else if (our_ip_is_source) {
799         packet_direction = OUTGOING;
800     } else if (our_ip_is_destination) {
801         packet_direction = INCOMING;
802     } else {
803         packet_direction = OTHER;
804     }
805 
806     return packet_direction;
807 }
808 
809 /* Get traffic type: check it belongs to our IPs */
get_packet_direction(patricia_tree_t * lookup_tree,uint32_t src_ip,uint32_t dst_ip,unsigned long & subnet,unsigned int & subnet_cidr_mask)810 direction get_packet_direction(patricia_tree_t* lookup_tree, uint32_t src_ip, uint32_t dst_ip, unsigned long& subnet, unsigned int& subnet_cidr_mask) {
811     direction packet_direction;
812 
813     bool our_ip_is_destination = false;
814     bool our_ip_is_source = false;
815 
816     prefix_t prefix_for_check_adreess;
817     prefix_for_check_adreess.family = AF_INET;
818     prefix_for_check_adreess.bitlen = 32;
819 
820     patricia_node_t* found_patrica_node = NULL;
821     prefix_for_check_adreess.add.sin.s_addr = dst_ip;
822 
823     unsigned long destination_subnet = 0;
824     unsigned int  destination_subnet_cidr_mask = 0;
825     found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_adreess, 1);
826 
827     if (found_patrica_node) {
828         our_ip_is_destination = true;
829         destination_subnet = found_patrica_node->prefix->add.sin.s_addr;
830         destination_subnet_cidr_mask = found_patrica_node->prefix->bitlen;
831     }
832 
833     found_patrica_node = NULL;
834     prefix_for_check_adreess.add.sin.s_addr = src_ip;
835 
836     unsigned long source_subnet = 0;
837     unsigned int source_subnet_cidr_mask = 0;
838     found_patrica_node = patricia_search_best2(lookup_tree, &prefix_for_check_adreess, 1);
839 
840     if (found_patrica_node) {
841         our_ip_is_source = true;
842         source_subnet = found_patrica_node->prefix->add.sin.s_addr;
843         source_subnet_cidr_mask = found_patrica_node->prefix->bitlen;
844     }
845 
846     subnet = 0;
847     if (our_ip_is_source && our_ip_is_destination) {
848         packet_direction = INTERNAL;
849     } else if (our_ip_is_source) {
850         subnet = source_subnet;
851         subnet_cidr_mask = source_subnet_cidr_mask;
852 
853         packet_direction = OUTGOING;
854     } else if (our_ip_is_destination) {
855         subnet = destination_subnet;
856         subnet_cidr_mask = destination_subnet_cidr_mask;
857 
858         packet_direction = INCOMING;
859     } else {
860         packet_direction = OTHER;
861     }
862 
863     return packet_direction;
864 }
865 
get_direction_name(direction direction_value)866 std::string get_direction_name(direction direction_value) {
867     std::string direction_name;
868 
869     switch (direction_value) {
870     case INCOMING:
871         direction_name = "incoming";
872         break;
873     case OUTGOING:
874         direction_name = "outgoing";
875         break;
876     case INTERNAL:
877         direction_name = "internal";
878         break;
879     case OTHER:
880         direction_name = "other";
881         break;
882     default:
883         direction_name = "unknown";
884         break;
885     }
886 
887     return direction_name;
888 }
889 
890 // We haven't this code for FreeBSD yet
891 #ifdef __linux__
manage_interface_promisc_mode(std::string interface_name,bool switch_on)892 bool manage_interface_promisc_mode(std::string interface_name, bool switch_on) {
893     extern log4cpp::Category& logger;
894 
895     // We need really any socket for ioctl
896     int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
897 
898     if (!fd) {
899         logger << log4cpp::Priority::ERROR << "Can't create socket for promisc mode manager";
900         return false;
901     }
902 
903     struct ifreq ethreq;
904     memset(&ethreq, 0, sizeof(ethreq));
905     strncpy(ethreq.ifr_name, interface_name.c_str(), IFNAMSIZ);
906 
907     int ioctl_res = ioctl(fd, SIOCGIFFLAGS, &ethreq);
908 
909     if (ioctl_res == -1) {
910         logger << log4cpp::Priority::ERROR << "Can't get interface flags";
911         return false;
912     }
913 
914     bool promisc_enabled_on_device = ethreq.ifr_flags & IFF_PROMISC;
915 
916     if (switch_on) {
917         if (promisc_enabled_on_device) {
918             logger << log4cpp::Priority::INFO << "Interface " << interface_name << " in promisc mode already";
919             return true;
920         } else {
921              logger << log4cpp::Priority::INFO << "Interface in non promisc mode now, switch it on";
922              ethreq.ifr_flags |= IFF_PROMISC;
923 
924              int ioctl_res_set = ioctl(fd, SIOCSIFFLAGS, &ethreq);
925 
926              if (ioctl_res_set == -1) {
927                  logger << log4cpp::Priority::ERROR << "Can't set interface flags";
928                  return false;
929              }
930 
931              return true;
932         }
933     } else {
934         if (!promisc_enabled_on_device) {
935             logger << log4cpp::Priority::INFO << "Interface " << interface_name << " in normal mode already";
936             return true;
937         } else {
938             logger << log4cpp::Priority::INFO << "Interface in  promisc mode now, switch it off";
939 
940             ethreq.ifr_flags &= ~IFF_PROMISC;
941             int ioctl_res_set = ioctl(fd, SIOCSIFFLAGS, &ethreq);
942 
943             if (ioctl_res_set == -1) {
944                 logger << log4cpp::Priority::ERROR << "Can't set interface flags";
945                 return false;
946             }
947 
948             return true;
949         }
950     }
951 
952 }
953 
954 #endif
955 
956 #ifdef ENABLE_LUA_HOOKS
init_lua_jit(std::string lua_hooks_path)957 lua_State* init_lua_jit(std::string lua_hooks_path) {
958     extern log4cpp::Category& logger;
959 
960     lua_State* lua_state = luaL_newstate();
961 
962     if (lua_state == NULL) {
963         logger << log4cpp::Priority::ERROR << "Can't create LUA session";
964 
965         return NULL;
966     }
967 
968      // load libraries
969     luaL_openlibs(lua_state);
970 
971     int lua_load_file_result = luaL_dofile(lua_state, lua_hooks_path.c_str());
972 
973     if (lua_load_file_result != 0) {
974         logger << log4cpp::Priority::ERROR << "LuaJIT can't load file correctly from path: " << lua_hooks_path
975             << " disable LUA support";
976 
977         return NULL;
978     }
979 
980     return lua_state;
981 }
982 
call_lua_function(std::string function_name,lua_State * lua_state_param,std::string client_addres_in_string_format,void * ptr)983 bool call_lua_function(std::string function_name, lua_State* lua_state_param, std::string client_addres_in_string_format, void* ptr) {
984     extern log4cpp::Category& logger;
985 
986     /* Function name */
987     lua_getfield(lua_state_param, LUA_GLOBALSINDEX, function_name.c_str());
988 
989     /* Function params */
990     lua_pushstring(lua_state_param, client_addres_in_string_format.c_str());
991     lua_pushlightuserdata(lua_state_param, ptr);
992 
993     // Call with 1 argumnents and 1 result
994     lua_call(lua_state_param, 2, 1);
995 
996     if (lua_gettop(lua_state_param) == 1) {
997         bool result = lua_toboolean(lua_state_param, -1) == 1 ? true : false;
998 
999         // pop returned value
1000         lua_pop(lua_state_param, 1);
1001 
1002         return result;
1003     } else {
1004         logger << log4cpp::Priority::ERROR << "We got " << lua_gettop(lua_state_param) << " return values from the LUA, it's error, please check your LUA code";
1005         return false;
1006     }
1007 
1008     return false;
1009 }
1010 
1011 #endif
1012 
serialize_attack_description_to_json(attack_details & current_attack)1013 json_object* serialize_attack_description_to_json(attack_details& current_attack) {
1014     json_object* jobj = json_object_new_object();
1015 
1016     attack_type_t attack_type = detect_attack_type(current_attack);
1017     std::string printable_attack_type = get_printable_attack_name(attack_type);
1018 
1019     json_object_object_add(jobj, "attack_type", json_object_new_string(printable_attack_type.c_str()));
1020     json_object_object_add(jobj, "initial_attack_power", json_object_new_int(current_attack.attack_power));
1021     json_object_object_add(jobj, "peak_attack_power",    json_object_new_int(current_attack.max_attack_power));
1022     json_object_object_add(jobj, "attack_direction",     json_object_new_string(get_direction_name(current_attack.attack_direction).c_str()));
1023     json_object_object_add(jobj, "attack_protocol",      json_object_new_string(get_printable_protocol_name(current_attack.attack_protocol).c_str()));
1024 
1025     json_object_object_add(jobj, "total_incoming_traffic", json_object_new_int(current_attack.in_bytes));
1026     json_object_object_add(jobj, "total_outgoing_traffic", json_object_new_int(current_attack.out_bytes));
1027     json_object_object_add(jobj, "total_incoming_pps",     json_object_new_int(current_attack.in_packets));
1028     json_object_object_add(jobj, "total_outgoing_pps",     json_object_new_int(current_attack.out_packets));
1029     json_object_object_add(jobj, "total_incoming_flows",   json_object_new_int(current_attack.in_flows));
1030     json_object_object_add(jobj, "total_outgoing_flows",   json_object_new_int(current_attack.out_flows));
1031 
1032     json_object_object_add(jobj, "average_incoming_traffic", json_object_new_int(current_attack.average_in_bytes));
1033     json_object_object_add(jobj, "average_outgoing_traffic", json_object_new_int(current_attack.average_out_bytes));
1034     json_object_object_add(jobj, "average_incoming_pps",     json_object_new_int(current_attack.average_in_packets));
1035     json_object_object_add(jobj, "average_outgoing_pps",     json_object_new_int(current_attack.average_out_packets));
1036     json_object_object_add(jobj, "average_incoming_flows",   json_object_new_int(current_attack.average_in_flows));
1037     json_object_object_add(jobj, "average_outgoing_flows",   json_object_new_int(current_attack.average_out_flows));
1038 
1039     json_object_object_add(jobj, "incoming_ip_fragmented_traffic", json_object_new_int( current_attack.fragmented_in_bytes ));
1040     json_object_object_add(jobj, "outgoing_ip_fragmented_traffic", json_object_new_int( current_attack.fragmented_out_bytes  ));
1041     json_object_object_add(jobj, "incoming_ip_fragmented_pps", json_object_new_int( current_attack.fragmented_in_packets ));
1042     json_object_object_add(jobj, "outgoing_ip_fragmented_pps", json_object_new_int( current_attack.fragmented_out_packets ));
1043 
1044     json_object_object_add(jobj, "incoming_tcp_traffic", json_object_new_int( current_attack.tcp_in_bytes ));
1045     json_object_object_add(jobj, "outgoing_tcp_traffic", json_object_new_int( current_attack.tcp_out_bytes ));
1046     json_object_object_add(jobj, "incoming_tcp_pps", json_object_new_int( current_attack.tcp_in_packets ));
1047     json_object_object_add(jobj, "outgoing_tcp_pps", json_object_new_int(current_attack.tcp_out_packets ));
1048 
1049     json_object_object_add(jobj, "incoming_syn_tcp_traffic", json_object_new_int( current_attack.tcp_syn_in_bytes ));
1050     json_object_object_add(jobj, "outgoing_syn_tcp_traffic", json_object_new_int( current_attack.tcp_syn_out_bytes ));
1051     json_object_object_add(jobj, "incoming_syn_tcp_pps", json_object_new_int( current_attack.tcp_syn_in_packets  ));
1052     json_object_object_add(jobj, "outgoing_syn_tcp_pps", json_object_new_int( current_attack.tcp_syn_out_packets ));
1053 
1054     json_object_object_add(jobj, "incoming_udp_traffic", json_object_new_int( current_attack.udp_in_bytes  ));
1055     json_object_object_add(jobj, "outgoing_udp_traffic", json_object_new_int( current_attack.udp_out_bytes ));
1056     json_object_object_add(jobj, "incoming_udp_pps", json_object_new_int( current_attack.udp_in_packets ));
1057     json_object_object_add(jobj, "outgoing_udp_pps", json_object_new_int( current_attack.udp_out_packets ));
1058 
1059     json_object_object_add(jobj, "incoming_icmp_traffic", json_object_new_int( current_attack.icmp_in_bytes   ));
1060     json_object_object_add(jobj, "outgoing_icmp_traffic", json_object_new_int( current_attack.icmp_out_bytes ));
1061     json_object_object_add(jobj, "incoming_icmp_pps", json_object_new_int( current_attack.icmp_in_packets ));
1062     json_object_object_add(jobj, "outgoing_icmp_pps", json_object_new_int( current_attack.icmp_out_packets ));
1063 
1064     return jobj;
1065 }
1066 
serialize_attack_description(attack_details & current_attack)1067 std::string serialize_attack_description(attack_details& current_attack) {
1068     std::stringstream attack_description;
1069 
1070     attack_type_t attack_type = detect_attack_type(current_attack);
1071     std::string printable_attack_type = get_printable_attack_name(attack_type);
1072 
1073     attack_description
1074     << "Attack type: " << printable_attack_type << "\n"
1075     << "Initial attack power: " << current_attack.attack_power << " packets per second\n"
1076     << "Peak attack power: " << current_attack.max_attack_power << " packets per second\n"
1077     << "Attack direction: " << get_direction_name(current_attack.attack_direction) << "\n"
1078     << "Attack protocol: " << get_printable_protocol_name(current_attack.attack_protocol) << "\n";
1079 
1080     attack_description
1081     << "Total incoming traffic: " << convert_speed_to_mbps(current_attack.in_bytes) << " mbps\n"
1082     << "Total outgoing traffic: " << convert_speed_to_mbps(current_attack.out_bytes) << " mbps\n"
1083     << "Total incoming pps: " << current_attack.in_packets << " packets per second\n"
1084     << "Total outgoing pps: " << current_attack.out_packets << " packets per second\n"
1085     << "Total incoming flows: " << current_attack.in_flows << " flows per second\n"
1086     << "Total outgoing flows: " << current_attack.out_flows << " flows per second\n";
1087 
1088 
1089     // Add average counters
1090     attack_description
1091     << "Average incoming traffic: " << convert_speed_to_mbps(current_attack.average_in_bytes) << " mbps\n"
1092     << "Average outgoing traffic: " << convert_speed_to_mbps(current_attack.average_out_bytes) << " mbps\n"
1093     << "Average incoming pps: " << current_attack.average_in_packets << " packets per second\n"
1094     << "Average outgoing pps: " << current_attack.average_out_packets << " packets per second\n"
1095     << "Average incoming flows: " << current_attack.average_in_flows << " flows per second\n"
1096     << "Average outgoing flows: " << current_attack.average_out_flows << " flows per second\n";
1097 
1098     attack_description
1099     << "Incoming ip fragmented traffic: " << convert_speed_to_mbps(current_attack.fragmented_in_bytes) << " mbps\n"
1100     << "Outgoing ip fragmented traffic: " << convert_speed_to_mbps(current_attack.fragmented_out_bytes)
1101     << " mbps\n"
1102     << "Incoming ip fragmented pps: " << current_attack.fragmented_in_packets
1103     << " packets per second\n"
1104     << "Outgoing ip fragmented pps: " << current_attack.fragmented_out_packets
1105     << " packets per second\n"
1106 
1107     << "Incoming tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_in_bytes) << " mbps\n"
1108     << "Outgoing tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_out_bytes) << " mbps\n"
1109     << "Incoming tcp pps: " << current_attack.tcp_in_packets << " packets per second\n"
1110     << "Outgoing tcp pps: " << current_attack.tcp_out_packets << " packets per second\n"
1111     << "Incoming syn tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_syn_in_bytes)
1112     << " mbps\n"
1113     << "Outgoing syn tcp traffic: " << convert_speed_to_mbps(current_attack.tcp_syn_out_bytes) << " mbps\n"
1114     << "Incoming syn tcp pps: " << current_attack.tcp_syn_in_packets << " packets per second\n"
1115     << "Outgoing syn tcp pps: " << current_attack.tcp_syn_out_packets << " packets per second\n"
1116 
1117     << "Incoming udp traffic: " << convert_speed_to_mbps(current_attack.udp_in_bytes) << " mbps\n"
1118     << "Outgoing udp traffic: " << convert_speed_to_mbps(current_attack.udp_out_bytes) << " mbps\n"
1119     << "Incoming udp pps: " << current_attack.udp_in_packets << " packets per second\n"
1120     << "Outgoing udp pps: " << current_attack.udp_out_packets << " packets per second\n"
1121 
1122     << "Incoming icmp traffic: " << convert_speed_to_mbps(current_attack.icmp_in_bytes) << " mbps\n"
1123     << "Outgoing icmp traffic: " << convert_speed_to_mbps(current_attack.icmp_out_bytes) << " mbps\n"
1124     << "Incoming icmp pps: " << current_attack.icmp_in_packets << " packets per second\n"
1125     << "Outgoing icmp pps: " << current_attack.icmp_out_packets << " packets per second\n";
1126 
1127     return attack_description.str();
1128 }
1129 
detect_attack_type(attack_details & current_attack)1130 attack_type_t detect_attack_type(attack_details& current_attack) {
1131     double threshold_value = 0.9;
1132 
1133     if (current_attack.attack_direction == INCOMING) {
1134         if (current_attack.tcp_syn_in_packets > threshold_value * current_attack.in_packets) {
1135             return ATTACK_SYN_FLOOD;
1136         } else if (current_attack.icmp_in_packets > threshold_value * current_attack.in_packets) {
1137             return ATTACK_ICMP_FLOOD;
1138         } else if (current_attack.fragmented_in_packets > threshold_value * current_attack.in_packets) {
1139             return ATTACK_IP_FRAGMENTATION_FLOOD;
1140         } else if (current_attack.udp_in_packets > threshold_value * current_attack.in_packets) {
1141             return ATTACK_UDP_FLOOD;
1142         }
1143     } else if (current_attack.attack_direction == OUTGOING) {
1144         if (current_attack.tcp_syn_out_packets > threshold_value * current_attack.out_packets) {
1145             return ATTACK_SYN_FLOOD;
1146         } else if (current_attack.icmp_out_packets > threshold_value * current_attack.out_packets) {
1147             return ATTACK_ICMP_FLOOD;
1148         } else if (current_attack.fragmented_out_packets > threshold_value * current_attack.out_packets) {
1149             return ATTACK_IP_FRAGMENTATION_FLOOD;
1150         } else if (current_attack.udp_out_packets > threshold_value * current_attack.out_packets) {
1151             return ATTACK_UDP_FLOOD;
1152         }
1153     }
1154 
1155     return ATTACK_UNKNOWN;
1156 }
1157 
get_printable_attack_name(attack_type_t attack)1158 std::string get_printable_attack_name(attack_type_t attack) {
1159     if (attack == ATTACK_SYN_FLOOD) {
1160         return "syn_flood";
1161     } else if (attack == ATTACK_ICMP_FLOOD) {
1162         return "icmp_flood";
1163     } else if (attack == ATTACK_UDP_FLOOD) {
1164         return "udp_flood";
1165     } else if (attack == ATTACK_IP_FRAGMENTATION_FLOOD) {
1166         return "ip_fragmentation";
1167     } else if (attack == ATTACK_UNKNOWN) {
1168         return "unknown";
1169     } else {
1170         return "unknown";
1171     }
1172 }
1173 
serialize_network_load_to_text(map_element & network_speed_meter,bool average)1174 std::string serialize_network_load_to_text(map_element& network_speed_meter, bool average) {
1175     std::stringstream buffer;
1176 
1177     std::string prefix = "Network";
1178 
1179     if (average) {
1180         prefix = "Average network";
1181     }
1182 
1183     buffer
1184         << prefix << " incoming traffic: "<< convert_speed_to_mbps(network_speed_meter.in_bytes) << " mbps\n"
1185         << prefix << " outgoing traffic: "<< convert_speed_to_mbps(network_speed_meter.out_bytes) << " mbps\n"
1186         << prefix << " incoming pps: "<< network_speed_meter.in_packets << " packets per second\n"
1187         << prefix << " outgoing pps: "<< network_speed_meter.out_packets << " packets per second\n";
1188 
1189     return buffer.str();
1190 }
1191 
serialize_network_load_to_json(map_element & network_speed_meter)1192 json_object* serialize_network_load_to_json(map_element& network_speed_meter) {
1193     json_object* jobj = json_object_new_object();
1194 
1195     json_object_object_add(jobj, "incoming traffic", json_object_new_int(network_speed_meter.in_bytes));
1196     json_object_object_add(jobj, "outgoing traffic", json_object_new_int(network_speed_meter.out_bytes));
1197     json_object_object_add(jobj, "incoming pps",     json_object_new_int(network_speed_meter.in_packets));
1198     json_object_object_add(jobj, "outgoing pps",     json_object_new_int(network_speed_meter.out_packets));
1199 
1200     return jobj;
1201 }
1202 
serialize_statistic_counters_about_attack(attack_details & current_attack)1203 std::string serialize_statistic_counters_about_attack(attack_details& current_attack) {
1204     std::stringstream attack_description;
1205 
1206     double average_packet_size_for_incoming_traffic = 0;
1207     double average_packet_size_for_outgoing_traffic = 0;
1208 
1209     if (current_attack.average_in_packets > 0) {
1210         average_packet_size_for_incoming_traffic =
1211         (double)current_attack.average_in_bytes / (double)current_attack.average_in_packets;
1212     }
1213 
1214     if (current_attack.average_out_packets > 0) {
1215         average_packet_size_for_outgoing_traffic =
1216         (double)current_attack.average_out_bytes / (double)current_attack.average_out_packets;
1217     }
1218 
1219     // We do not need very accurate size
1220     attack_description.precision(1);
1221     attack_description << "Average packet size for incoming traffic: " << std::fixed
1222                        << average_packet_size_for_incoming_traffic << " bytes \n"
1223                        << "Average packet size for outgoing traffic: " << std::fixed
1224                        << average_packet_size_for_outgoing_traffic << " bytes \n";
1225 
1226     return attack_description.str();
1227 }
1228 
dns_lookup(std::string domain_name)1229 std::string dns_lookup(std::string domain_name) {
1230     try {
1231         boost::asio::io_service io_service;
1232         boost::asio::ip::tcp::resolver resolver(io_service);
1233 
1234         boost::asio::ip::tcp::resolver::query query(domain_name, "");
1235 
1236         for (boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
1237             i != boost::asio::ip::tcp::resolver::iterator();
1238             ++i)
1239         {
1240             boost::asio::ip::tcp::endpoint end = *i;
1241             return end.address().to_string();
1242         }
1243     } catch (std::exception& e) {
1244         return "";
1245     }
1246 
1247     return "";
1248 }
1249 
store_data_to_stats_server(unsigned short int graphite_port,std::string graphite_host,std::string buffer_as_string)1250 bool store_data_to_stats_server(unsigned short int graphite_port, std::string graphite_host, std::string buffer_as_string) {
1251    int client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
1252 
1253     if (client_sockfd < 0) {
1254         return false;
1255     }
1256 
1257     struct sockaddr_in serv_addr;
1258     memset(&serv_addr, 0, sizeof(serv_addr));
1259 
1260     serv_addr.sin_family = AF_INET;
1261     serv_addr.sin_port = htons(graphite_port);
1262 
1263     int pton_result = inet_pton(AF_INET, graphite_host.c_str(), &serv_addr.sin_addr);
1264 
1265     if (pton_result <= 0) {
1266         close(client_sockfd);
1267         return false;
1268     }
1269 
1270     int connect_result = connect(client_sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
1271 
1272     if (connect_result < 0) {
1273         close(client_sockfd);
1274         return false;
1275     }
1276 
1277     int write_result = write(client_sockfd, buffer_as_string.c_str(), buffer_as_string.size());
1278 
1279     close(client_sockfd);
1280 
1281     if (write_result > 0) {
1282         return true;
1283     } else {
1284         return false;
1285     }
1286 }
1287 
convert_hex_as_string_to_uint(std::string hex,uint32_t & value)1288 bool convert_hex_as_string_to_uint(std::string hex, uint32_t& value) {
1289     std::stringstream ss;
1290 
1291     ss << std::hex << hex;
1292     ss >> value;
1293 
1294     return ss.fail();
1295 }
1296