From b901ebd3cd786e8cec0f10c461f8bcc8e4219081 Mon Sep 17 00:00:00 2001 From: Ralph Ronnquist Date: Thu, 23 Jun 2022 10:44:30 +1000 Subject: [PATCH] Change to use hashvector and externalised ignore list --- socket-sniff/Makefile | 4 +- socket-sniff/ignores.i | 75 +---------- socket-sniff/socket-sniff.c | 262 +++++++++++++++++++++++++----------- 3 files changed, 189 insertions(+), 152 deletions(-) diff --git a/socket-sniff/Makefile b/socket-sniff/Makefile index e90a6de..4f8b149 100644 --- a/socket-sniff/Makefile +++ b/socket-sniff/Makefile @@ -1,10 +1,10 @@ default: socket-sniff .INTERMEDIATE: socket-sniff.o -socket-sniff.o: CFLAGS = -Wall -I../htable -g +socket-sniff.o: CFLAGS = -Wall -I../pvector -g socket-sniff.o: socket-sniff.c | ignores.i -socket-sniff: LDLIBS = -L../htable -lhtable +socket-sniff: LDLIBS = -L../pvector -lpvector socket-sniff: socket-sniff.o clean: diff --git a/socket-sniff/ignores.i b/socket-sniff/ignores.i index 79728bb..59435d3 100644 --- a/socket-sniff/ignores.i +++ b/socket-sniff/ignores.i @@ -1,78 +1,7 @@ static char *IGNORES[] = { - "10.0.99.", // ganetinet "127.", // localhost - "152.228.204.144", // VM via nardoo - "152.228.204.145", - "152.228.204.146", - "152.228.204.147", - "152.228.204.148", - "152.228.204.149", - "152.228.204.150", - "152.228.204.151", - "152.228.204.152", - "152.228.204.153", - "152.228.204.154", - "152.228.204.155", - "152.228.204.156", - "152.228.204.157", - "152.228.204.158", - "152.228.204.159", - "2001:41d0:2:1f68:" // (via) nash - "2001:41d0:2:d06e:" // (via) newtonia - "2001:41d0:8:732b:" // (via) napier - "2001:41d0:a:511b:" // (via) nardoo - "37.187.145.27", // nardoo - "37.59.56.43", // napier - "46.105.97.110", // newtonia - "5.135.82.176", // VM via napier - "5.135.82.177", - "5.135.82.178", - "5.135.82.179", - "5.135.82.180", - "5.135.82.181", - "5.135.82.182", - "5.135.82.183", - "5.135.82.184", - "5.135.82.185", - "5.135.82.186", - "5.135.82.187", - "5.135.82.188", - "5.135.82.189", - "5.135.82.190", - "5.135.82.191", - "5.196.38.16", // VM via newtonia - "5.196.38.17", - "5.196.38.18", - "5.196.38.19", - "5.196.38.20", - "5.196.38.21", - "5.196.38.22", - "5.196.38.23", - "5.196.38.24", - "5.196.38.25", - "5.196.38.26", - "5.196.38.27", - "5.196.38.28", - "5.196.38.29", - "5.196.38.30", - "5.196.38.31", - "54.36.142.176", // VM via nash - "54.36.142.177", - "54.36.142.178", - "54.36.142.179", - "54.36.142.180", - "54.36.142.181", - "54.36.142.182", - "54.36.142.183", - "54.36.142.184", - "54.36.142.185", - "54.36.142.186", - "54.36.142.187", - "54.36.142.188", - "54.36.142.189", - "54.36.142.190", - "54.36.142.191", - "94.23.30.104", // nash + "0:0:0:0:0:0:0:1", // localhost + "ff02:0:0:0:0:1:", // (char*)0 }; diff --git a/socket-sniff/socket-sniff.c b/socket-sniff/socket-sniff.c index 3048c0d..e939712 100644 --- a/socket-sniff/socket-sniff.c +++ b/socket-sniff/socket-sniff.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,19 +7,21 @@ #include #include #include +#include #include #include #include -#include + +#include // Seconds between outputs -#define DELAY 5 +static int DELAY = 5; // Byte count fade-out between displays -#define FADE 10000 +static int FADE = 10000; // Number of top usage to report -#define WORST 20 +static int WORST = 20; // Number of characters for text format IP holdings #define IPBUFMAX 40 @@ -37,73 +40,156 @@ static void die(char *m) { exit( 1 ); } -static int Count_hashcode(htable *table,unsigned char *key) { - int value = 0; - int i = 0; - while ( *key ) { - value += *(key++) + (i++); - value += i; - } - return value; +// Return pointer to the key for an item +static void *Countp_itemkey(void *item) { + return ((Count*) item)->ip; +} + +// Return 1 if the item has the key, or 0 otherwise. +static int Countp_haskey(void *item,void *key) { + return memcmp( key, Countp_itemkey( item ), IPBUFMAX ) == 0; } -static htable TBL = HTABLEINIT( Count, ip, Count_hashcode ); -static Count *last_add; +// Returns the hashcode for a key +static unsigned long Countp_hashcode(void *key) { + return hashvector_hashcode( key, IPBUFMAX ); +} + +static hashvector TBL = { + .table = { 256, 0 }, + .fill = 0, + .holes = 0, + .keyhashcode = Countp_hashcode, + .itemkey = Countp_itemkey, + .haskey = Countp_haskey +}; + static char buffer[ IPBUFMAX ]; -#include "ignores.i" +/*============================================================ + * Reading ignore lines. + */ +// Return pointer to the key for an item +static void *charp_itemkey(void *item) { + return item; +} -static struct { - Count *table[ WORST ]; - int fill; - int lowest; -} worst; +// Return 1 if the item has the key, or 0 otherwise. +static int charp_haskey(void *item,void *key) { + return strcmp( key, item ) == 0; +} -static int Countp_compare(const void *ax, const void *bx) { - Count *a = *(Count**) ax; - Count *b = *(Count**) bx; - int x = b->total - a->total; - if ( x != 0 ) { - if ( a->last == 0 ) { - return ( b->last == 0 )? x : -1; +// Returns the hashcode for a key +static unsigned long charp_hashcode(void *key) { + return hashvector_hashcode( key, strlen( (const char *) key ) ); +} + +static hashvector IGN = { + .table = { 256, 0 }, + .fill = 0, + .holes = 0, + .keyhashcode = charp_hashcode, + .itemkey = charp_itemkey, + .haskey = charp_haskey +}; + +static void read_ignore_file(char *filename) { + #define RDBLKSZ 1000000 + static char block[ RDBLKSZ ]; + static char *cur = block; + static char *end = block; + int fd = open( filename, O_RDONLY ); + if ( fd < 0 ) { + die( "Cannot load the ignare file." ); + } + for ( ;; ) { + char *p = cur; + size_t n; + for ( ;; ) { // move p to end of line + while ( p < end && *p != '\n' ) { + p++; + } + if ( p < end ) { + break; + } + if ( cur != block && cur != end ) { + memmove( cur, block, end - cur ); + end -= cur - block; + cur = block; + p = end; + } + n = RDBLKSZ - ( end - cur ); + n = read( fd, end, n ); + if ( n <= 0 ) { + return; // All done + } + end += n; } + // Line from cur to '\n' at p < end. + char *ip = calloc( 1, p - cur + 1 ); + memcpy( ip, cur, p - cur ); + cur = p + 1; + hashvector_add( &IGN, ip ); } - x = b->last - a->last; - return x; } -static void add_worst_ordered(Count *item) { - if ( worst.fill < WORST ) { - worst.table[ worst.fill++ ] = item; - if ( worst.fill == WORST ) { - qsort( worst.table, worst.fill, sizeof( Count* ), Countp_compare ); - } - return; +/*============================================================*/ + +static int Countp_compare(const void *ax, const void *bx) { + Count *a = (Count*) ax; + Count *b = (Count*) bx; + if ( b->ignore ) { + return 1; } - Count **repl = bsearch( - &item, worst.table, worst.fill, sizeof( Count* ), Countp_compare ); - if ( repl == 0 ) { - return; + if ( a->ignore ) { + return -1; } - int size = (char*) &worst.table[ worst.fill - 1 ] - (char*) repl; - if ( size > 0 ) { - memmove( repl + 1, repl, size ); + int x = a->total - b->total; + if ( x ) { + return x; } - *repl = item; + return a->last - b->last; } +static int Countp_fade_and_print(unsigned long index,void *x,void *d) { + if ( x ) { + Count *item = (Count *) x; + item->last = item->accum; + item->total += item->last - FADE; + item->accum = 0; + if ( item->total <= 0 ) { + item->total = 0; + } else if ( index < WORST && item->ignore == 0 ) { + fprintf( stdout, "... %s %d %d\n", + item->ip, item->total, item->last ); + } + } + return 0; +} + +static int Countp_reclaim(pvector *pv,unsigned long ix,void *item,void *data) { + return 0; +} + + +// ip points to [ IPBUFMAX ] of ip address in text static void add_show_table(char *ip,size_t length) { static time_t show = 0; Count *item; - int i = htfind( &TBL, ip, (unsigned char **) &item ); + int i = hashvector_find( &TBL, ip, (void**) &item ); if ( i == 0 ) { item = (Count *) calloc( 1, sizeof( Count ) ); memcpy( item->ip, ip, strlen( ip ) ); item->accum = length; - item->ignore = ignored( ip ); - htadd( &TBL, (unsigned char *) item ); - item->next = last_add; - last_add = item; + hashvector_add( &TBL, item ); + item->ignore = hashvector_find( &IGN, ip, 0 ); + for ( i = strlen( ip )-1; i > 1; i-- ) { + if ( ip[i] == '.' || ip[i] == ':' ) { + item->ignore |= hashvector_find( &IGN, ip, 0 ); + } + ip[i] = 0; + } + //fprintf( stdout, "add %s\n", ip ); } else { item->accum += length; } @@ -118,30 +204,13 @@ static void add_show_table(char *ip,size_t length) { if ( now.tv_sec - show > DELAY ) { show = now.tv_sec; } - show += 5; // Time for next output - // collate entries; Keep the X worst entries, but reduce all a bit - worst.fill = 0; - item = last_add; - for ( ; item; item = item->next ) { - item->last = item->accum; - item->total += item->last - FADE; - if ( item->total < 0 ) { - item->total = 0; - } - item->accum = 0; - if ( item->ignore == 0 ) { - add_worst_ordered( item ); - } - } - //fprintf( stdout, "" ); - for ( i = 0; i < worst.fill; i++ ) { - item = worst.table[ i ]; - if ( item->total && item->last ) { - fprintf( stdout, "... %s %d %d\n", - item->ip, item->total, item->last ); - } - } - fprintf( stdout, "==%d/%d/%d\n", TBL.fill, TBL.holes,TBL.size ); + show += DELAY; // Time for next output + pvector ordered = { 0, 0 }; + hashvector_contents( &TBL, &ordered ); + pvector_qsort( &ordered, Countp_compare ); + pvector_iterate( &ordered, Countp_fade_and_print, 0 ); + pvector_resize( &ordered, 0, Countp_reclaim, 0 ); + fprintf( stdout, "==%ld/%ld/%ld\n", TBL.fill, TBL.holes, TBL.table.size ); } static char *ipv4_address(char *b) { @@ -160,12 +229,44 @@ static char *ipv6_address(short *b) { int main(int argc,char **argv) { static char packet[ 2048 ]; - if ( argc != 2 ) { + int ARG = 1; + // Check for -fN to set FADE + if ( ARG < argc && strncmp( argv[ ARG ], "-d", 2 ) == 0 ) { + if ( sscanf( argv[ ARG ]+2, "%d", &DELAY ) != 1 ) { + die( "Missing/bad delay value" ); + } + fprintf( stdout, "Delay is %d seconds between reports\n", DELAY ); + ARG++; + } + if ( ARG < argc && strncmp( argv[ ARG ], "-f", 2 ) == 0 ) { + if ( sscanf( argv[ ARG ]+2, "%d", &FADE ) != 1 ) { + die( "Missing/bad fade value" ); + } + fprintf( stdout, "Fading %d bytes before reports\n", FADE ); + ARG++; + } + if ( ARG < argc && strncmp( argv[ ARG ], "-n", 2 ) == 0 ) { + if ( sscanf( argv[ ARG ]+2, "%d", &WORST ) != 1 ) { + die( "Missing/bad number to display" ); + } + fprintf( stdout, "Displaying at most %d lines in reports\n", WORST ); + ARG++; + } + if ( ARG < argc && strncmp( argv[ ARG ], "-i", 2 ) == 0 ) { + char *filename = argv[ ARG ] + 2; + if ( (*filename) == 0 ) { + die( "Missing/bad ignore filename" ); + } + read_ignore_file( filename ); + fprintf( stdout, "ignoring ip prefixes from %s\n", filename ); + ARG++; + } + if ( ARG >= argc ) { die( "Please tell which interface to sniff" ); } setbuf( stdout, 0 ); int N; - char *iface = argv[ argc - 1 ]; + char *iface = argv[ ARG ]; int fd = socket( AF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) ); char flags[4] = { 1,0,0,0 }; if ( fd < 0 ) { @@ -189,10 +290,17 @@ int main(int argc,char **argv) { int code = ntohs( *((short*)(packet+12)) ); if ( code == 0x0800 ) { // 14+12=src 14+16=dst - add_show_table( ipv4_address( packet+30 ), N ); + char *p = ipv4_address( packet+30 ); + if ( ( strncmp( p, "127.", 4 ) != 0 ) ) { + add_show_table( p, N ); + } } else if ( code == 0x86dd ) { // 14+8=src 14+24=dst - add_show_table( ipv6_address( (short*)(packet+38) ), N ); + char *p = ipv6_address( (short*)(packet+38) ); + if ( ( strncmp( p, "ff02:0:0:0:0:", 13 ) != 0 ) && + ( strncmp( p, "0:0:0:0:0:0:0:1", 15 ) != 0 ) ) { + add_show_table( p, N ); + } } else if ( code == 0x0800 ) { // ignore } else if ( code == 0x8100 ) { -- 2.39.2