expanded tests
[rrq/rrqmisc.git] / socket-sniff / socket-sniff.c
index e939712b3d8a2935096c86edf2ec4200e2639d32..545c9f7019690413caded5f65221667a781d5a0d 100644 (file)
@@ -23,18 +23,25 @@ static int FADE = 10000;
 // Number of top usage to report
 static int WORST = 20;
 
+// Drop-out age
+static int OLD = 600;
+
 // Number of characters for text format IP holdings
 #define IPBUFMAX 40
 
+// Count record for IP -> length mapping
 typedef struct _Count {
-    struct _Count *next;
-    int ignore;
-    int last;
-    int accum;
-    int total;
-    char ip[ IPBUFMAX ];
+    struct _Count *next; // Next Count in time order
+    struct _Count *prev; // Previous Count in time order
+    struct timeval when; // Last update time for this Count record
+    int ignore; // Flag to leave out from reports
+    int last;   // The saved accumulation from the last report period
+    int accum;  // Current accumulation
+    int total;  // The total accumulation (reduced by fading)
+    char ip[ IPBUFMAX ]; // The IP concerned, in ascii
 } Count;
 
+// Print message and exit
 static void die(char *m) {
     fprintf( stderr, "%s\n", m );
     exit( 1 );
@@ -55,8 +62,9 @@ static unsigned long Countp_hashcode(void *key) {
     return hashvector_hashcode( key, IPBUFMAX );
 }
 
+// The hashvector of seen IP
 static hashvector TBL = {
-    .table = { 256, 0 },
+    .table = { VECTOR_SLOTS, 0 },
     .fill = 0,
     .holes = 0,
     .keyhashcode = Countp_hashcode,
@@ -64,6 +72,13 @@ static hashvector TBL = {
     .haskey = Countp_haskey
 };
 
+// The Count records in time order
+static struct {
+    Count *head;
+    Count *tail;
+} trail;
+
+// Temporary buffer for IP addresses in ascii
 static char buffer[ IPBUFMAX ];
 
 /*============================================================
@@ -167,7 +182,7 @@ static int Countp_fade_and_print(unsigned long index,void *x,void *d) {
     return 0;
 }
 
-static int Countp_reclaim(pvector *pv,unsigned long ix,void *item,void *data) {
+static int Countp_reclaim(vector *pv,unsigned long ix,void *item,void *data) {
     return 0;
 }
 
@@ -177,10 +192,14 @@ static void add_show_table(char *ip,size_t length) {
     static time_t show = 0;
     Count *item;
     int i = hashvector_find( &TBL, ip, (void**) &item );
+    struct timeval now;
+    if ( gettimeofday( &now, 0 ) ) {
+       perror( "gettimeofday" );
+       exit( 1 );
+    }
     if ( i == 0 ) {
        item = (Count *) calloc( 1, sizeof( Count ) );
        memcpy( item->ip, ip, strlen( ip ) );
-       item->accum = length;
        hashvector_add( &TBL, item );
        item->ignore = hashvector_find( &IGN, ip, 0 );
        for ( i = strlen( ip )-1; i > 1; i-- ) {
@@ -189,14 +208,43 @@ static void add_show_table(char *ip,size_t length) {
            }
            ip[i] = 0;
        }
-       //fprintf( stdout, "add %s\n", ip );
+       fprintf( stdout, "add %s\n", item->ip );
     } else {
-       item->accum += length;
+    // Unlink item from the trail
+       if ( item->next ) {
+           item->next->prev = item->prev;
+       }
+       if ( item->prev ) {
+           item->prev->next = item->next;
+       }
+       if ( trail.head == item ) {
+           trail.head = item->next;
+       }
+       if ( trail.tail == item ) {
+           trail.tail = item->prev;
+       }
+       item->prev = item->next = 0;
     }
-    struct timeval now;
-    if ( gettimeofday( &now, 0 ) ) {
-       perror( "gettimeofday" );
-       exit( 1 );
+    item->accum += length;
+    item->when = now;
+    // Link in item to the trail end
+    if ( trail.head == 0 ) {
+       trail.head = item;
+    } else {
+       trail.tail->next = item;
+       item->prev = trail.tail;
+    }
+    trail.tail = item;
+    // Drop counters older than an hour
+    while ( trail.head->when.tv_sec + OLD < item->when.tv_sec ) {
+       Count *old = trail.head;
+       trail.head = old->next;
+       if ( trail.head ) {
+           trail.head->prev = 0;
+       }
+       fprintf( stdout, "drop %s\n", old->ip );
+       hashvector_delete( &TBL, old );
+       free( old );
     }
     if ( now.tv_sec < show ) {
        return;
@@ -205,11 +253,11 @@ static void add_show_table(char *ip,size_t length) {
        show = now.tv_sec;
     }
     show += DELAY; // Time for next output
-    pvector ordered = { 0, 0 };
+    vector 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 );
+    vector_qsort( &ordered, Countp_compare );
+    vector_iterate( &ordered, Countp_fade_and_print, 0 );
+    vector_resize( &ordered, 0, Countp_reclaim, 0 );
     fprintf( stdout, "==%ld/%ld/%ld\n", TBL.fill, TBL.holes, TBL.table.size );
 }
 
@@ -252,6 +300,13 @@ int main(int argc,char **argv) {
        fprintf( stdout, "Displaying at most %d lines in reports\n", WORST );
        ARG++;
     }
+    if ( ARG < argc && strncmp( argv[ ARG ], "-a", 2 ) == 0 ) {
+       if ( sscanf( argv[ ARG ]+2, "%d", &OLD ) != 1 ) {
+           die( "Missing/bad drop-out age (seconds)" );
+       }
+       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 ) {
@@ -301,10 +356,8 @@ int main(int argc,char **argv) {
                 ( 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 ) {
-           // ignore
+           // ignore VLAN
        } else {
            // funny code
        }