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(¤t_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(¤t_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(ðreq, 0, sizeof(ethreq));
905 strncpy(ethreq.ifr_name, interface_name.c_str(), IFNAMSIZ);
906
907 int ioctl_res = ioctl(fd, SIOCGIFFLAGS, ðreq);
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, ðreq);
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, ðreq);
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