From: Ralph Ronnquist Date: Wed, 15 Jun 2022 00:05:51 +0000 (+1000) Subject: initial X-Git-Tag: 0.1~32 X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=d596ebac3d36c4dd69485f49daa05e673dad0def;p=rrq%2Frrqmisc.git initial --- diff --git a/socket-sniff/Makefile b/socket-sniff/Makefile new file mode 100644 index 0000000..e90a6de --- /dev/null +++ b/socket-sniff/Makefile @@ -0,0 +1,11 @@ +default: socket-sniff + +.INTERMEDIATE: socket-sniff.o +socket-sniff.o: CFLAGS = -Wall -I../htable -g +socket-sniff.o: socket-sniff.c | ignores.i + +socket-sniff: LDLIBS = -L../htable -lhtable +socket-sniff: socket-sniff.o + +clean: + rm -f socket-sniff diff --git a/socket-sniff/ignores.i b/socket-sniff/ignores.i new file mode 100644 index 0000000..79728bb --- /dev/null +++ b/socket-sniff/ignores.i @@ -0,0 +1,113 @@ +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 + (char*)0 +}; + +// Return the size of the IGN table +static int IGN_count() { + int i = 0; + while ( IGNORES[ i ] != 0 ) { + i++; + } + return i; +} + +/** + * Compare an IP against an ignore entry of width w. + * return 0 if ip starts with ign, <0 if ip < ign, and >0 if ip > ign + */ +static int IGN_cmp(const void *ipx, const void *ignx) { + char *ip = (char *) ipx; + char *ign = *(char**) ignx; + while ( *ign ) { + if ( *ip == 0 ) { + return -1; + } + int c = *(ip++) - *(ign++); + if ( c ) { + return c; + } + } + return 0; +} + +static int ignored(char *ip) { + static int IGN_size = -1; + if ( IGN_size == -1 ) { + IGN_size = IGN_count(); + } + return bsearch( ip, IGNORES, IGN_size, sizeof( char* ), IGN_cmp )? 1 : 0; +} diff --git a/socket-sniff/socket-sniff.c b/socket-sniff/socket-sniff.c new file mode 100644 index 0000000..6844359 --- /dev/null +++ b/socket-sniff/socket-sniff.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Seconds between outputs +#define DELAY 5 + +// Byte count fade-out between displays +#define FADE 10000 + +// Number of top usage to report +#define WORST 20 + +// Number of characters for text format IP holdings +#define IPBUFMAX 40 + +typedef struct _Count { + struct _Count *next; + int ignore; + int last; + int accum; + int total; + char ip[ IPBUFMAX ]; +} Count; + +static void die(char *m) { + fprintf( stderr, "%s\n", 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; +} + +static htable TBL = HTABLEINIT( Count, ip, Count_hashcode ); +static Count *last_add; +static char buffer[ IPBUFMAX ]; + +#include "ignores.i" + +static struct { + Count *table[ WORST ]; + int fill; + int lowest; +} worst; + +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; + } + } + 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; + } + Count **repl = bsearch( + &item, worst.table, worst.fill, sizeof( Count* ), Countp_compare ); + if ( repl == 0 ) { + return; + } + int size = (char*) &worst.table[ worst.fill - 1 ] - (char*) repl; + if ( size > 0 ) { + memmove( repl + 1, repl, size ); + } + *repl = item; +} + +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 ); + 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; + } else { + item->accum += length; + } + struct timeval now; + if ( gettimeofday( &now, 0 ) ) { + perror( "gettimeofday" ); + exit( 1 ); + } + if ( now.tv_sec < show ) { + return; + } + 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 ); +} + +static char *ipv4_address(char *b) { + memset( buffer, 0, sizeof( buffer ) ); + sprintf( buffer, "%hhu.%hhu.%hhu.%hhu", b[0], b[1], b[2], b[3] ); + return buffer; +} + +static char *ipv6_address(short *b) { + memset( buffer, 0, sizeof( buffer ) ); + sprintf( buffer, "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]), + ntohs(b[4]), ntohs(b[5]), ntohs(b[6]), ntohs(b[7]) ); + return buffer; +} + +int main(int argc,char **argv) { + static char packet[ 2048 ]; + if ( argc != 2 ) { + die( "Please tell which interface to sniff" ); + } + setbuf( stdout, 0 ); + int N; + char *iface = argv[ argc - 1 ]; + int fd = socket( AF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) ); + char flags[4] = { 1,0,0,0 }; + if ( fd < 0 ) { + perror( "what?" ); + die( "socket" ); + } + if ( fd < 0 ) { + die( "socket" ); + } + N = strlen(iface); + if ( setsockopt( fd, SOL_SOCKET, SO_BINDTODEVICE, iface, N ) ) { + die( "setsockopt bind to device" ); + } + if ( setsockopt( fd, SOL_SOCKET, SO_BROADCAST, &flags, 4 ) ) { + die( "setsockopt broadcast" ); + } + while ( ( N = read( fd, packet, 2048 ) ) > 0 ) { + if ( N < 54 ) { + continue; + } + int code = ntohs( *((short*)(packet+12)) ); + if ( code == 0x0800 ) { + // 14+12=src 14+16=dst + add_show_table( ipv4_address( packet+30 ), N ); + } else if ( code == 0x86dd ) { + // 14+8=src 14+24=dst + add_show_table( ipv6_address( (short*)(packet+38) ), N ); + } else if ( code == 0x0800 ) { + // ignore + } else if ( code == 0x8100 ) { + // ignore + } else { + // funny code + } + } + return 0; +}