xref: /plan9/sys/src/cmd/netstat.c (revision 80f6c381da98f5d77621b17cfed932f5075ed924)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ip.h>
5 #include <ndb.h>
6 
7 void	pip(char*, Dir*);
8 void	nstat(char*, void (*)(char*, Dir*));
9 void	pipifc(void);
10 
11 Biobuf	out;
12 char	*netroot;
13 char *proto[20];
14 int nproto;
15 int	notrans;
16 
17 void
usage(void)18 usage(void)
19 {
20 	fprint(2, "usage: %s [-in] [-p proto] [network-dir]\n", argv0);
21 	exits("usage");
22 }
23 
24 void
main(int argc,char * argv[])25 main(int argc, char *argv[])
26 {
27 	int justinterfaces = 0;
28 	int i, tot, fd;
29 	Dir *d;
30 	char buf[128];
31 
32 	ARGBEGIN{
33 	case 'i':
34 		justinterfaces = 1;
35 		break;
36 	case 'n':
37 		notrans = 1;
38 		break;
39 	case 'p':
40 		if(nproto >= nelem(proto))
41 			sysfatal("too many protos");
42 		proto[nproto++] = EARGF(usage());
43 		break;
44 	default:
45 		usage();
46 	}ARGEND;
47 
48 	netroot = "/net";
49 	switch(argc){
50 	case 0:
51 		break;
52 	case 1:
53 		netroot = argv[0];
54 		break;
55 	default:
56 		usage();
57 	}
58 
59 	Binit(&out, 1, OWRITE);
60 
61 	if(justinterfaces){
62 		pipifc();
63 		exits(0);
64 	}
65 
66 	if(nproto){
67 		for(i=0; i<nproto; i++)
68 			nstat(proto[i], pip);
69 	}else{
70 		fd = open(netroot, OREAD);
71 		if(fd < 0)
72 			sysfatal("open %s: %r", netroot);
73 
74 		tot = dirreadall(fd, &d);
75 		for(i=0; i<tot; i++){
76 			if(strcmp(d[i].name, "ipifc") == 0)
77 				continue;
78 			snprint(buf, sizeof buf, "%s/%s/0/local", netroot, d[i].name);
79 			if(access(buf, 0) >= 0)
80 				nstat(d[i].name, pip);
81 		}
82 	}
83 	exits(0);
84 }
85 
86 void
nstat(char * net,void (* f)(char *,Dir *))87 nstat(char *net, void (*f)(char*, Dir*))
88 {
89 	int fdir, i, tot;
90 	Dir *dir;
91 	char buf[128];
92 
93 	snprint(buf, sizeof buf, "%s/%s", netroot, net);
94 	fdir = open(buf, OREAD);
95 	if(fdir < 0)
96 		return;
97 
98 	tot = dirreadall(fdir, &dir);
99 	for(i = 0; i < tot; i++) {
100 		(*f)(net, &dir[i]);
101 		Bflush(&out);
102 	}
103 	free(dir);
104 	close(fdir);
105 }
106 
107 char*
getport(char * net,char * p)108 getport(char *net, char *p)
109 {
110 	static char port[10];
111 
112 	strncpy(port, p, sizeof(port)-1);
113 	port[sizeof(port)-1] = 0;
114 	if(notrans || (p = csgetvalue(netroot, "port", p, net, nil)) == nil)
115 		return port;
116 	strncpy(port, p, sizeof(port)-1);
117 	port[sizeof(port)-1] = 0;
118 	free(p);
119 	return port;
120 }
121 
122 void
pip(char * net,Dir * db)123 pip(char *net, Dir *db)
124 {
125 	int n, fd;
126 	char buf[128], *p;
127 	char *dname;
128 
129 	if(strcmp(db->name, "clone") == 0)
130 		return;
131 	if(strcmp(db->name, "stats") == 0)
132 		return;
133 
134 	snprint(buf, sizeof buf, "%s/%s/%s/status", netroot, net, db->name);
135 	fd = open(buf, OREAD);
136 	if(fd < 0)
137 		return;
138 	n = read(fd, buf, sizeof(buf));
139 	close(fd);
140 	if(n < 0)
141 		return;
142 	buf[n] = 0;
143 
144 	p = strchr(buf, ' ');
145 	if(p != 0)
146 		*p = 0;
147 	p = strrchr(buf, '\n');
148 	if(p != 0)
149 		*p = 0;
150 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, db->name, db->uid, buf);
151 
152 	snprint(buf, sizeof buf, "%s/%s/%s/local", netroot, net, db->name);
153 	fd = open(buf, OREAD);
154 	if(fd < 0) {
155 		Bprint(&out, "\n");
156 		return;
157 	}
158 	n = read(fd, buf, sizeof(buf));
159 	close(fd);
160 	if(n < 0) {
161 		Bprint(&out, "\n");
162 		return;
163 	}
164 	buf[n-1] = 0;
165 	p = strchr(buf, '!');
166 	if(p == 0) {
167 		Bprint(&out, "\n");
168 		return;
169 	}
170 	*p = '\0';
171 	Bprint(&out, "%-10s ", getport(net, p+1));
172 
173 	snprint(buf, sizeof buf, "%s/%s/%s/remote", netroot, net, db->name);
174 	fd = open(buf, OREAD);
175 	if(fd < 0) {
176 		print("\n");
177 		return;
178 	}
179 	n = read(fd, buf, sizeof(buf));
180 	close(fd);
181 	if(n < 0) {
182 		print("\n");
183 		return;
184 	}
185 	buf[n-1] = 0;
186 	p = strchr(buf, '!');
187 	if(p != nil)
188 		*p++ = '\0';
189 
190 	if(notrans){
191 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
192 		return;
193 	}
194 	dname = csgetvalue(netroot, "ip", buf, "dom", nil);
195 	if(dname == nil) {
196 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
197 		return;
198 	}
199 	Bprint(&out, "%-10s %s\n", getport(net, p), dname);
200 	Bflush(&out);
201 	free(dname);
202 }
203 
204 void
pipifc(void)205 pipifc(void)
206 {
207 	Ipifc *ip, *nip;
208 	Iplifc *lifc;
209 	char buf[100];
210 	int l, i;
211 
212 	fmtinstall('I', eipfmt);
213 	fmtinstall('M', eipfmt);
214 
215 	ip = readipifc(netroot, nil, -1);
216 
217 	l = 7;
218 	for(nip = ip; nip; nip = nip->next){
219 		for(lifc = nip->lifc; lifc; lifc = lifc->next){
220 			i = snprint(buf, sizeof buf, "%I", lifc->ip);
221 			if(i > l)
222 				l = i;
223 			i = snprint(buf, sizeof buf, "%I", lifc->net);
224 			if(i > l)
225 				l = i;
226 		}
227 	}
228 
229 	for(nip = ip; nip; nip = nip->next){
230 		for(lifc = nip->lifc; lifc; lifc = lifc->next)
231 			Bprint(&out, "%-12s %5d %-*I %5M %-*I %8lud %8lud %8lud %8lud\n",
232 				nip->dev, nip->mtu,
233 				l, lifc->ip, lifc->mask, l, lifc->net,
234 				nip->pktin, nip->pktout,
235 				nip->errin, nip->errout);
236 	}
237 	Bflush(&out);
238 }
239