xref: /plan9-contrib/sys/src/cmd/netstat.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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	pipifc(char*, char*);
9 void	nstat(char*, void (*)(char*, char*));
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 		nstat("ipifc", 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*, char*))
65 {
66 	int fdir, i, n, tot;
67 	char dir[500*DIRLEN], *mem;
68 
69 	sprint(dir, "%s/%s", netroot, net);
70 	fdir = open(dir, OREAD);
71 	if(fdir < 0)
72 		return;
73 
74 	mem = sbrk(0);
75 	tot = 0;
76 	while((n = read(fdir, dir, sizeof dir)) > 0){
77 		if(brk((void*)(mem + tot + n)) == -1) {
78 			fprint(2, "netstat: out of memory");
79 			return;
80 		}
81 		memmove(mem+tot, dir, n);
82 		tot += n;
83 	}
84 	for(i = 0; i < tot; i += DIRLEN) {
85 		(*f)(net, mem+i);
86 		Bflush(&out);
87 	}
88 	close(fdir);
89 }
90 
91 char*
92 getport(char *net, char *p)
93 {
94 	static char buf[Ndbvlen];
95 	Ndbtuple *t;
96 
97 	if(notrans)
98 		return p;
99 	t = csgetval(netroot, "port", p, net, buf);
100 	if(t)
101 		ndbfree(t);
102 	if(buf[0] == 0)
103 		return p;
104 	return buf;
105 }
106 
107 void
108 pip(char *net, char *entry)
109 {
110 	Dir db;
111 	int n, fd;
112 	char buf[128], *p;
113 	Ndbtuple *tp;
114 	char dname[Ndbvlen];
115 
116 	if(strcmp(entry, "clone") == 0)
117 		return;
118 	if(strcmp(entry, "stats") == 0)
119 		return;
120 
121 	sprint(buf, "%s/%s/%s/ctl", netroot, net, entry);
122 	if(dirstat(buf, &db) < 0)
123 		return;
124 
125 	sprint(buf, "%s/%s/%s/status", netroot, net, entry);
126 	fd = open(buf, OREAD);
127 	if(fd < 0)
128 		return;
129 
130 	n = read(fd, buf, sizeof(buf));
131 	if(n < 0)
132 		return;
133 	buf[n] = 0;
134 	close(fd);
135 
136 	p = strchr(buf, ' ');
137 	if(p != 0)
138 		*p = 0;
139 
140 	Bprint(&out, "%-4s %-4s %-10s %-12s ", net, entry, db.uid, buf);
141 
142 	sprint(buf, "%s/%s/%s/local", netroot, net, entry);
143 	fd = open(buf, OREAD);
144 	if(fd < 0) {
145 		Bprint(&out, "\n");
146 		return;
147 	}
148 	n = read(fd, buf, sizeof(buf));
149 	if(n < 0) {
150 		Bprint(&out, "\n");
151 		return;
152 	}
153 	buf[n-1] = 0;
154 	close(fd);
155 	p = strchr(buf, '!');
156 	if(p == 0) {
157 		Bprint(&out, "\n");
158 		return;
159 	}
160 	*p = '\0';
161 	Bprint(&out, "%-10s ", getport(net, p+1));
162 
163 	sprint(buf, "%s/%s/%s/remote", netroot, net, entry);
164 	fd = open(buf, OREAD);
165 	if(fd < 0) {
166 		print("\n");
167 		return;
168 	}
169 	n = read(fd, buf, sizeof(buf));
170 	if(n < 0) {
171 		print("\n");
172 		return;
173 	}
174 	buf[n-1] = 0;
175 	close(fd);
176 	p = strchr(buf, '!');
177 	*p++ = '\0';
178 
179 	if(notrans){
180 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
181 		return;
182 	}
183 	tp = csgetval(netroot, "ip", buf, "dom", dname);
184 	if(tp)
185 		ndbfree(tp);
186 	if(dname[0] == 0) {
187 		Bprint(&out, "%-10s %s\n", getport(net, p), buf);
188 		return;
189 	}
190 	Bprint(&out, "%-10s %s\n", getport(net, p), dname);
191 	Bflush(&out);
192 }
193 
194 void
195 pipifc(char *net, char *entry)
196 {
197 	int n, fd;
198 	char buf[128], *p;
199 	char *f[9];
200 
201 	if(strcmp(entry, "clone") == 0)
202 		return;
203 	if(strcmp(entry, "stats") == 0)
204 		return;
205 
206 	sprint(buf, "%s/%s/%s/status", netroot, net, entry);
207 	fd = open(buf, OREAD);
208 	if(fd < 0)
209 		return;
210 
211 	n = read(fd, buf, sizeof(buf));
212 	if(n < 0)
213 		return;
214 	buf[n] = 0;
215 	close(fd);
216 
217 	n = getfields(buf, f, 9, 1, " \t\n");
218 	if(n < 7)
219 		return;
220 	p = strrchr(f[0], '/');
221 	if(p != nil)
222 		f[0] = p+1;
223 
224 	if(n == 9)
225 		Bprint(&out, "%-8s %-5s %-16s %-16s %-16s %-10s %-10s %-6s %-6s\n",
226 			f[0], f[1], f[2], f[3], f[4],
227 			f[5], f[6], f[7], f[8]);
228 	else
229 		Bprint(&out, "               %-16s %-16s %-16s %-10s %-10s %-6s %-6s\n",
230 			f[0], f[1], f[2], f[3], f[4],
231 			f[5], f[6]);
232 }
233