Change to use hashvector and externalised ignore list
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 23 Jun 2022 00:44:30 +0000 (10:44 +1000)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Thu, 23 Jun 2022 00:44:30 +0000 (10:44 +1000)
socket-sniff/Makefile
socket-sniff/ignores.i
socket-sniff/socket-sniff.c

index e90a6deaf20bab64bb94fb53d1925c43b3328452..4f8b149a8bfe44bb47ec43b55f7279fa7dea6997 100644 (file)
@@ -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:
index 79728bb09bc00e7a8ce4609dde51bff1be047604..59435d39ca2f50822c53f8b0c4dfa329063b126d 100644 (file)
@@ -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
 };
 
index 3048c0d11b3864627c7c55f73bd34a965b57b25f..e939712b3d8a2935096c86edf2ec4200e2639d32 100644 (file)
@@ -1,4 +1,5 @@
 #include <arpa/inet.h>
+#include <fcntl.h>
 #include <linux/if_ether.h>
 #include <linux/in.h>
 #include <stddef.h>
@@ -6,19 +7,21 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
-#include <htable.h>
+
+#include <hashvector.h>
 
 // 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, "\e[2J" );
-    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 ) {