aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnettrace
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2023-08-08 16:27:18 -0400
committerLibravatar netblue30 <netblue30@protonmail.com>2023-08-08 16:27:18 -0400
commitc4962789fc88e349a0c6a6c51af4a7cfc09fcc99 (patch)
tree83e69a67a17f9962846175e3f5cd0856d5e50de0 /src/fnettrace
parentMerge branch 'master' of ssh://github.com/netblue30/firejail (diff)
downloadfirejail-c4962789fc88e349a0c6a6c51af4a7cfc09fcc99.tar.gz
firejail-c4962789fc88e349a0c6a6c51af4a7cfc09fcc99.tar.zst
firejail-c4962789fc88e349a0c6a6c51af4a7cfc09fcc99.zip
nettrace stats
Diffstat (limited to 'src/fnettrace')
-rw-r--r--src/fnettrace/event.c105
-rw-r--r--src/fnettrace/fnettrace.h28
-rw-r--r--src/fnettrace/main.c244
-rw-r--r--src/fnettrace/radix.c40
-rw-r--r--src/fnettrace/radix.h3
-rw-r--r--src/fnettrace/static-ip-map.txt19
6 files changed, 329 insertions, 110 deletions
diff --git a/src/fnettrace/event.c b/src/fnettrace/event.c
new file mode 100644
index 000000000..f4ccf5360
--- /dev/null
+++ b/src/fnettrace/event.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright (C) 2014-2023 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fnettrace.h"
21
22typedef struct event_t {
23 struct event_t *next;
24 char *record;
25} Event;
26
27static Event *event = NULL;
28static Event *last_event = NULL;
29int ev_cnt = 0;
30
31void ev_clear(void) {
32 ev_cnt = 0;
33 Event *ev = event;
34 while (ev) {
35 Event *next = ev->next;
36 free(ev->record);
37 free(ev);
38 ev = next;
39 }
40 event = NULL;
41}
42
43void ev_add(char *record) {
44 assert(record);
45
46 // braking recursivity
47 if (*record == '\0')
48 return;
49
50 char *ptr = strchr(record, '\n');
51 if (ptr)
52 *ptr = '\0';
53
54 // filter out duplicates
55 if (event && strcmp(event->record, record) == 0)
56 return;
57
58 Event *ev = malloc(sizeof(Event));
59 if (!ev)
60 errExit("malloc");
61 memset(ev, 0, sizeof(Event));
62
63 ev->record = strdup(record);
64 if (!ev->record)
65 errExit("strdup");
66
67 if (event == NULL) {
68 event = ev;
69 last_event = ev;
70 }
71 else {
72 last_event->next = ev;
73 last_event = ev;
74 }
75 ev_cnt++;
76
77 // recursivity
78 if (ptr)
79 ev_add(++ptr);
80}
81
82void ev_print(FILE *fp) {
83 assert(fp);
84
85 Event *ev = event;
86 while (ev) {
87 fprintf(fp, " ");
88 if (strstr(ev->record, "NXDOMAIN")) {
89 if (fp == stdout)
90 ansi_red(ev->record);
91 else
92 fprintf(fp, "%s", ev->record);
93 }
94 else if (strstr(ev->record, "SSH connection")) {
95 if (fp == stdout)
96 ansi_red(ev->record);
97 else
98 fprintf(fp, "%s", ev->record);
99 }
100 else
101 fprintf(fp, "%s", ev->record);
102 fprintf(fp, "\n");
103 ev = ev->next;
104 }
105}
diff --git a/src/fnettrace/fnettrace.h b/src/fnettrace/fnettrace.h
index b4a8f26c7..9b4973235 100644
--- a/src/fnettrace/fnettrace.h
+++ b/src/fnettrace/fnettrace.h
@@ -53,6 +53,27 @@ static inline void ansi_clrscr(void) {
53 fflush(0); 53 fflush(0);
54} 54}
55 55
56static inline void ansi_bold(const char *str) {
57 char str1[] = {0x1b, '[', '1', 'm', '\0'};
58 char str2[] = {0x1b, '[', '0', 'm', '\0'};
59 printf("%s%s%s", str1, str, str2);
60 fflush(0);
61}
62
63static inline void ansi_faint(const char *str) {
64 char str1[] = {0x1b, '[', '2', 'm', '\0'};
65 char str2[] = {0x1b, '[', '0', 'm', '\0'};
66 printf("%s%s%s", str1, str, str2);
67 fflush(0);
68}
69
70static inline void ansi_red(const char *str) {
71 char str1[] = {0x1b, '[', '9', '1', 'm', '\0'};
72 char str2[] = {0x1b, '[', '0', 'm', '\0'};
73 printf("%s%s%s", str1, str, str2);
74 fflush(0);
75}
76
56static inline uint8_t hash(uint32_t ip) { 77static inline uint8_t hash(uint32_t ip) {
57 uint8_t *ptr = (uint8_t *) &ip; 78 uint8_t *ptr = (uint8_t *) &ip;
58 // simple byte xor 79 // simple byte xor
@@ -78,4 +99,11 @@ void terminal_restore(void);
78// runprog.c 99// runprog.c
79int runprog(const char *program); 100int runprog(const char *program);
80 101
102// event.c
103extern int ev_cnt;
104void ev_clear(void);
105void ev_add(char *record);
106void ev_print(FILE *fp);
107
108
81#endif 109#endif
diff --git a/src/fnettrace/main.c b/src/fnettrace/main.c
index 3bafd9090..a1e46f307 100644
--- a/src/fnettrace/main.c
+++ b/src/fnettrace/main.c
@@ -27,6 +27,12 @@
27 27
28static char *arg_log = NULL; 28static char *arg_log = NULL;
29 29
30// only 0 or negative values; postive values as defiend in RFCsq
31#define PROTOCOL_ICMP 0
32#define PROTOCOL_SSH -1
33
34
35
30//***************************************************************** 36//*****************************************************************
31// packet stats 37// packet stats
32//***************************************************************** 38//*****************************************************************
@@ -42,41 +48,18 @@ uint32_t stats_tor = 0;
42uint32_t stats_http = 0; 48uint32_t stats_http = 0;
43uint32_t stats_ssh = 0; 49uint32_t stats_ssh = 0;
44 50
45//***************************************************************** 51static void clear_stats(void) {
46// sni/dns log storage 52 stats_pkts = 0;
47//***************************************************************** 53 stats_icmp_echo = 0;
48typedef struct lognode_t { 54 stats_dns = 0;
49#define LOG_RECORD_LEN 255 55 stats_dns_dot = 0;
50 char record[LOG_RECORD_LEN + 1]; 56 stats_dns_doh = 0;
51} LogNode; 57 stats_dns_doq = 0;
52// circular list of SNI log records 58 stats_tls = 0;
53#define SNIMAX 64 59 stats_quic = 0;
54LogNode sni_table[SNIMAX] = {0}; 60 stats_tor = 0;
55int sni_index = 0; 61 stats_http = 0;
56 62 stats_ssh = 0;
57// circular list of SNI log records
58#define DNSMAX 64
59LogNode dns_table[SNIMAX] = {0};
60int dns_index = 0;
61
62static void print_sni(void) {
63 int i;
64 for (i = sni_index; i < SNIMAX; i++)
65 if (*sni_table[i].record)
66 printf(" %s", sni_table[i].record);
67 for (i = 0; i < sni_index; i++)
68 if (*sni_table[i].record)
69 printf(" %s", sni_table[i].record);
70}
71
72static void print_dns(void) {
73 int i;
74 for (i = dns_index; i < DNSMAX; i++)
75 if (*dns_table[i].record)
76 printf(" %s", dns_table[i].record);
77 for (i = 0; i < dns_index; i++)
78 if (*dns_table[i].record)
79 printf(" %s", dns_table[i].record);
80} 63}
81 64
82//***************************************************************** 65//*****************************************************************
@@ -92,7 +75,7 @@ typedef struct hnode_t {
92 uint32_t bytes; // number of bytes received in the last display interval 75 uint32_t bytes; // number of bytes received in the last display interval
93 uint32_t pkts; // number of packets received in the last display interval 76 uint32_t pkts; // number of packets received in the last display interval
94 uint16_t port_src; 77 uint16_t port_src;
95 uint8_t protocol; 78 int protocol;
96 79
97 // the firewall is build based on source address, and in the linked list 80 // the firewall is build based on source address, and in the linked list
98 // we could have elements with the same address but different ports 81 // we could have elements with the same address but different ports
@@ -135,7 +118,7 @@ void hfree(HNode *ptr) {
135} 118}
136 119
137// using protocol 0 and port 0 for ICMP 120// using protocol 0 and port 0 for ICMP
138static void hnode_add(uint32_t ip_src, uint8_t protocol, uint16_t port_src, uint32_t bytes) { 121static void hnode_add(uint32_t ip_src, int protocol, uint16_t port_src, uint32_t bytes) {
139 uint8_t h = hash(ip_src); 122 uint8_t h = hash(ip_src);
140 123
141 // find 124 // find
@@ -383,7 +366,9 @@ static void hnode_print(unsigned bw) {
383 else 366 else
384 sprintf(stats, "%u KB/s ", bw / (1024 * DISPLAY_INTERVAL)); 367 sprintf(stats, "%u KB/s ", bw / (1024 * DISPLAY_INTERVAL));
385// int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes); 368// int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes);
386 int len = snprintf(line, LINE_MAX, "%32s address:port (protocol) network\n", stats); 369 char faint1[] = {0x1b, '[', '2', 'm', '\0'};
370 char faint2[] = {0x1b, '[', '0', 'm', '\0'};
371 int len = snprintf(line, LINE_MAX, "%32s %saddress:port (protocol) network%s\n", stats, faint1, faint2);
387 adjust_line(line, len, cols); 372 adjust_line(line, len, cols);
388 printf("%s", line); 373 printf("%s", line);
389 374
@@ -461,10 +446,14 @@ static void hnode_print(unsigned bw) {
461 protocol = "UDP"; 446 protocol = "UDP";
462 else if (ptr->protocol == 0x06) 447 else if (ptr->protocol == 0x06)
463 protocol = "TCP"; 448 protocol = "TCP";
449 else if (ptr->protocol == PROTOCOL_SSH) {
450 protocol = "SSH";
451 stats_ssh += ptr->pkts;
452 }
464 453
465 if (protocol == NULL) 454 if (protocol == NULL)
466 protocol = ""; 455 protocol = "";
467 if (ptr->port_src == 0) 456 if (ptr->port_src == PROTOCOL_ICMP)
468 len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d (ICMP) %s\n", 457 len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d (ICMP) %s\n",
469 bytes, bwline, PRINT_IP(ptr->ip_src), ptr->rnode->name); 458 bytes, bwline, PRINT_IP(ptr->ip_src), ptr->rnode->name);
470 else 459 else
@@ -490,7 +479,7 @@ static void hnode_print(unsigned bw) {
490 479
491 ptr = next; 480 ptr = next;
492 } 481 }
493 printf("press any key to access stats\n"); 482 ansi_faint("(D)isplay, (S)ave, (C)lear, e(X)it\n");
494 483
495#ifdef DEBUG 484#ifdef DEBUG
496 { 485 {
@@ -505,10 +494,34 @@ static void hnode_print(unsigned bw) {
505#endif 494#endif
506} 495}
507 496
497static void print_stats(FILE *fp) {
498 assert(fp);
499
500 fprintf(fp, "Stats: %u packets\n", stats_pkts);
501 fprintf(fp, " encrypted: TLS %u, QUIC %u, Tor %u\n",
502 stats_tls, stats_quic, stats_tor);
503 fprintf(fp, " unencrypted: HTTP %u\n", stats_http);
504 fprintf(fp, " C&C backchannel: SSH %u, PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n",
505 stats_ssh, stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq);
506
507 fprintf(fp, "\n\nIP map");
508 if (fp == stdout)
509 ansi_faint(" - server-address network (packets)\n");
510 else
511 fprintf(fp, " - server-address network (packets)\n");
512 radix_print(fp, 1);
513
514 fprintf(fp, "\n\nEvents %d", ev_cnt);
515 if (fp == stdout)
516 ansi_faint(" - time address:port data\n");
517 else
518 fprintf(fp, " - time address:port data\n");
519 ev_print(fp);
508 520
509void print_stats(void) {
510} 521}
511 522
523
524
512// trace rx traffic coming in 525// trace rx traffic coming in
513static void run_trace(void) { 526static void run_trace(void) {
514 // trace only rx ipv4 tcp and upd 527 // trace only rx ipv4 tcp and upd
@@ -523,7 +536,7 @@ static void run_trace(void) {
523 if (p1 != -1) 536 if (p1 != -1)
524 printf("loading snitrace..."); 537 printf("loading snitrace...");
525 538
526 int p2 = runprog(LIBDIR "/firejail/fnettrace-dns --nolocal"); 539 int p2 = runprog(LIBDIR "/firejail/fnettrace-dns");
527 if (p2 != -1) 540 if (p2 != -1)
528 printf("loading dnstrace..."); 541 printf("loading dnstrace...");
529 unsigned last_print_traces = 0; 542 unsigned last_print_traces = 0;
@@ -575,40 +588,67 @@ static void run_trace(void) {
575 int icmp = 0; 588 int icmp = 0;
576 589
577 if (FD_ISSET(0, &rfds)) { 590 if (FD_ISSET(0, &rfds)) {
578 getchar(); 591 int c = getchar();
579 printf("\n\nStats: %u packets\n", stats_pkts); 592 if (c == 'c' || c == 'C') {
580 printf(" encrypted: TLS %u, QUIC %u, SSH %u, Tor %u\n", 593 clear_stats();
581 stats_tls, stats_quic, stats_ssh, stats_tor); 594 ev_clear();
582 printf(" unencrypted: HTTP %u\n", stats_http); 595 radix_clear_data();
583 printf(" C&C backchannel: PING %u, DNS %u, DoH %u, DoT %u, DoQ %u\n", 596 continue;
584 stats_icmp_echo, stats_dns, stats_dns_doh, stats_dns_dot, stats_dns_doq); 597 }
585 printf("press any key to continue..."); 598 else if (c == 'd' || c == 'D') {
586 fflush(0); 599 printf("\n\n");
587 600 ansi_bold("__________________________________________________________________________\n");
588 getchar(); 601 print_stats(stdout);
589 printf("\n\nSNI log - time server-address SNI\n"); 602 ansi_bold("__________________________________________________________________________\n");
590 print_sni(); 603 ansi_faint("press any key to continue...");
591 printf("press any key to continue..."); 604 fflush(0);
592 fflush(0); 605
593 606 getchar();
594 getchar(); 607 continue;
595 printf("\n\nDNS log - time server-address domain\n"); 608 }
596 print_dns(); 609 if (c == 's' || c == 'S') {
597 printf("press any key to continue..."); 610 printf("The file is saved in /tmp directory. Please enter the file name: ");
598 fflush(0); 611 fflush(0);
599 612
600 getchar(); 613 char buf[LINE_MAX + 5]; // eave some room to add /tmp/
601 printf("\n\nIP table: %d addresses - server-address network (packets)\n", radix_nodes); 614 strcpy(buf, "/tmp/");
602 radix_print(1); 615 terminal_restore();
603 printf("press any key to continue..."); 616 if (fgets(buf + 5, LINE_MAX, stdin) == NULL)
604 fflush(0); 617 errExit("fgets");
605 618 terminal_set();
606 getchar(); 619
620 // remove '\n' and open the file
621 char *ptr = strchr(buf, '\n');
622 if (!ptr) { // we should have a '\n'
623 printf("Error: invalid file name\n");
624 sleep(5);
625 continue;
626 }
627 *ptr = '\0';
628
629 FILE *fp = fopen(buf, "w");
630 if (!fp) {
631 printf("Error: cannot open file %s\n", buf);
632 perror("fopen");
633 sleep(5);
634 continue;
635 }
636
637 printf("Saving stats in %s file...\n", buf);
638 print_stats(fp);
639 fclose(fp);
640 int rv = chmod(buf, 0600);
641 (void) rv;
642 sleep(1);
643 continue;
644 }
645 else if (c == 'x' || c == 'X')
646 break;
607 continue; 647 continue;
608 } 648 }
609 else if (FD_ISSET(p1, &rfds)) { 649 else if (FD_ISSET(p1, &rfds)) {
610 char buf[1024]; 650 char buf[LINE_MAX];
611 ssize_t sz = read(p1, buf, 1024 - 1); 651 ssize_t sz = read(p1, buf, LINE_MAX - 1);
612 if (sz == -1) 652 if (sz == -1)
613 errExit("error reading snitrace"); 653 errExit("error reading snitrace");
614 if (sz == 0) { 654 if (sz == 0) {
@@ -618,19 +658,13 @@ static void run_trace(void) {
618 if (strncmp(buf, "SNI trace", 9) == 0) 658 if (strncmp(buf, "SNI trace", 9) == 0)
619 continue; 659 continue;
620 660
621 if (sz > LOG_RECORD_LEN)
622 sz = LOG_RECORD_LEN;
623 buf[sz] = '\0'; 661 buf[sz] = '\0';
624 strcpy(sni_table[sni_index].record, buf); 662 ev_add(buf);
625 if (++sni_index >= SNIMAX) {
626 sni_index = 0;
627 *sni_table[sni_index].record = '\0';
628 }
629 continue; 663 continue;
630 } 664 }
631 else if (FD_ISSET(p2, &rfds)) { 665 else if (FD_ISSET(p2, &rfds)) {
632 char buf[1024]; 666 char buf[LINE_MAX];
633 ssize_t sz = read(p2, buf, 1024 - 1); 667 ssize_t sz = read(p2, buf, LINE_MAX - 1);
634 if (sz == -1) 668 if (sz == -1)
635 errExit("error reading dnstrace"); 669 errExit("error reading dnstrace");
636 if (sz == 0) { 670 if (sz == 0) {
@@ -640,16 +674,11 @@ static void run_trace(void) {
640 if (strncmp(buf, "DNS trace", 9) == 0) 674 if (strncmp(buf, "DNS trace", 9) == 0)
641 continue; 675 continue;
642 676
643 if (sz > LOG_RECORD_LEN)
644 sz = LOG_RECORD_LEN;
645 buf[sz] = '\0'; 677 buf[sz] = '\0';
646 strcpy(dns_table[dns_index].record, buf); 678 ev_add(buf);
647 if (++dns_index >= DNSMAX) {
648 dns_index = 0;
649 *dns_table[dns_index].record = '\0';
650 }
651 continue; 679 continue;
652 } 680 }
681 // by default we assume TCP
653 else if (FD_ISSET(s2, &rfds)) 682 else if (FD_ISSET(s2, &rfds))
654 sock = s2; 683 sock = s2;
655 else if (FD_ISSET(s3, &rfds)) { 684 else if (FD_ISSET(s3, &rfds)) {
@@ -658,7 +687,7 @@ static void run_trace(void) {
658 } 687 }
659 688
660 unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL); 689 unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL);
661 if (bytes >= 20) { // size of IP header 690 if (bytes >= 20) { // minimum size of IP packet
662#ifdef DEBUG 691#ifdef DEBUG
663 { 692 {
664 uint32_t ip_src; 693 uint32_t ip_src;
@@ -682,12 +711,30 @@ static void run_trace(void) {
682 uint8_t hlen = (buf[0] & 0x0f) * 4; 711 uint8_t hlen = (buf[0] & 0x0f) * 4;
683 uint16_t port_src = 0; 712 uint16_t port_src = 0;
684 if (icmp) 713 if (icmp)
685 hnode_add(ip_src, 0, 0, bytes + 14); 714 hnode_add(ip_src, PROTOCOL_ICMP, 0, bytes + 14);
686 else { 715 else { // itcp or udp
687 memcpy(&port_src, buf + hlen, 2); 716 memcpy(&port_src, buf + hlen, 2);
688 port_src = ntohs(port_src); 717 port_src = ntohs(port_src);
689 718 int protocol = (int) buf[9];
690 uint8_t protocol = buf[9]; 719
720 // detect ssh on a standard or not so standard port (22)
721 if (protocol == 6) { // tcp
722 uint8_t dataoffset = *(buf + hlen + 12);
723 uint8_t tcphlen = (dataoffset >> 2);
724 if (memcmp(buf + hlen + tcphlen, "SSH-", 4) == 0) {
725 time_t seconds = time(NULL);
726 struct tm *t = localtime(&seconds);
727 char ip[30];
728 sprintf(ip, "%d.%d.%d.%d", PRINT_IP(ip_src));
729 char *msg;
730 if (asprintf(&msg, "%02d:%02d:%02d %-15s SSH connection",
731 t->tm_hour, t->tm_min, t->tm_sec, ip) == -1)
732 errExit("asprintf");
733 ev_add(msg);
734 free(msg);
735 protocol = PROTOCOL_SSH;
736 }
737 }
691 hnode_add(ip_src, protocol, port_src, bytes + 14); 738 hnode_add(ip_src, protocol, port_src, bytes + 14);
692 } 739 }
693 740
@@ -705,7 +752,10 @@ static void run_trace(void) {
705 close(s1); 752 close(s1);
706 close(s2); 753 close(s2);
707 close(s3); 754 close(s3);
708 print_stats(); 755 if (p1 != -1)
756 close(p1);
757 if (p2 != -1)
758 close(p2);
709} 759}
710 760
711 761
@@ -765,7 +815,7 @@ int main(int argc, char **argv) {
765 else if (strcmp(argv[i], "--print-map") == 0) { 815 else if (strcmp(argv[i], "--print-map") == 0) {
766 char *fname = "static-ip-map.txt"; 816 char *fname = "static-ip-map.txt";
767 load_hostnames(fname); 817 load_hostnames(fname);
768 radix_print(0); 818 radix_print(stdout, 0);
769 return 0; 819 return 0;
770 } 820 }
771 else if (strncmp(argv[i], "--squash-map=", 13) == 0) { 821 else if (strncmp(argv[i], "--squash-map=", 13) == 0) {
@@ -787,7 +837,7 @@ int main(int argc, char **argv) {
787 printf("# License GPLv2\n"); 837 printf("# License GPLv2\n");
788 printf("#\n"); 838 printf("#\n");
789 839
790 radix_print(0); 840 radix_print(stdout, 0);
791 printf("\n#\n#\n# input %d, output %d\n#\n#\n", in, radix_nodes); 841 printf("\n#\n#\n# input %d, output %d\n#\n#\n", in, radix_nodes);
792 fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes); 842 fprintf(stderr, "static ip map: input %d, output %d\n", in, radix_nodes);
793 return 0; 843 return 0;
diff --git a/src/fnettrace/radix.c b/src/fnettrace/radix.c
index 322ee2643..9dfa725a2 100644
--- a/src/fnettrace/radix.c
+++ b/src/fnettrace/radix.c
@@ -151,21 +151,22 @@ RNode *radix_longest_prefix_match(uint32_t ip) {
151} 151}
152 152
153static uint32_t sum; 153static uint32_t sum;
154static void print(RNode *ptr, int level, int pkts) { 154static void print(FILE *fp, RNode *ptr, int level, int pkts) {
155 assert(fp);
155 if (!ptr) 156 if (!ptr)
156 return; 157 return;
157 if (ptr->name) { 158 if (ptr->name) {
158 if (pkts) { 159 if (pkts) {
159 if (ptr->pkts) { 160 if (ptr->pkts) {
160 printf(" %d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); 161 fprintf(fp, " %d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level);
161 printf("%s", ptr->name); 162 fprintf(fp, "%s", ptr->name);
162 printf(" (%u)\n", ptr->pkts); 163 fprintf(fp, " (%u)\n", ptr->pkts);
163 } 164 }
164 } 165 }
165 else { 166 else {
166 printf("%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level); 167 fprintf(fp, "%d.%d.%d.%d/%d ", PRINT_IP(sum << (32 - level)), level);
167 printf("%s", ptr->name); 168 fprintf(fp, "%s", ptr->name);
168 printf("\n"); 169 fprintf(fp, "\n");
169 } 170 }
170 } 171 }
171 172
@@ -174,21 +175,21 @@ static void print(RNode *ptr, int level, int pkts) {
174 175
175 level++; 176 level++;
176 sum <<= 1; 177 sum <<= 1;
177 print(ptr->zero, level, pkts); 178 print(fp, ptr->zero, level, pkts);
178 sum++; 179 sum++;
179 print(ptr->one, level, pkts); 180 print(fp, ptr->one, level, pkts);
180 sum--; 181 sum--;
181 sum >>= 1; 182 sum >>= 1;
182} 183}
183 184
184void radix_print(int pkts) { 185void radix_print(FILE *fp, int pkts) {
185 if (!head) 186 if (!head)
186 return; 187 return;
187 sum = 0; 188 sum = 0;
188 print(head->zero, 1, pkts); 189 print(fp, head->zero, 1, pkts);
189 assert(sum == 0); 190 assert(sum == 0);
190 sum = 1; 191 sum = 1;
191 print(head->one, 1, pkts); 192 print(fp, head->one, 1, pkts);
192 assert(sum == 1); 193 assert(sum == 1);
193} 194}
194 195
@@ -241,3 +242,18 @@ void radix_squash(void) {
241 assert(sum == 1); 242 assert(sum == 1);
242 243
243} 244}
245
246static void clear_data(RNode *ptr) {
247 if (!ptr)
248 return;
249 ptr->pkts = 0;
250 clear_data(ptr->zero);
251 clear_data(ptr->one);
252}
253
254void radix_clear_data(void) {
255 if (!head)
256 return;
257 clear_data(head->zero);
258 clear_data(head->one);
259}
diff --git a/src/fnettrace/radix.h b/src/fnettrace/radix.h
index 358524723..686d60ace 100644
--- a/src/fnettrace/radix.h
+++ b/src/fnettrace/radix.h
@@ -30,7 +30,8 @@ typedef struct rnode_t {
30extern int radix_nodes; 30extern int radix_nodes;
31RNode *radix_longest_prefix_match(uint32_t ip); 31RNode *radix_longest_prefix_match(uint32_t ip);
32RNode*radix_add(uint32_t ip, uint32_t mask, char *name); 32RNode*radix_add(uint32_t ip, uint32_t mask, char *name);
33void radix_print(int pkts); 33void radix_print(FILE *fp, int pkts);
34void radix_squash(void); 34void radix_squash(void);
35void radix_clear_data(void);
35 36
36#endif 37#endif
diff --git a/src/fnettrace/static-ip-map.txt b/src/fnettrace/static-ip-map.txt
index eb66df73f..088b5cfea 100644
--- a/src/fnettrace/static-ip-map.txt
+++ b/src/fnettrace/static-ip-map.txt
@@ -153,6 +153,7 @@
15345.113.128.0/22 Twitch 15345.113.128.0/22 Twitch
15447.88.0.0/14 Alibaba 15447.88.0.0/14 Alibaba
15552.223.192.0/18 Twitch 15552.223.192.0/18 Twitch
15663.141.247.168/29 BitChute
15663.245.208.0/23 Mozilla 15763.245.208.0/23 Mozilla
15764.63.0.0/18 Twitter 15864.63.0.0/18 Twitter
15864.112.13.0/24 Dropbox 15964.112.13.0/24 Dropbox
@@ -168,6 +169,7 @@
16866.218.64.0/19 Yahoo 16966.218.64.0/19 Yahoo
16966.220.144.0/20 Facebook 17066.220.144.0/20 Facebook
17069.30.200.200/29 BitChute 17169.30.200.200/29 BitChute
17269.30.241.48/29 BitChute
17169.53.224.0/19 Netflix 17369.53.224.0/19 Netflix
17269.171.224.0/19 Facebook 17469.171.224.0/19 Facebook
17369.197.182.184/29 BitChute 17569.197.182.184/29 BitChute
@@ -222,7 +224,10 @@
222173.208.154.8/29 BitChute 224173.208.154.8/29 BitChute
223173.208.154.160/29 BitChute 225173.208.154.160/29 BitChute
224173.208.185.200/29 BitChute 226173.208.185.200/29 BitChute
227173.208.203.248/29 BitChute
228173.208.216.40/29 BitChute
225173.208.219.112/29 BitChute 229173.208.219.112/29 BitChute
230173.208.246.160/29 BitChute
226178.154.131.0/24 Yandex 231178.154.131.0/24 Yandex
227185.2.220.0/22 Netflix 232185.2.220.0/22 Netflix
228185.9.188.0/22 Netflix 233185.9.188.0/22 Netflix
@@ -246,6 +251,7 @@
246192.151.158.136/29 BitChute 251192.151.158.136/29 BitChute
247192.173.64.0/18 Netflix 252192.173.64.0/18 Netflix
248192.187.97.88/29 BitChute 253192.187.97.88/29 BitChute
254192.187.114.16/29 BitChute
249192.187.114.96/29 BitChute 255192.187.114.96/29 BitChute
250192.187.123.112/29 BitChute 256192.187.123.112/29 BitChute
251192.187.126.0/29 BitChute 257192.187.126.0/29 BitChute
@@ -254,13 +260,17 @@
254198.38.96.0/19 Netflix 260198.38.96.0/19 Netflix
255198.45.48.0/20 Netflix 261198.45.48.0/20 Netflix
256198.204.226.120/29 BitChute 262198.204.226.120/29 BitChute
263198.204.228.48/29 BitChute
264198.204.245.32/29 BitChute
257198.204.245.88/29 BitChute 265198.204.245.88/29 BitChute
266198.204.250.208/29 BitChute
258198.252.206.0/24 Stack Exchange 267198.252.206.0/24 Stack Exchange
259199.9.248.0/21 Twitch 268199.9.248.0/21 Twitch
260199.16.156.0/22 Twitter 269199.16.156.0/22 Twitter
261199.59.148.0/22 Twitter 270199.59.148.0/22 Twitter
262199.168.96.24/29 BitChute 271199.168.96.24/29 BitChute
263204.12.194.176/29 BitChute 272204.12.194.176/29 BitChute
273204.12.220.232/29 BitChute
264205.185.194.0/24 Steam 274205.185.194.0/24 Steam
265205.196.6.0/24 Steam 275205.196.6.0/24 Steam
266207.45.72.0/22 Netflix 276207.45.72.0/22 Netflix
@@ -273,6 +283,15 @@
273208.110.68.56/29 BitChute 283208.110.68.56/29 BitChute
274209.140.128.0/18 eBay 284209.140.128.0/18 eBay
275 285
286# WholeSale Internet
28769.30.192.0/18 WholeSale Internet
28869.197.128.0/18 WholeSale Internet
289173.208.128.0/17 WholeSale Internet
290204.12.192.0/18 WholeSale Internet
291208.67.0.0/21 WholeSale Internet
292208.110.64.0/19 WholeSale Internet
293208.110.91.0/24 WholeSale Internet
294
276# Imperva 295# Imperva
277199.83.128.0/21 Imperva 296199.83.128.0/21 Imperva
278198.143.32.0/19 Imperva 297198.143.32.0/19 Imperva