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