xref: /plan9/sys/src/cmd/ip/measure.c (revision 274d35ba18649000b37dd5ce33abed48883c9b02)
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