xref: /plan9/sys/src/cmd/netstat.c (revision 80f6c381da98f5d77621b17cfed932f5075ed924)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ip.h>
53e12c5d1SDavid du Colombier #include <ndb.h>
63e12c5d1SDavid du Colombier 
79a747e4fSDavid du Colombier void	pip(char*, Dir*);
89a747e4fSDavid du Colombier void	nstat(char*, void (*)(char*, Dir*));
99a747e4fSDavid du Colombier void	pipifc(void);
103e12c5d1SDavid du Colombier 
113e12c5d1SDavid du Colombier Biobuf	out;
127dd7cddfSDavid du Colombier char	*netroot;
1368412abfSDavid du Colombier char *proto[20];
1468412abfSDavid du Colombier int nproto;
157dd7cddfSDavid du Colombier int	notrans;
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier void
usage(void)1868412abfSDavid du Colombier usage(void)
1968412abfSDavid du Colombier {
2068412abfSDavid du Colombier 	fprint(2, "usage: %s [-in] [-p proto] [network-dir]\n", argv0);
217dd7cddfSDavid du Colombier 	exits("usage");
227dd7cddfSDavid du Colombier }
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier void
main(int argc,char * argv[])257dd7cddfSDavid du Colombier main(int argc, char *argv[])
263e12c5d1SDavid du Colombier {
277dd7cddfSDavid du Colombier 	int justinterfaces = 0;
28d9306527SDavid du Colombier 	int i, tot, fd;
29d9306527SDavid du Colombier 	Dir *d;
30d9306527SDavid du Colombier 	char buf[128];
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier 	ARGBEGIN{
3368412abfSDavid du Colombier 	case 'i':
3468412abfSDavid du Colombier 		justinterfaces = 1;
3568412abfSDavid du Colombier 		break;
367dd7cddfSDavid du Colombier 	case 'n':
377dd7cddfSDavid du Colombier 		notrans = 1;
387dd7cddfSDavid du Colombier 		break;
3968412abfSDavid du Colombier 	case 'p':
4068412abfSDavid du Colombier 		if(nproto >= nelem(proto))
4168412abfSDavid du Colombier 			sysfatal("too many protos");
4268412abfSDavid du Colombier 		proto[nproto++] = EARGF(usage());
437dd7cddfSDavid du Colombier 		break;
447dd7cddfSDavid du Colombier 	default:
457dd7cddfSDavid du Colombier 		usage();
467dd7cddfSDavid du Colombier 	}ARGEND;
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier 	netroot = "/net";
497dd7cddfSDavid du Colombier 	switch(argc){
507dd7cddfSDavid du Colombier 	case 0:
517dd7cddfSDavid du Colombier 		break;
527dd7cddfSDavid du Colombier 	case 1:
537dd7cddfSDavid du Colombier 		netroot = argv[0];
547dd7cddfSDavid du Colombier 		break;
557dd7cddfSDavid du Colombier 	default:
567dd7cddfSDavid du Colombier 		usage();
577dd7cddfSDavid du Colombier 	}
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier 	Binit(&out, 1, OWRITE);
603e12c5d1SDavid du Colombier 
617dd7cddfSDavid du Colombier 	if(justinterfaces){
629a747e4fSDavid du Colombier 		pipifc();
637dd7cddfSDavid du Colombier 		exits(0);
647dd7cddfSDavid du Colombier 	}
657dd7cddfSDavid du Colombier 
6668412abfSDavid du Colombier 	if(nproto){
6768412abfSDavid du Colombier 		for(i=0; i<nproto; i++)
6868412abfSDavid du Colombier 			nstat(proto[i], pip);
6968412abfSDavid du Colombier 	}else{
70*80f6c381SDavid du Colombier 		fd = open(netroot, OREAD);
71*80f6c381SDavid du Colombier 		if(fd < 0)
72*80f6c381SDavid du Colombier 			sysfatal("open %s: %r", netroot);
73*80f6c381SDavid du Colombier 
74d9306527SDavid du Colombier 		tot = dirreadall(fd, &d);
75d9306527SDavid du Colombier 		for(i=0; i<tot; i++){
76d9306527SDavid du Colombier 			if(strcmp(d[i].name, "ipifc") == 0)
77d9306527SDavid du Colombier 				continue;
78d9306527SDavid du Colombier 			snprint(buf, sizeof buf, "%s/%s/0/local", netroot, d[i].name);
79d9306527SDavid du Colombier 			if(access(buf, 0) >= 0)
80d9306527SDavid du Colombier 				nstat(d[i].name, pip);
81d9306527SDavid du Colombier 		}
8268412abfSDavid du Colombier 	}
833e12c5d1SDavid du Colombier 	exits(0);
843e12c5d1SDavid du Colombier }
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier void
nstat(char * net,void (* f)(char *,Dir *))879a747e4fSDavid du Colombier nstat(char *net, void (*f)(char*, Dir*))
883e12c5d1SDavid du Colombier {
899a747e4fSDavid du Colombier 	int fdir, i, tot;
909a747e4fSDavid du Colombier 	Dir *dir;
919a747e4fSDavid du Colombier 	char buf[128];
923e12c5d1SDavid du Colombier 
939a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s", netroot, net);
949a747e4fSDavid du Colombier 	fdir = open(buf, OREAD);
953e12c5d1SDavid du Colombier 	if(fdir < 0)
963e12c5d1SDavid du Colombier 		return;
973e12c5d1SDavid du Colombier 
989a747e4fSDavid du Colombier 	tot = dirreadall(fdir, &dir);
999a747e4fSDavid du Colombier 	for(i = 0; i < tot; i++) {
1009a747e4fSDavid du Colombier 		(*f)(net, &dir[i]);
1013e12c5d1SDavid du Colombier 		Bflush(&out);
1023e12c5d1SDavid du Colombier 	}
1039a747e4fSDavid du Colombier 	free(dir);
1043e12c5d1SDavid du Colombier 	close(fdir);
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier char*
getport(char * net,char * p)1083e12c5d1SDavid du Colombier getport(char *net, char *p)
1093e12c5d1SDavid du Colombier {
11057837e0bSDavid du Colombier 	static char port[10];
1113e12c5d1SDavid du Colombier 
11257837e0bSDavid du Colombier 	strncpy(port, p, sizeof(port)-1);
11357837e0bSDavid du Colombier 	port[sizeof(port)-1] = 0;
11457837e0bSDavid du Colombier 	if(notrans || (p = csgetvalue(netroot, "port", p, net, nil)) == nil)
11557837e0bSDavid du Colombier 		return port;
11657837e0bSDavid du Colombier 	strncpy(port, p, sizeof(port)-1);
11757837e0bSDavid du Colombier 	port[sizeof(port)-1] = 0;
11857837e0bSDavid du Colombier 	free(p);
11957837e0bSDavid du Colombier 	return port;
1203e12c5d1SDavid du Colombier }
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier void
pip(char * net,Dir * db)1239a747e4fSDavid du Colombier pip(char *net, Dir *db)
1243e12c5d1SDavid du Colombier {
1253e12c5d1SDavid du Colombier 	int n, fd;
1267dd7cddfSDavid du Colombier 	char buf[128], *p;
12757837e0bSDavid du Colombier 	char *dname;
1283e12c5d1SDavid du Colombier 
1299a747e4fSDavid du Colombier 	if(strcmp(db->name, "clone") == 0)
1303e12c5d1SDavid du Colombier 		return;
1319a747e4fSDavid du Colombier 	if(strcmp(db->name, "stats") == 0)
1327dd7cddfSDavid du Colombier 		return;
1333e12c5d1SDavid du Colombier 
134*80f6c381SDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s/%s/status", netroot, net, db->name);
1353e12c5d1SDavid du Colombier 	fd = open(buf, OREAD);
1363e12c5d1SDavid du Colombier 	if(fd < 0)
1373e12c5d1SDavid du Colombier 		return;
1383e12c5d1SDavid du Colombier 	n = read(fd, buf, sizeof(buf));
139*80f6c381SDavid du Colombier 	close(fd);
1403e12c5d1SDavid du Colombier 	if(n < 0)
1413e12c5d1SDavid du Colombier 		return;
1423e12c5d1SDavid du Colombier 	buf[n] = 0;
1433e12c5d1SDavid du Colombier 
1443e12c5d1SDavid du Colombier 	p = strchr(buf, ' ');
1457dd7cddfSDavid du Colombier 	if(p != 0)
1467dd7cddfSDavid du Colombier 		*p = 0;
147*80f6c381SDavid du Colombier 	p = strrchr(buf, '\n');
148*80f6c381SDavid du Colombier 	if(p != 0)
149*80f6c381SDavid du Colombier 		*p = 0;
1509a747e4fSDavid du Colombier 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, db->name, db->uid, buf);
1517dd7cddfSDavid du Colombier 
152*80f6c381SDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s/%s/local", netroot, net, db->name);
1533e12c5d1SDavid du Colombier 	fd = open(buf, OREAD);
1543e12c5d1SDavid du Colombier 	if(fd < 0) {
1553e12c5d1SDavid du Colombier 		Bprint(&out, "\n");
1563e12c5d1SDavid du Colombier 		return;
1573e12c5d1SDavid du Colombier 	}
1583e12c5d1SDavid du Colombier 	n = read(fd, buf, sizeof(buf));
159*80f6c381SDavid du Colombier 	close(fd);
1603e12c5d1SDavid du Colombier 	if(n < 0) {
1613e12c5d1SDavid du Colombier 		Bprint(&out, "\n");
1623e12c5d1SDavid du Colombier 		return;
1633e12c5d1SDavid du Colombier 	}
1643e12c5d1SDavid du Colombier 	buf[n-1] = 0;
1653e12c5d1SDavid du Colombier 	p = strchr(buf, '!');
1663e12c5d1SDavid du Colombier 	if(p == 0) {
1673e12c5d1SDavid du Colombier 		Bprint(&out, "\n");
1683e12c5d1SDavid du Colombier 		return;
1693e12c5d1SDavid du Colombier 	}
1703e12c5d1SDavid du Colombier 	*p = '\0';
1713e12c5d1SDavid du Colombier 	Bprint(&out, "%-10s ", getport(net, p+1));
1723e12c5d1SDavid du Colombier 
173*80f6c381SDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s/%s/remote", netroot, net, db->name);
1743e12c5d1SDavid du Colombier 	fd = open(buf, OREAD);
1753e12c5d1SDavid du Colombier 	if(fd < 0) {
1763e12c5d1SDavid du Colombier 		print("\n");
1773e12c5d1SDavid du Colombier 		return;
1783e12c5d1SDavid du Colombier 	}
1793e12c5d1SDavid du Colombier 	n = read(fd, buf, sizeof(buf));
180*80f6c381SDavid du Colombier 	close(fd);
1813e12c5d1SDavid du Colombier 	if(n < 0) {
1823e12c5d1SDavid du Colombier 		print("\n");
1833e12c5d1SDavid du Colombier 		return;
1843e12c5d1SDavid du Colombier 	}
1853e12c5d1SDavid du Colombier 	buf[n-1] = 0;
1863e12c5d1SDavid du Colombier 	p = strchr(buf, '!');
187*80f6c381SDavid du Colombier 	if(p != nil)
1883e12c5d1SDavid du Colombier 		*p++ = '\0';
1893e12c5d1SDavid du Colombier 
1907dd7cddfSDavid du Colombier 	if(notrans){
1913e12c5d1SDavid du Colombier 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
1923e12c5d1SDavid du Colombier 		return;
1933e12c5d1SDavid du Colombier 	}
19457837e0bSDavid du Colombier 	dname = csgetvalue(netroot, "ip", buf, "dom", nil);
19557837e0bSDavid du Colombier 	if(dname == nil) {
1967dd7cddfSDavid du Colombier 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
1977dd7cddfSDavid du Colombier 		return;
1987dd7cddfSDavid du Colombier 	}
1997dd7cddfSDavid du Colombier 	Bprint(&out, "%-10s %s\n", getport(net, p), dname);
2007dd7cddfSDavid du Colombier 	Bflush(&out);
20157837e0bSDavid du Colombier 	free(dname);
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier void
pipifc(void)2059a747e4fSDavid du Colombier pipifc(void)
2067dd7cddfSDavid du Colombier {
2079a747e4fSDavid du Colombier 	Ipifc *ip, *nip;
2089a747e4fSDavid du Colombier 	Iplifc *lifc;
2099a747e4fSDavid du Colombier 	char buf[100];
2109a747e4fSDavid du Colombier 	int l, i;
2117dd7cddfSDavid du Colombier 
2129a747e4fSDavid du Colombier 	fmtinstall('I', eipfmt);
2139a747e4fSDavid du Colombier 	fmtinstall('M', eipfmt);
2147dd7cddfSDavid du Colombier 
2159a747e4fSDavid du Colombier 	ip = readipifc(netroot, nil, -1);
2167dd7cddfSDavid du Colombier 
2179a747e4fSDavid du Colombier 	l = 7;
2189a747e4fSDavid du Colombier 	for(nip = ip; nip; nip = nip->next){
2199a747e4fSDavid du Colombier 		for(lifc = nip->lifc; lifc; lifc = lifc->next){
2209a747e4fSDavid du Colombier 			i = snprint(buf, sizeof buf, "%I", lifc->ip);
2219a747e4fSDavid du Colombier 			if(i > l)
2229a747e4fSDavid du Colombier 				l = i;
2239a747e4fSDavid du Colombier 			i = snprint(buf, sizeof buf, "%I", lifc->net);
2249a747e4fSDavid du Colombier 			if(i > l)
2259a747e4fSDavid du Colombier 				l = i;
2269a747e4fSDavid du Colombier 		}
2279a747e4fSDavid du Colombier 	}
2287dd7cddfSDavid du Colombier 
2299a747e4fSDavid du Colombier 	for(nip = ip; nip; nip = nip->next){
2309a747e4fSDavid du Colombier 		for(lifc = nip->lifc; lifc; lifc = lifc->next)
23139734e7eSDavid du Colombier 			Bprint(&out, "%-12s %5d %-*I %5M %-*I %8lud %8lud %8lud %8lud\n",
2329a747e4fSDavid du Colombier 				nip->dev, nip->mtu,
2339a747e4fSDavid du Colombier 				l, lifc->ip, lifc->mask, l, lifc->net,
2349a747e4fSDavid du Colombier 				nip->pktin, nip->pktout,
2359a747e4fSDavid du Colombier 				nip->errin, nip->errout);
2369a747e4fSDavid du Colombier 	}
2379a747e4fSDavid du Colombier 	Bflush(&out);
2383e12c5d1SDavid du Colombier }
239