Commit | Line | Data |
---|---|---|
5ff67f98 DF |
1 | /* |
2 | * Copyright (c) 1983 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
7 | #ifndef lint | |
8 | char copyright[] = | |
9 | "@(#) Copyright (c) 1983 Regents of the University of California.\n\ | |
10 | All rights reserved.\n"; | |
11 | #endif not lint | |
12 | ||
ed85a06f | 13 | #ifndef lint |
38d9ef3b | 14 | static char sccsid[] = "@(#)main.c 5.8 (Berkeley) %G%"; |
5ff67f98 | 15 | #endif not lint |
ed85a06f SL |
16 | |
17 | #include <sys/param.h> | |
d96df0d1 | 18 | #include <sys/vmmac.h> |
0be88646 | 19 | #include <sys/socket.h> |
7cd60ad6 | 20 | #include <machine/pte.h> |
ed85a06f SL |
21 | #include <ctype.h> |
22 | #include <errno.h> | |
23 | #include <netdb.h> | |
24 | #include <nlist.h> | |
25 | #include <stdio.h> | |
26 | ||
27 | struct nlist nl[] = { | |
28 | #define N_MBSTAT 0 | |
29 | { "_mbstat" }, | |
30 | #define N_IPSTAT 1 | |
31 | { "_ipstat" }, | |
32 | #define N_TCB 2 | |
33 | { "_tcb" }, | |
34 | #define N_TCPSTAT 3 | |
35 | { "_tcpstat" }, | |
36 | #define N_UDB 4 | |
37 | { "_udb" }, | |
38 | #define N_UDPSTAT 5 | |
39 | { "_udpstat" }, | |
40 | #define N_RAWCB 6 | |
41 | { "_rawcb" }, | |
42 | #define N_SYSMAP 7 | |
43 | { "_Sysmap" }, | |
44 | #define N_SYSSIZE 8 | |
45 | { "_Syssize" }, | |
46 | #define N_IFNET 9 | |
47 | { "_ifnet" }, | |
48 | #define N_HOSTS 10 | |
49 | { "_hosts" }, | |
50 | #define N_RTHOST 11 | |
51 | { "_rthost" }, | |
52 | #define N_RTNET 12 | |
53 | { "_rtnet" }, | |
7333c75b SL |
54 | #define N_ICMPSTAT 13 |
55 | { "_icmpstat" }, | |
bbd2d21e SL |
56 | #define N_RTSTAT 14 |
57 | { "_rtstat" }, | |
404a567d SL |
58 | #define N_NFILE 15 |
59 | { "_nfile" }, | |
60 | #define N_FILE 16 | |
61 | { "_file" }, | |
62 | #define N_UNIXSW 17 | |
63 | { "_unixsw" }, | |
f508555e MK |
64 | #define N_RTHASHSIZE 18 |
65 | { "_rthashsize" }, | |
0be88646 KS |
66 | #define N_IDP 19 |
67 | { "_nspcb"}, | |
68 | #define N_IDPSTAT 20 | |
69 | { "_idpstat"}, | |
70 | #define N_SPPSTAT 21 | |
71 | { "_spp_istat"}, | |
72 | #define N_NSERR 22 | |
73 | { "_ns_errstat"}, | |
a5545777 MK |
74 | |
75 | /* BBN Internet protocol implementation */ | |
76 | #define N_TCP 23 | |
77 | { "_tcp" }, | |
78 | #define N_UDP 24 | |
79 | { "_udp" }, | |
80 | #define N_RDP 25 | |
81 | { "_rdp" }, | |
82 | #define N_RDPSTAT 26 | |
83 | { "_rdpstat" }, | |
84 | ||
7333c75b | 85 | "", |
ed85a06f SL |
86 | }; |
87 | ||
404a567d | 88 | /* internet protocols */ |
a5545777 | 89 | extern int protopr(), bbnprotopr(); |
7333c75b | 90 | extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats(); |
a5545777 | 91 | extern int tcpstats(), udpstats(), ipstats(), icmpstats(), rdpstats(); |
0be88646 KS |
92 | extern int nsprotopr(); |
93 | extern int spp_stats(), idp_stats(), nserr_stats(); | |
6df0a927 | 94 | |
ed85a06f | 95 | struct protox { |
6df0a927 SL |
96 | u_char pr_index; /* index into nlist of cb head */ |
97 | u_char pr_sindex; /* index into nlist of stat block */ | |
98 | u_char pr_wanted; /* 1 if wanted, 0 otherwise */ | |
99 | int (*pr_cblocks)(); /* control blocks printing routine */ | |
100 | int (*pr_stats)(); /* statistics printing routine */ | |
101 | char *pr_name; /* well-known name */ | |
a5545777 MK |
102 | }; |
103 | ||
104 | struct protox berkprotox[] = { | |
6df0a927 SL |
105 | { N_TCB, N_TCPSTAT, 1, protopr, |
106 | tcp_stats, "tcp" }, | |
107 | { N_UDB, N_UDPSTAT, 1, protopr, | |
108 | udp_stats, "udp" }, | |
109 | { -1, N_IPSTAT, 1, 0, | |
110 | ip_stats, "ip" }, | |
7333c75b SL |
111 | { -1, N_ICMPSTAT, 1, 0, |
112 | icmp_stats, "icmp" }, | |
6df0a927 SL |
113 | { -1, -1, 0, 0, |
114 | 0, 0 } | |
ed85a06f SL |
115 | }; |
116 | ||
a5545777 MK |
117 | struct protox bbnprotox[] = { |
118 | { N_TCP, N_TCPSTAT, 1, bbnprotopr, | |
119 | tcpstats, "tcp" }, | |
120 | { N_UDP, N_UDPSTAT, 1, bbnprotopr, | |
121 | udpstats, "udp" }, | |
122 | { N_RDP, N_RDPSTAT, 1, bbnprotopr, | |
123 | rdpstats, "rdp" }, | |
124 | { N_RAWCB, 0, 1, bbnprotopr, | |
125 | 0, "raw" }, | |
126 | { -1, N_IPSTAT, 1, 0, | |
127 | ipstats, "ip" }, | |
128 | { -1, N_ICMPSTAT, 1, 0, | |
129 | icmpstats, "icmp" }, | |
130 | { -1, -1, 0, 0, | |
131 | 0, 0 } | |
132 | }; | |
133 | ||
0be88646 KS |
134 | struct protox nsprotox[] = { |
135 | { N_IDP, N_IDPSTAT, 1, nsprotopr, | |
136 | idp_stats, "idp" }, | |
137 | { N_IDP, N_SPPSTAT, 1, nsprotopr, | |
138 | spp_stats, "spp" }, | |
139 | { -1, N_NSERR, 1, 0, | |
140 | nserr_stats, "ns_err" }, | |
141 | { -1, -1, 0, 0, | |
142 | 0, 0 } | |
143 | }; | |
144 | ||
ed85a06f SL |
145 | struct pte *Sysmap; |
146 | ||
147 | char *system = "/vmunix"; | |
148 | char *kmemf = "/dev/kmem"; | |
149 | int kmem; | |
150 | int kflag; | |
151 | int Aflag; | |
152 | int aflag; | |
153 | int hflag; | |
154 | int iflag; | |
155 | int mflag; | |
156 | int nflag; | |
157 | int rflag; | |
158 | int sflag; | |
159 | int tflag; | |
0be88646 | 160 | int fflag; |
ed85a06f | 161 | int interval; |
79ddba48 EW |
162 | char *interface; |
163 | int unit; | |
2a893f10 | 164 | char usage[] = "[ -Aaihmnrst ] [-f address_family] [-I interface] [ interval ] [ system ] [ core ]"; |
ed85a06f | 165 | |
0be88646 | 166 | int af = AF_UNSPEC; |
2a893f10 | 167 | |
ed85a06f SL |
168 | main(argc, argv) |
169 | int argc; | |
170 | char *argv[]; | |
171 | { | |
172 | int i; | |
173 | char *cp, *name; | |
174 | register struct protoent *p; | |
0be88646 | 175 | register struct protox *tp; |
ed85a06f SL |
176 | |
177 | name = argv[0]; | |
178 | argc--, argv++; | |
179 | while (argc > 0 && **argv == '-') { | |
180 | for (cp = &argv[0][1]; *cp; cp++) | |
18f196b0 | 181 | switch(*cp) { |
ed85a06f SL |
182 | |
183 | case 'A': | |
184 | Aflag++; | |
185 | break; | |
186 | ||
187 | case 'a': | |
188 | aflag++; | |
189 | break; | |
190 | ||
191 | case 'h': | |
192 | hflag++; | |
193 | break; | |
194 | ||
195 | case 'i': | |
196 | iflag++; | |
197 | break; | |
198 | ||
199 | case 'm': | |
200 | mflag++; | |
201 | break; | |
202 | ||
203 | case 'n': | |
204 | nflag++; | |
205 | break; | |
206 | ||
207 | case 'r': | |
208 | rflag++; | |
209 | break; | |
210 | ||
211 | case 's': | |
212 | sflag++; | |
213 | break; | |
214 | ||
215 | case 't': | |
216 | tflag++; | |
217 | break; | |
218 | ||
404a567d | 219 | case 'u': |
2a893f10 | 220 | af = AF_UNIX; |
404a567d SL |
221 | break; |
222 | ||
0be88646 KS |
223 | case 'f': |
224 | argv++; | |
225 | argc--; | |
2a893f10 | 226 | if (strcmp(*argv, "ns") == 0) |
0be88646 | 227 | af = AF_NS; |
2a893f10 | 228 | else if (strcmp(*argv, "inet") == 0) |
0be88646 | 229 | af = AF_INET; |
2a893f10 MK |
230 | else if (strcmp(*argv, "unix") == 0) |
231 | af = AF_UNIX; | |
232 | else { | |
233 | fprintf(stderr, "%s: unknown address family\n", | |
234 | *argv); | |
235 | exit(10); | |
0be88646 KS |
236 | } |
237 | break; | |
238 | ||
79ddba48 EW |
239 | case 'I': |
240 | iflag++; | |
241 | if (*(interface = cp + 1) == 0) { | |
242 | if ((interface = argv[1]) == 0) | |
243 | break; | |
244 | argv++; | |
245 | argc--; | |
246 | } | |
247 | for (cp = interface; isalpha(*cp); cp++) | |
248 | ; | |
249 | unit = atoi(cp); | |
250 | *cp-- = 0; | |
251 | break; | |
252 | ||
ed85a06f SL |
253 | default: |
254 | use: | |
255 | printf("usage: %s %s\n", name, usage); | |
256 | exit(1); | |
257 | } | |
258 | argv++, argc--; | |
259 | } | |
260 | if (argc > 0 && isdigit(argv[0][0])) { | |
261 | interval = atoi(argv[0]); | |
262 | if (interval <= 0) | |
263 | goto use; | |
264 | argv++, argc--; | |
90cb8200 | 265 | iflag++; |
ed85a06f SL |
266 | } |
267 | if (argc > 0) { | |
268 | system = *argv; | |
269 | argv++, argc--; | |
270 | } | |
271 | nlist(system, nl); | |
272 | if (nl[0].n_type == 0) { | |
273 | fprintf(stderr, "%s: no namelist\n", system); | |
274 | exit(1); | |
275 | } | |
276 | if (argc > 0) { | |
277 | kmemf = *argv; | |
278 | kflag++; | |
279 | } | |
280 | kmem = open(kmemf, 0); | |
281 | if (kmem < 0) { | |
282 | fprintf(stderr, "cannot open "); | |
283 | perror(kmemf); | |
284 | exit(1); | |
285 | } | |
286 | if (kflag) { | |
287 | off_t off; | |
288 | ||
289 | off = nl[N_SYSMAP].n_value & 0x7fffffff; | |
290 | lseek(kmem, off, 0); | |
291 | nl[N_SYSSIZE].n_value *= 4; | |
292 | Sysmap = (struct pte *)malloc(nl[N_SYSSIZE].n_value); | |
293 | if (Sysmap == 0) { | |
294 | perror("Sysmap"); | |
295 | exit(1); | |
296 | } | |
297 | read(kmem, Sysmap, nl[N_SYSSIZE].n_value); | |
298 | } | |
299 | if (mflag) { | |
300 | mbpr(nl[N_MBSTAT].n_value); | |
301 | exit(0); | |
302 | } | |
ed85a06f SL |
303 | /* |
304 | * Keep file descriptors open to avoid overhead | |
305 | * of open/close on each call to get* routines. | |
306 | */ | |
ed85a06f SL |
307 | sethostent(1); |
308 | setnetent(1); | |
90cb8200 SL |
309 | if (iflag) { |
310 | intpr(interval, nl[N_IFNET].n_value); | |
311 | exit(0); | |
312 | } | |
ed85a06f SL |
313 | if (hflag) { |
314 | hostpr(nl[N_HOSTS].n_value); | |
315 | exit(0); | |
316 | } | |
317 | if (rflag) { | |
bbd2d21e SL |
318 | if (sflag) |
319 | rt_stats(nl[N_RTSTAT].n_value); | |
320 | else | |
f508555e MK |
321 | routepr(nl[N_RTHOST].n_value, nl[N_RTNET].n_value, |
322 | nl[N_RTHASHSIZE].n_value); | |
ed85a06f SL |
323 | exit(0); |
324 | } | |
0be88646 | 325 | if (af == AF_INET || af == AF_UNSPEC) { |
a5545777 MK |
326 | struct protox *head; |
327 | ||
328 | head = (nl[N_TCB].n_type == 0) ? bbnprotox : berkprotox; | |
90cb8200 SL |
329 | setprotoent(1); |
330 | setservent(1); | |
ed85a06f | 331 | |
a5545777 MK |
332 | for (tp = head; tp->pr_name; tp++) { |
333 | if (tp->pr_wanted == 0) | |
ed85a06f | 334 | continue; |
a5545777 MK |
335 | |
336 | if (sflag) { | |
337 | if (tp->pr_stats) | |
338 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, tp->pr_name); | |
339 | } else if (tp->pr_cblocks) | |
340 | (*tp->pr_cblocks)(nl[tp->pr_index].n_value, tp->pr_name); | |
ed85a06f SL |
341 | } |
342 | endprotoent(); | |
0be88646 KS |
343 | } |
344 | if (af == AF_NS || af == AF_UNSPEC) { | |
345 | for (tp = nsprotox; tp->pr_name; tp++) { | |
54c165a5 MK |
346 | if (sflag) { |
347 | if (tp->pr_stats) | |
348 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, | |
349 | tp->pr_name); | |
350 | } else | |
351 | if (tp->pr_cblocks) | |
352 | (*tp->pr_cblocks)(nl[tp->pr_index].n_value, | |
353 | tp->pr_name); | |
0be88646 KS |
354 | } |
355 | } | |
54c165a5 | 356 | if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) |
2a893f10 MK |
357 | unixpr(nl[N_NFILE].n_value, nl[N_FILE].n_value, |
358 | nl[N_UNIXSW].n_value); | |
085b521c | 359 | exit(0); |
ed85a06f SL |
360 | } |
361 | ||
362 | /* | |
363 | * Seek into the kernel for a value. | |
364 | */ | |
365 | klseek(fd, base, off) | |
366 | int fd, base, off; | |
367 | { | |
368 | ||
369 | if (kflag) { | |
370 | /* get kernel pte */ | |
4659bf8e | 371 | #ifdef vax |
ed85a06f | 372 | base &= 0x7fffffff; |
4659bf8e | 373 | #endif |
d96df0d1 | 374 | base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); |
ed85a06f SL |
375 | } |
376 | lseek(fd, base, off); | |
377 | } | |
bbd2d21e SL |
378 | |
379 | char * | |
380 | plural(n) | |
381 | int n; | |
382 | { | |
383 | ||
384 | return (n != 1 ? "s" : ""); | |
385 | } |