xref: /plan9/sys/src/cmd/netstat.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
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 buf[Ndbvlen];
99 	Ndbtuple *t;
100 
101 	if(notrans)
102 		return p;
103 	t = csgetval(netroot, "port", p, net, buf);
104 	if(t)
105 		ndbfree(t);
106 	if(buf[0] == 0)
107 		return p;
108 	return buf;
109 }
110 
111 void
112 pip(char *net, Dir *db)
113 {
114 	int n, fd;
115 	char buf[128], *p;
116 	Ndbtuple *tp;
117 	char dname[Ndbvlen];
118 
119 	if(strcmp(db->name, "clone") == 0)
120 		return;
121 	if(strcmp(db->name, "stats") == 0)
122 		return;
123 
124 	snprint(buf, sizeof buf, "%s/%s/%s/ctl", netroot, net, db->name);
125 
126 	sprint(buf, "%s/%s/%s/status", netroot, net, db->name);
127 	fd = open(buf, OREAD);
128 	if(fd < 0)
129 		return;
130 
131 	n = read(fd, buf, sizeof(buf));
132 	if(n < 0)
133 		return;
134 	buf[n] = 0;
135 	close(fd);
136 
137 	p = strchr(buf, ' ');
138 	if(p != 0)
139 		*p = 0;
140 
141 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, db->name, db->uid, buf);
142 
143 	sprint(buf, "%s/%s/%s/local", netroot, net, db->name);
144 	fd = open(buf, OREAD);
145 	if(fd < 0) {
146 		Bprint(&out, "\n");
147 		return;
148 	}
149 	n = read(fd, buf, sizeof(buf));
150 	if(n < 0) {
151 		Bprint(&out, "\n");
152 		return;
153 	}
154 	buf[n-1] = 0;
155 	close(fd);
156 	p = strchr(buf, '!');
157 	if(p == 0) {
158 		Bprint(&out, "\n");
159 		return;
160 	}
161 	*p = '\0';
162 	Bprint(&out, "%-10s ", getport(net, p+1));
163 
164 	sprint(buf, "%s/%s/%s/remote", netroot, net, db->name);
165 	fd = open(buf, OREAD);
166 	if(fd < 0) {
167 		print("\n");
168 		return;
169 	}
170 	n = read(fd, buf, sizeof(buf));
171 	if(n < 0) {
172 		print("\n");
173 		return;
174 	}
175 	buf[n-1] = 0;
176 	close(fd);
177 	p = strchr(buf, '!');
178 	*p++ = '\0';
179 
180 	if(notrans){
181 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
182 		return;
183 	}
184 	tp = csgetval(netroot, "ip", buf, "dom", dname);
185 	if(tp)
186 		ndbfree(tp);
187 	if(dname[0] == 0) {
188 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
189 		return;
190 	}
191 	Bprint(&out, "%-10s %s\n", getport(net, p), dname);
192 	Bflush(&out);
193 }
194 
195 void
196 pipifc(void)
197 {
198 	Ipifc *ip, *nip;
199 	Iplifc *lifc;
200 	char buf[100];
201 	int l, i;
202 
203 	fmtinstall('I', eipfmt);
204 	fmtinstall('M', eipfmt);
205 
206 	ip = readipifc(netroot, nil, -1);
207 
208 	l = 7;
209 	for(nip = ip; nip; nip = nip->next){
210 		for(lifc = nip->lifc; lifc; lifc = lifc->next){
211 			i = snprint(buf, sizeof buf, "%I", lifc->ip);
212 			if(i > l)
213 				l = i;
214 			i = snprint(buf, sizeof buf, "%I", lifc->net);
215 			if(i > l)
216 				l = i;
217 		}
218 	}
219 
220 	for(nip = ip; nip; nip = nip->next){
221 		for(lifc = nip->lifc; lifc; lifc = lifc->next)
222 			Bprint(&out, "%-12s %5d %-*I %5M %-*I %8lud %8lud %8lud %8lud\n",
223 				nip->dev, nip->mtu,
224 				l, lifc->ip, lifc->mask, l, lifc->net,
225 				nip->pktin, nip->pktout,
226 				nip->errin, nip->errout);
227 	}
228 	Bflush(&out);
229 }
230