Skip to content

Commit

Permalink
nettrace
Browse files Browse the repository at this point in the history
  • Loading branch information
netblue30 committed Jan 10, 2022
1 parent 1754635 commit 55b986d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 40 deletions.
1 change: 1 addition & 0 deletions src/fnettrace/fnettrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static inline uint8_t hash(uint32_t ip) {
void logprintf(char* fmt, ...);

// hostnames.c
extern int geoip_calls;
void load_hostnames(const char *fname);
char* retrieve_hostname(uint32_t ip);
void build_list(const char *fname);
Expand Down
17 changes: 16 additions & 1 deletion src/fnettrace/hostnames
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
9.9.9.0/24 Quad9 DNS
45.90.28.0/22 NextDNS
149.112.112.0/24 Quad9 DNS
149.112.120.0/21 CIRA DNS Canada
149.112.120.0/21 CIRA DNS Csnada

This comment has been minimized.

Copy link
@glitsj16

glitsj16 Jan 10, 2022

Collaborator

Typo? According to geoiplookup these are indeed in Canada...

$ geoiplookup -f /usr/share/GeoIP/GeoIP.dat 149.112.120.0
GeoIP Country Edition: CA, Canada

This comment has been minimized.

Copy link
@netblue30

netblue30 Jan 11, 2022

Author Owner

typo, thanks!

176.103.128.0/19 Adguard DNS
185.228.168.0/24 Cleanbrowsing DNS
193.0.0.0/21 whois.ripe.net Netherlands
Expand Down Expand Up @@ -160,6 +160,21 @@
108.46.0.0/16 MCI
192.229.128.0/17 MCI

# Microsoft
40.76.0.0/14 Microsoft
40.96.0.0/12 Microsoft
40.112.0.0/13 Microsoft
40.124.0.0/16 Microsoft
40.74.0.0/15 Microsoft
40.80.0.0/12 Microsoft
40.120.0.0/14 Microsoft
40.125.0.0/17 Microsoft
52.145.0.0/16 Microsoft
52.148.0.0/14 Microsoft
52.152.0.0/13 Microsoft
52.146.0.0/15 Microsoft
52.160.0.0/11 Microsoft

# Yahoo
63.250.192.0/19 Yahoo
66.196.64.0/18 Yahoo
Expand Down
10 changes: 10 additions & 0 deletions src/fnettrace/hostnames.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@
#include "radix.h"
#define MAXBUF 1024

int geoip_calls = 0;
static int geoip_not_found = 0;

char *retrieve_hostname(uint32_t ip) {
if (geoip_not_found)
return NULL;
geoip_calls++;

char *rv = NULL;
char *cmd;
if (asprintf(&cmd, "/usr/bin/geoiplookup %d.%d.%d.%d", PRINT_IP(ip)) == -1)
Expand All @@ -47,6 +53,10 @@ char *retrieve_hostname(uint32_t ip) {
fclose(fp);
return rv;
}
else
geoip_not_found = 1;

free(cmd);

return NULL;
}
Expand Down
112 changes: 82 additions & 30 deletions src/fnettrace/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ HNode *htable[HMAX] = {NULL};
// display linked list
HNode *dlist = NULL;

static unsigned bwmax = 0; // max bytes received in a display interval

static void hnode_add(uint32_t ip_src, uint32_t ip_dst, uint8_t protocol, uint16_t port_src, uint32_t bytes) {
uint8_t h = hash(ip_src);

Expand Down Expand Up @@ -151,20 +149,52 @@ static char *print_bw(unsigned units) {
units = DISPLAY_BW_UNITS ;

if (bw_line[units] == NULL) {
char *ptr = malloc(DISPLAY_BW_UNITS + 1);
char *ptr = malloc(DISPLAY_BW_UNITS + 2);
if (!ptr)
errExit("malloc");
bw_line[units] = ptr;

unsigned i;
for (i = 0; i < DISPLAY_BW_UNITS; i++, ptr++)
sprintf(ptr, "%s", (i < units)? "*": " ");
sprintf(ptr, "%s", " ");
}

return bw_line[units];
}

static void hnode_print(void) {
#define LINE_MAX 200
static inline void adjust_line(char *str, int len, int cols) {
if (len > LINE_MAX) // functions such as snprintf truncate the string, and return the length of the untruncated string
len = LINE_MAX;
if (cols > 4 && len > cols) {
str[cols] = '\0';
str[cols- 1] = '\n';
}
}

#define BWMAX_CNT 8
static unsigned adjust_bandwidth(unsigned bw) {
static unsigned array[BWMAX_CNT] = {0};
static int instance = 0;

array[instance] = bw;
int i;
unsigned sum = 0;
unsigned max = 0;
for ( i = 0; i < BWMAX_CNT; i++) {
sum += array[i];
max = (max > array[i])? max: array[i];
}
sum /= BWMAX_CNT;

if (++instance >= BWMAX_CNT)
instance = 0;

return (max < (sum / 2))? sum: max;
}

static void hnode_print(unsigned bw) {
assert(!arg_netfilter);
ansi_clrscr();

Expand All @@ -178,38 +208,47 @@ static void hnode_print(void) {

// get terminal size
struct winsize sz;
int col = 80;
int cols = 80;
if (isatty(STDIN_FILENO)) {
if (!ioctl(0, TIOCGWINSZ, &sz))
col = sz.ws_col;
cols = sz.ws_col;
}
#define LINE_MAX 200
if (cols > LINE_MAX)
cols = LINE_MAX;
char line[LINE_MAX + 1];
if (col > LINE_MAX)
col = LINE_MAX;

// print stats line
bw = adjust_bandwidth(bw);
char stats[31];
if (bw > (1024 * 1024 * DISPLAY_INTERVAL))
sprintf(stats, "%d MB/s ", bw / (1024 * 1024 * DISPLAY_INTERVAL));
else
sprintf(stats, "%d KB/s ", bw / (1024 * DISPLAY_INTERVAL));
int len = snprintf(line, LINE_MAX, "%32s geoip %d, IP database %d\n", stats, geoip_calls, radix_nodes);
adjust_line(line, len, cols);
printf("%s", line);

HNode *ptr = dlist;
HNode *prev = NULL;
int row = 0;
while (ptr) {
HNode *next = ptr->dnext;
if (--ptr->ttl > 0) {
char bytes[11];
if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 1024 * 2)) // > 2 MB/second
sprintf(bytes, "%u MB/s",
snprintf(bytes, 11, "%u MB/s",
(unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024* 1024)));
else if (ptr->bytes > (DISPLAY_INTERVAL * 1024 * 2)) // > 2 KB/second
sprintf(bytes, "%u KB/s",
snprintf(bytes, 11, "%u KB/s",
(unsigned) (ptr->bytes / (DISPLAY_INTERVAL * 1024)));
else
sprintf(bytes, "%u B/s", (unsigned) (ptr->bytes / DISPLAY_INTERVAL));
snprintf(bytes, 11, "%u B/s", (unsigned) (ptr->bytes / DISPLAY_INTERVAL));

char *hostname = ptr->hostname;
if (!hostname)
hostname = radix_find_last(ptr->ip_src);

if (!hostname)
hostname = retrieve_hostname(ptr->ip_src);

if (!hostname)
hostname = " ";
else {
Expand All @@ -218,16 +257,30 @@ static void hnode_print(void) {
errExit("strdup");
}

unsigned bwunit = bwmax / DISPLAY_BW_UNITS;
unsigned units = ptr->bytes / bwunit;
char *bwline = print_bw(units);
unsigned bwunit = bw / DISPLAY_BW_UNITS;
char *bwline;
if (bwunit == 0)
bwline = print_bw(0);
else
bwline = print_bw(ptr->bytes / bwunit);

char *protocol = "";
if (ptr->port_src == 80)
protocol = "(HTTP)";
else if (ptr->port_src == 853)
protocol = "(DoT)";
else if (ptr->protocol == 0x11)
protocol = "(UDP)";
/*
else (ptr->port_src == 443)
protocol = "SSL";
else if (ptr->port_src == 53)
protocol = "DNS";
*/

sprintf(line, "%10s %s %d.%d.%d.%d:%u %s\n", bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, hostname);
int len = strlen(line);
if (col > 4 && len > col) {
line[col] = '\0';
line[col - 1] = '\n';
}
len = snprintf(line, LINE_MAX, "%10s %s %d.%d.%d.%d:%u%s %s\n",
bytes, bwline, PRINT_IP(ptr->ip_src), ptr->port_src, protocol, hostname);
adjust_line(line, len, cols);
printf("%s", line);

if (ptr->bytes)
Expand All @@ -246,6 +299,7 @@ static void hnode_print(void) {

ptr = next;
}

}

static void run_trace(void) {
Expand All @@ -262,18 +316,16 @@ static void run_trace(void) {
unsigned last_print_traces = 0;
unsigned last_print_remaining = 0;
unsigned char buf[MAX_BUF_SIZE];
unsigned bwcurrent = 0;
unsigned bw = 0; // bandwidth calculations
while (1) {
unsigned end = time(NULL);
if (arg_netfilter && end - start >= NETLOCK_INTERVAL)
break;
if (end % DISPLAY_INTERVAL == 1 && last_print_traces != end) { // first print after 1 second
if (bwcurrent > bwmax)
bwmax = bwcurrent;
if (!arg_netfilter)
hnode_print();
hnode_print(bw);
last_print_traces = end;
bwcurrent = 0;
bw = 0;
}
if (arg_netfilter && last_print_remaining != end) {
logprintf(".");
Expand All @@ -300,7 +352,7 @@ static void run_trace(void) {

unsigned bytes = recvfrom(sock, buf, MAX_BUF_SIZE, 0, NULL, NULL);
if (bytes >= 20) { // size of IP header
bwcurrent += bytes + 14; // assume a 14 byte Ethernet layer
bw += bytes + 14; // assume a 14 byte Ethernet layer
// filter out loopback traffic
if (buf[12] != 127) {
uint32_t ip_src;
Expand Down Expand Up @@ -486,8 +538,8 @@ static void usage(void) {
printf("Options:\n");
printf(" --build=filename - compact list of addresses\n");
printf(" --help, -? - this help screen\n");
printf(" --log=filename - netlocker logfile\n");
printf(" --netfilter - build the firewall rules and commit them.\n");
printf(" --log=filename - logfile\n");
printf("\n");
}

Expand Down
20 changes: 11 additions & 9 deletions src/fnettrace/radix.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "fnettrace.h"

RNode *head = 0;
int radix_nodes = 0;

static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name) {
assert(ptr);
Expand All @@ -34,6 +35,7 @@ static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name)
RNode *node = malloc(sizeof(RNode));
if (!node)
errExit("malloc");
radix_nodes++;
memset(node, 0, sizeof(RNode));
node->ip = ip;
node->mask = mask;
Expand All @@ -42,7 +44,7 @@ static inline RNode *addOne(RNode *ptr, uint32_t ip, uint32_t mask, char *name)
if (!node->name)
errExit("strdup");
}

ptr->one = node;
return node;
}
Expand All @@ -62,7 +64,7 @@ static inline RNode *addZero(RNode *ptr, uint32_t ip, uint32_t mask, char *name)
if (!node->name)
errExit("strdup");
}

ptr->zero = node;
return node;
}
Expand Down Expand Up @@ -146,13 +148,13 @@ char *radix_find_last(uint32_t ip) {
if (ptr->name)
rv = ptr;
}

return (rv)? rv->name: NULL;
}

static void radix_print_node(RNode *ptr, int level) {
assert(ptr);

int i;
for (i = 0; i < level; i++)
printf(" ");
Expand All @@ -173,7 +175,7 @@ void radix_print(void) {
printf("radix tree is empty\n");
return;
}

printf("radix IPv4 tree\n");
radix_print_node(head, 0);
}
Expand All @@ -187,14 +189,14 @@ static inline int mask2cidr(uint32_t mask) {
if (mask & m)
cnt++;
}

return cnt;
}

static void radix_build_list_node(RNode *ptr) {
assert(ptr);


if (ptr->name) {
printf("%d.%d.%d.%d/%d %s\n", PRINT_IP(ptr->ip), mask2cidr(ptr->mask), ptr->name);
return;
Expand All @@ -213,6 +215,6 @@ void radix_build_list(void) {
return;
}

radix_build_list_node(head);
radix_build_list_node(head);
}

1 change: 1 addition & 0 deletions src/fnettrace/radix.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ typedef struct rnode_t {
char *name;
} RNode;

extern int radix_nodes;
char *radix_find_first(uint32_t ip);
char *radix_find_last(uint32_t ip);
void radix_add(uint32_t ip, uint32_t mask, char *name);
Expand Down

0 comments on commit 55b986d

Please sign in to comment.