17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <ip.h>
57dd7cddfSDavid du Colombier
67dd7cddfSDavid du Colombier /*
77dd7cddfSDavid du Colombier * ether packet
87dd7cddfSDavid du Colombier */
97dd7cddfSDavid du Colombier typedef struct Etherpkt Etherpkt;
107dd7cddfSDavid du Colombier struct Etherpkt {
117dd7cddfSDavid du Colombier uchar d[6];
127dd7cddfSDavid du Colombier uchar s[6];
137dd7cddfSDavid du Colombier uchar type[2];
147dd7cddfSDavid du Colombier char data[1500];
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier #define ETHERMINTU 60 /* minimum transmit size */
177dd7cddfSDavid du Colombier #define ETHERMAXTU 1514 /* maximum transmit size */
187dd7cddfSDavid du Colombier #define ETHERHDRSIZE 14 /* size of an ethernet header */
197dd7cddfSDavid du Colombier
207dd7cddfSDavid du Colombier /*
217dd7cddfSDavid du Colombier * ip packets
227dd7cddfSDavid du Colombier */
237dd7cddfSDavid du Colombier typedef struct Ippkt Ippkt;
247dd7cddfSDavid du Colombier struct Ippkt
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier uchar vihl; /* Version and header length */
277dd7cddfSDavid du Colombier uchar tos; /* Type of service */
287dd7cddfSDavid du Colombier uchar length[2]; /* packet length */
297dd7cddfSDavid du Colombier uchar id[2]; /* Identification */
307dd7cddfSDavid du Colombier uchar frag[2]; /* Fragment information */
317dd7cddfSDavid du Colombier uchar ttl; /* Time to live */
327dd7cddfSDavid du Colombier uchar proto; /* Protocol */
337dd7cddfSDavid du Colombier uchar cksum[2]; /* Header checksum */
347dd7cddfSDavid du Colombier uchar src[4]; /* Ip source */
357dd7cddfSDavid du Colombier uchar dst[4]; /* Ip destination */
367dd7cddfSDavid du Colombier char data[1];
377dd7cddfSDavid du Colombier };
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier #define IP_HDRSIZE 20
407dd7cddfSDavid du Colombier #define IP_UDPPROTO 17
417dd7cddfSDavid du Colombier #define IP_MBONEPROTO 4
427dd7cddfSDavid du Colombier #define IP_TCPPROTO 6
437dd7cddfSDavid du Colombier #define IP_ILPROTO 40
447dd7cddfSDavid du Colombier #define IP_ICMPPROTO 1
457dd7cddfSDavid du Colombier #define IP_DF 0x4000
467dd7cddfSDavid du Colombier #define IP_MF 0x2000
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier #define NetS(x) (((x)[0]<<8) | (x)[1])
497dd7cddfSDavid du Colombier #define NetL(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3])
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier /*
527dd7cddfSDavid du Colombier * run flags
537dd7cddfSDavid du Colombier */
547dd7cddfSDavid du Colombier int debug;
557dd7cddfSDavid du Colombier int mbone;
567dd7cddfSDavid du Colombier
577dd7cddfSDavid du Colombier ulong protoin[256];
587dd7cddfSDavid du Colombier ulong protoout[256];
597dd7cddfSDavid du Colombier ulong protopin[256];
607dd7cddfSDavid du Colombier ulong protopout[256];
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier void
error(char * s)637dd7cddfSDavid du Colombier error(char *s)
647dd7cddfSDavid du Colombier {
65*274d35baSDavid du Colombier char buf[ERRMAX];
667dd7cddfSDavid du Colombier
67*274d35baSDavid du Colombier errstr(buf, sizeof buf);
687dd7cddfSDavid du Colombier fprint(2, "snoopy: %s %s\n", buf, s);
697dd7cddfSDavid du Colombier exits("death");
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier
727dd7cddfSDavid du Colombier void
warning(char * s)737dd7cddfSDavid du Colombier warning(char *s)
747dd7cddfSDavid du Colombier {
75*274d35baSDavid du Colombier char buf[ERRMAX];
767dd7cddfSDavid du Colombier
77*274d35baSDavid du Colombier errstr(buf, sizeof buf);
787dd7cddfSDavid du Colombier fprint(2, "snoopy: %s %s\n", buf, s);
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier void
printproto(int p)827dd7cddfSDavid du Colombier printproto(int p)
837dd7cddfSDavid du Colombier {
84*274d35baSDavid du Colombier print("\t%d(%ld %ld %ld %ld)", p, protoin[p], protopin[p], protoout[p], protopout[p]);
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier void
main(int argc,char * argv[])887dd7cddfSDavid du Colombier main(int argc, char *argv[])
897dd7cddfSDavid du Colombier {
907dd7cddfSDavid du Colombier Etherpkt e;
917dd7cddfSDavid du Colombier Ippkt *ip;
927dd7cddfSDavid du Colombier long n;
937dd7cddfSDavid du Colombier int fd, cfd;
947dd7cddfSDavid du Colombier int ts, len, t;
957dd7cddfSDavid du Colombier long start;
967dd7cddfSDavid du Colombier int delta;
977dd7cddfSDavid du Colombier uchar target[6];
987dd7cddfSDavid du Colombier char buf[256];
997dd7cddfSDavid du Colombier ulong samples;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier samples = -1;
1027dd7cddfSDavid du Colombier ARGBEGIN{
1037dd7cddfSDavid du Colombier case 'd':
1047dd7cddfSDavid du Colombier debug++;
1057dd7cddfSDavid du Colombier break;
1067dd7cddfSDavid du Colombier case 's':
1077dd7cddfSDavid du Colombier samples = atoi(ARGF());
1087dd7cddfSDavid du Colombier break;
1097dd7cddfSDavid du Colombier }ARGEND;
1107dd7cddfSDavid du Colombier
1117dd7cddfSDavid du Colombier if(argc < 2){
1127dd7cddfSDavid du Colombier fprint(2, "usage: %s device ip-addr [minutes-per-sample]\n", argv0);
1137dd7cddfSDavid du Colombier exits("usage");
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier if(argc > 2)
1167dd7cddfSDavid du Colombier delta = atoi(argv[2])*60*1000;
1177dd7cddfSDavid du Colombier else
1187dd7cddfSDavid du Colombier delta = 5*60*1000;
1197dd7cddfSDavid du Colombier parseether(target, argv[1]);
1207dd7cddfSDavid du Colombier
121*274d35baSDavid du Colombier fmtinstall('E', eipfmt);
122*274d35baSDavid du Colombier fmtinstall('I', eipfmt);
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s!-2", argv[0]);
1257dd7cddfSDavid du Colombier fd = dial(buf, 0, 0, &cfd);
1267dd7cddfSDavid du Colombier if(fd < 0)
1277dd7cddfSDavid du Colombier error("opening ether data");
1287dd7cddfSDavid du Colombier if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
1297dd7cddfSDavid du Colombier error("connecting");
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier start = 0;
1327dd7cddfSDavid du Colombier fd = -1;
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier for(;;){
1357dd7cddfSDavid du Colombier if(fd < 0){
1367dd7cddfSDavid du Colombier fd = dial(buf, 0, 0, &cfd);
1377dd7cddfSDavid du Colombier if(fd < 0)
1387dd7cddfSDavid du Colombier error("opening ether data");
1397dd7cddfSDavid du Colombier if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
1407dd7cddfSDavid du Colombier error("connecting");
1417dd7cddfSDavid du Colombier close(cfd);
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier n = read(fd, &e, sizeof(e));
1447dd7cddfSDavid du Colombier if(n <= 0)
1457dd7cddfSDavid du Colombier break;
1467dd7cddfSDavid du Colombier ts = NetL(&e.d[60]);
1477dd7cddfSDavid du Colombier n = NetS(&e.d[58]) - ETHERHDRSIZE;
1487dd7cddfSDavid du Colombier if(n < 0)
1497dd7cddfSDavid du Colombier continue;
1507dd7cddfSDavid du Colombier if(start == 0)
1517dd7cddfSDavid du Colombier start = ts;
1527dd7cddfSDavid du Colombier t = NetS(e.type);
1537dd7cddfSDavid du Colombier if(t == 0x0800 || (t&0xFF00) == 0x1000){
1547dd7cddfSDavid du Colombier ip = (Ippkt*)e.data;
1557dd7cddfSDavid du Colombier len = NetS(ip->length);
1567dd7cddfSDavid du Colombier if(len > n)
1577dd7cddfSDavid du Colombier len = n;
1587dd7cddfSDavid du Colombier if(debug)
1597dd7cddfSDavid du Colombier fprint(2, "%I -> %I %d\n", ip->src, ip->dst, len);
1607dd7cddfSDavid du Colombier if(memcmp(e.s, target, 6) == 0){
1617dd7cddfSDavid du Colombier protopin[0]++;
1627dd7cddfSDavid du Colombier protoin[0] += len;
1637dd7cddfSDavid du Colombier if(ip->proto){
1647dd7cddfSDavid du Colombier protopin[ip->proto]++;
1657dd7cddfSDavid du Colombier protoin[ip->proto] += len;
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier if(memcmp(e.d, target, 6) == 0){
1697dd7cddfSDavid du Colombier protopout[0]++;
1707dd7cddfSDavid du Colombier protoout[0] += len;
1717dd7cddfSDavid du Colombier if(ip->proto){
1727dd7cddfSDavid du Colombier protopout[ip->proto]++;
1737dd7cddfSDavid du Colombier protoout[ip->proto] += len;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier if(ts - start >= delta){
178*274d35baSDavid du Colombier print("%8.8ld %ld", time(0), ts - start);
1797dd7cddfSDavid du Colombier printproto(0);
1807dd7cddfSDavid du Colombier printproto(IP_MBONEPROTO);
1817dd7cddfSDavid du Colombier printproto(IP_UDPPROTO);
1827dd7cddfSDavid du Colombier printproto(IP_TCPPROTO);
1837dd7cddfSDavid du Colombier print("\n");
1847dd7cddfSDavid du Colombier start = 0;
1857dd7cddfSDavid du Colombier memset(protoin, 0, sizeof(protoin));
1867dd7cddfSDavid du Colombier memset(protoout, 0, sizeof(protoout));
1877dd7cddfSDavid du Colombier memset(protopin, 0, sizeof(protopin));
1887dd7cddfSDavid du Colombier memset(protopout, 0, sizeof(protopout));
1897dd7cddfSDavid du Colombier close(fd);
1907dd7cddfSDavid du Colombier fd = -1;
1917dd7cddfSDavid du Colombier if(--samples == 0)
1927dd7cddfSDavid du Colombier break;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier exits(0);
1967dd7cddfSDavid du Colombier }
197