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
error(char * s)63 error(char *s)
64 {
65 char buf[ERRMAX];
66
67 errstr(buf, sizeof buf);
68 fprint(2, "snoopy: %s %s\n", buf, s);
69 exits("death");
70 }
71
72 void
warning(char * s)73 warning(char *s)
74 {
75 char buf[ERRMAX];
76
77 errstr(buf, sizeof buf);
78 fprint(2, "snoopy: %s %s\n", buf, s);
79 }
80
81 void
printproto(int p)82 printproto(int p)
83 {
84 print("\t%d(%ld %ld %ld %ld)", p, protoin[p], protopin[p], protoout[p], protopout[p]);
85 }
86
87 void
main(int argc,char * argv[])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', eipfmt);
122 fmtinstall('I', eipfmt);
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.8ld %ld", 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