xref: /plan9-contrib/sys/src/cmd/netstat.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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*, char*);
8 void	pdk(char*, char*);
9 void	nstat(char*, void (*)(char*, char*));
10 
11 Ndb 	*ndb;
12 Biobuf	out;
13 
14 void
15 main(void)
16 {
17 	ndb = ndbopen(0);
18 
19 	Binit(&out, 1, OWRITE);
20 
21 	nstat("tcp", pip);
22 	nstat("udp", pip);
23 	nstat("il", pip);
24 	nstat("dk", pdk);
25 	exits(0);
26 }
27 
28 void
29 nstat(char *net, void (*f)(char*, char*))
30 {
31 	int fdir, i, n, tot;
32 	char dir[500*DIRLEN], *mem;
33 
34 	sprint(dir, "/net/%s", net);
35 	fdir = open(dir, OREAD);
36 	if(fdir < 0)
37 		return;
38 
39 	mem = sbrk(0);
40 	tot = 0;
41 	while((n = read(fdir, dir, sizeof dir)) > 0){
42 		if(brk((void*)(mem + tot + n)) == -1) {
43 			fprint(2, "netstat: out of memory");
44 			return;
45 		}
46 		memmove(mem+tot, dir, n);
47 		tot += n;
48 	}
49 	for(i = 0; i < tot; i += DIRLEN) {
50 		(*f)(net, mem+i);
51 		Bflush(&out);
52 	}
53 	close(fdir);
54 }
55 
56 void
57 pdk(char *net, char *entry)
58 {
59 	Dir db;
60 	int n, fd;
61 	char buf[128], *p, *t;
62 
63 	if(strcmp(entry, "clone") == 0)
64 		return;
65 
66 	sprint(buf, "/net/%s/%s/ctl", net, entry);
67 	if(dirstat(buf, &db) < 0)
68 		return;
69 
70 	sprint(buf, "/net/%s/%s/status", net, entry);
71 	fd = open(buf, OREAD);
72 	if(fd < 0)
73 		return;
74 	n = read(fd, buf, sizeof(buf));
75 	if(n < 0)
76 		return;
77 	buf[n] = 0;
78 	close(fd);
79 
80 	p = strchr(buf, ' ');
81 	if(p == 0)
82 		return;
83 	p = strchr(p+1, ' ');
84 	if(p == 0)
85 		return;
86 	t = strchr(p+1, ' ');
87 	if(t == 0)
88 		return;
89 	*t = 0;
90 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, entry, db.uid, p);
91 
92 	sprint(buf, "/net/%s/%s/local", net, entry);
93 	fd = open(buf, OREAD);
94 	if(fd < 0) {
95 		Bprint(&out, "\n");
96 		return;
97 	}
98 	n = read(fd, buf, sizeof(buf));
99 	if(n < 0) {
100 		Bprint(&out, "\n");
101 		return;
102 	}
103 	buf[n-1] = 0;
104 	p = strchr(buf, '!');
105 	if(p == 0) {
106 		Bprint(&out, "\n");
107 		return;
108 	}
109 	Bprint(&out, "%-10s ", p+1);
110 
111 	sprint(buf, "/net/%s/%s/remote", net, entry);
112 	fd = open(buf, OREAD);
113 	if(fd < 0) {
114 		Bprint(&out, "\n", buf);
115 		return;
116 	}
117 	n = read(fd, buf, sizeof(buf));
118 	if(n < 0) {
119 		Bprint(&out, "\n");
120 		return;
121 	}
122 	buf[n-1] = 0;
123 	Bprint(&out, "%s\n", buf);
124 }
125 
126 char*
127 getport(char *net, char *p)
128 {
129 	Ndbs s;
130 	static Ndbtuple *t;
131 	static Ndbtuple *nt;
132 
133 	t = ndbsearch(ndb, &s, "port", p);
134 	while(t){
135 		for(nt = t; nt; nt = nt->entry) {
136 			if(strcmp(nt->attr, net) == 0)
137 				return nt->val;
138 		}
139 		ndbfree(t);
140 		t = ndbsnext(&s, "port", p);
141 	}
142 	return p;
143 }
144 
145 void
146 pip(char *net, char *entry)
147 {
148 	Dir db;
149 	Ipinfo ipi;
150 	int n, fd;
151 	char buf[128], *p, *t;
152 
153 	if(strcmp(entry, "clone") == 0)
154 		return;
155 
156 	sprint(buf, "/net/%s/%s/ctl", net, entry);
157 	if(dirstat(buf, &db) < 0)
158 		return;
159 
160 	sprint(buf, "/net/%s/%s/status", net, entry);
161 	fd = open(buf, OREAD);
162 	if(fd < 0)
163 		return;
164 	n = read(fd, buf, sizeof(buf));
165 	if(n < 0)
166 		return;
167 	buf[n] = 0;
168 	close(fd);
169 
170 	p = " Dgram";
171 	if(strcmp(net, "udp") != 0) {
172 		p = strchr(buf, ' ');
173 		if(p == 0)
174 			return;
175 		p = strchr(p+1, ' ');
176 		if(p == 0)
177 			return;
178 		t = strchr(p+1, ' ');
179 		if(t == 0)
180 			return;
181 		*t = 0;
182 	}
183 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, entry, db.uid, p);
184 
185 	sprint(buf, "/net/%s/%s/local", net, entry);
186 	fd = open(buf, OREAD);
187 	if(fd < 0) {
188 		Bprint(&out, "\n");
189 		return;
190 	}
191 	n = read(fd, buf, sizeof(buf));
192 	if(n < 0) {
193 		Bprint(&out, "\n");
194 		return;
195 	}
196 	buf[n-1] = 0;
197 	close(fd);
198 	p = strchr(buf, '!');
199 	if(p == 0) {
200 		Bprint(&out, "\n");
201 		return;
202 	}
203 	*p = '\0';
204 	Bprint(&out, "%-10s ", getport(net, p+1));
205 
206 	sprint(buf, "/net/%s/%s/remote", net, entry);
207 	fd = open(buf, OREAD);
208 	if(fd < 0) {
209 		print("\n");
210 		return;
211 	}
212 	n = read(fd, buf, sizeof(buf));
213 	if(n < 0) {
214 		print("\n");
215 		return;
216 	}
217 	buf[n-1] = 0;
218 	close(fd);
219 	p = strchr(buf, '!');
220 	*p++ = '\0';
221 
222 	n = ipinfo(ndb, 0, buf, 0, &ipi);
223 	if(n < 0) {
224 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
225 		return;
226 	}
227 	Bprint(&out, "%-10s %s\n", getport(net, p), ipi.domain);
228 }
229