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