1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <ip.h> 5 6 /* 7 * ether packet 8 */ 9 typedef struct Etherpkt Etherpkt; 10 struct Etherpkt { 11 uchar d[6]; 12 uchar s[6]; 13 uchar type[2]; 14 char data[1500]; 15 }; 16 #define ETHERMINTU 60 /* minimum transmit size */ 17 #define ETHERMAXTU 1514 /* maximum transmit size */ 18 #define ETHERHDRSIZE 14 /* size of an ethernet header */ 19 20 /* 21 * ip packets 22 */ 23 typedef struct Ippkt Ippkt; 24 struct Ippkt 25 { 26 uchar vihl; /* Version and header length */ 27 uchar tos; /* Type of service */ 28 uchar length[2]; /* packet length */ 29 uchar id[2]; /* Identification */ 30 uchar frag[2]; /* Fragment information */ 31 uchar ttl; /* Time to live */ 32 uchar proto; /* Protocol */ 33 uchar cksum[2]; /* Header checksum */ 34 uchar src[4]; /* Ip source */ 35 uchar dst[4]; /* Ip destination */ 36 char data[1]; 37 }; 38 39 #define IP_HDRSIZE 20 40 #define IP_UDPPROTO 17 41 #define IP_MBONEPROTO 4 42 #define IP_TCPPROTO 6 43 #define IP_ILPROTO 40 44 #define IP_ICMPPROTO 1 45 #define IP_DF 0x4000 46 #define IP_MF 0x2000 47 48 #define NetS(x) (((x)[0]<<8) | (x)[1]) 49 #define NetL(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3]) 50 51 /* 52 * run flags 53 */ 54 int debug; 55 int mbone; 56 57 ulong protoin[256]; 58 ulong protoout[256]; 59 ulong protopin[256]; 60 ulong protopout[256]; 61 62 void 63 error(char *s) 64 { 65 char buf[ERRLEN]; 66 67 errstr(buf); 68 fprint(2, "snoopy: %s %s\n", buf, s); 69 exits("death"); 70 } 71 72 void 73 warning(char *s) 74 { 75 char buf[ERRLEN]; 76 77 errstr(buf); 78 fprint(2, "snoopy: %s %s\n", buf, s); 79 } 80 81 void 82 printproto(int p) 83 { 84 print("\t%d(%d %d %d %d)", p, protoin[p], protopin[p], protoout[p], protopout[p]); 85 } 86 87 void 88 main(int argc, char *argv[]) 89 { 90 Etherpkt e; 91 Ippkt *ip; 92 long n; 93 int fd, cfd; 94 int ts, len, t; 95 long start; 96 int delta; 97 uchar target[6]; 98 char buf[256]; 99 ulong samples; 100 101 samples = -1; 102 ARGBEGIN{ 103 case 'd': 104 debug++; 105 break; 106 case 's': 107 samples = atoi(ARGF()); 108 break; 109 }ARGEND; 110 111 if(argc < 2){ 112 fprint(2, "usage: %s device ip-addr [minutes-per-sample]\n", argv0); 113 exits("usage"); 114 } 115 if(argc > 2) 116 delta = atoi(argv[2])*60*1000; 117 else 118 delta = 5*60*1000; 119 parseether(target, argv[1]); 120 121 fmtinstall('E', eipconv); 122 fmtinstall('I', eipconv); 123 124 snprint(buf, sizeof(buf), "%s!-2", argv[0]); 125 fd = dial(buf, 0, 0, &cfd); 126 if(fd < 0) 127 error("opening ether data"); 128 if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0) 129 error("connecting"); 130 131 start = 0; 132 fd = -1; 133 134 for(;;){ 135 if(fd < 0){ 136 fd = dial(buf, 0, 0, &cfd); 137 if(fd < 0) 138 error("opening ether data"); 139 if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0) 140 error("connecting"); 141 close(cfd); 142 } 143 n = read(fd, &e, sizeof(e)); 144 if(n <= 0) 145 break; 146 ts = NetL(&e.d[60]); 147 n = NetS(&e.d[58]) - ETHERHDRSIZE; 148 if(n < 0) 149 continue; 150 if(start == 0) 151 start = ts; 152 t = NetS(e.type); 153 if(t == 0x0800 || (t&0xFF00) == 0x1000){ 154 ip = (Ippkt*)e.data; 155 len = NetS(ip->length); 156 if(len > n) 157 len = n; 158 if(debug) 159 fprint(2, "%I -> %I %d\n", ip->src, ip->dst, len); 160 if(memcmp(e.s, target, 6) == 0){ 161 protopin[0]++; 162 protoin[0] += len; 163 if(ip->proto){ 164 protopin[ip->proto]++; 165 protoin[ip->proto] += len; 166 } 167 } 168 if(memcmp(e.d, target, 6) == 0){ 169 protopout[0]++; 170 protoout[0] += len; 171 if(ip->proto){ 172 protopout[ip->proto]++; 173 protoout[ip->proto] += len; 174 } 175 } 176 } 177 if(ts - start >= delta){ 178 print("%8.8d %d", time(0), ts - start); 179 printproto(0); 180 printproto(IP_MBONEPROTO); 181 printproto(IP_UDPPROTO); 182 printproto(IP_TCPPROTO); 183 print("\n"); 184 start = 0; 185 memset(protoin, 0, sizeof(protoin)); 186 memset(protoout, 0, sizeof(protoout)); 187 memset(protopin, 0, sizeof(protopin)); 188 memset(protopout, 0, sizeof(protopout)); 189 close(fd); 190 fd = -1; 191 if(--samples == 0) 192 break; 193 } 194 } 195 exits(0); 196 } 197