2 #include <linux/if_ether.h>
8 #include <sys/socket.h>
10 #include <sys/types.h>
14 // Seconds between outputs
17 // Byte count fade-out between displays
20 // Number of top usage to report
23 // Number of characters for text format IP holdings
26 typedef struct _Count {
35 static void die(char *m) {
36 fprintf( stderr, "%s\n", m );
40 static int Count_hashcode(htable *table,unsigned char *key) {
44 value += *(key++) + (i++);
50 static htable TBL = HTABLEINIT( Count, ip, Count_hashcode );
51 static Count *last_add;
52 static char buffer[ IPBUFMAX ];
57 Count *table[ WORST ];
62 static int Countp_compare(const void *ax, const void *bx) {
63 Count *a = *(Count**) ax;
64 Count *b = *(Count**) bx;
65 int x = b->total - a->total;
68 return ( b->last == 0 )? x : -1;
71 x = b->last - a->last;
75 static void add_worst_ordered(Count *item) {
76 if ( worst.fill < WORST ) {
77 worst.table[ worst.fill++ ] = item;
78 if ( worst.fill == WORST ) {
79 qsort( worst.table, worst.fill, sizeof( Count* ), Countp_compare );
83 Count **repl = bsearch(
84 &item, worst.table, worst.fill, sizeof( Count* ), Countp_compare );
88 int size = (char*) &worst.table[ worst.fill - 1 ] - (char*) repl;
90 memmove( repl + 1, repl, size );
95 static void add_show_table(char *ip,size_t length) {
96 static time_t show = 0;
98 int i = htfind( &TBL, ip, (unsigned char **) &item );
100 item = (Count *) calloc( 1, sizeof( Count ) );
101 memcpy( item->ip, ip, strlen( ip ) );
102 item->accum = length;
103 item->ignore = ignored( ip );
104 htadd( &TBL, (unsigned char *) item );
105 item->next = last_add;
108 item->accum += length;
111 if ( gettimeofday( &now, 0 ) ) {
112 perror( "gettimeofday" );
115 if ( now.tv_sec < show ) {
118 if ( now.tv_sec - show > DELAY ) {
121 show += 5; // Time for next output
122 // collate entries; Keep the X worst entries, but reduce all a bit
125 for ( ; item; item = item->next ) {
126 item->last = item->accum;
127 item->total += item->last - FADE;
128 if ( item->total < 0 ) {
132 if ( item->ignore == 0 ) {
133 add_worst_ordered( item );
136 //fprintf( stdout, "
\e[2J" );
137 for ( i = 0; i < worst.fill; i++ ) {
138 item = worst.table[ i ];
139 if ( item->total && item->last ) {
140 fprintf( stdout, "... %s %d %d\n",
141 item->ip, item->total, item->last );
144 fprintf( stdout, "==%d/%d/%d\n", TBL.fill, TBL.holes,TBL.size );
147 static char *ipv4_address(char *b) {
148 memset( buffer, 0, sizeof( buffer ) );
149 sprintf( buffer, "%hhu.%hhu.%hhu.%hhu", b[0], b[1], b[2], b[3] );
153 static char *ipv6_address(short *b) {
154 memset( buffer, 0, sizeof( buffer ) );
155 sprintf( buffer, "%x:%x:%x:%x:%x:%x:%x:%x",
156 ntohs(b[0]), ntohs(b[1]), ntohs(b[2]), ntohs(b[3]),
157 ntohs(b[4]), ntohs(b[5]), ntohs(b[6]), ntohs(b[7]) );
161 int main(int argc,char **argv) {
162 static char packet[ 2048 ];
164 die( "Please tell which interface to sniff" );
168 char *iface = argv[ argc - 1 ];
169 int fd = socket( AF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) );
170 char flags[4] = { 1,0,0,0 };
179 if ( setsockopt( fd, SOL_SOCKET, SO_BINDTODEVICE, iface, N ) ) {
180 die( "setsockopt bind to device" );
182 if ( setsockopt( fd, SOL_SOCKET, SO_BROADCAST, &flags, 4 ) ) {
183 die( "setsockopt broadcast" );
185 while ( ( N = read( fd, packet, 2048 ) ) > 0 ) {
189 int code = ntohs( *((short*)(packet+12)) );
190 if ( code == 0x0800 ) {
191 // 14+12=src 14+16=dst
192 add_show_table( ipv4_address( packet+30 ), N );
193 } else if ( code == 0x86dd ) {
194 // 14+8=src 14+24=dst
195 add_show_table( ipv6_address( (short*)(packet+38) ), N );
196 } else if ( code == 0x0800 ) {
198 } else if ( code == 0x8100 ) {