Commit | Line | Data |
---|---|---|
5ff67f98 | 1 | /* |
b36fc510 | 2 | * Copyright (c) 1983, 1988 Regents of the University of California. |
ee3f90a5 MK |
3 | * All rights reserved. |
4 | * | |
1c15e888 C |
5 | * Redistribution and use in source and binary forms are permitted provided |
6 | * that: (1) source distributions retain this entire copyright notice and | |
7 | * comment, and (2) distributions including binaries display the following | |
8 | * acknowledgement: ``This product includes software developed by the | |
9 | * University of California, Berkeley and its contributors'' in the | |
10 | * documentation or other materials provided with the distribution and in | |
11 | * all advertising materials mentioning features or use of this software. | |
12 | * Neither the name of the University nor the names of its contributors may | |
13 | * be used to endorse or promote products derived from this software without | |
14 | * specific prior written permission. | |
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED | |
16 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
5ff67f98 DF |
18 | */ |
19 | ||
20 | #ifndef lint | |
21 | char copyright[] = | |
b36fc510 | 22 | "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ |
5ff67f98 | 23 | All rights reserved.\n"; |
d2c7d54c | 24 | #endif /* not lint */ |
5ff67f98 | 25 | |
ed85a06f | 26 | #ifndef lint |
1c15e888 | 27 | static char sccsid[] = "@(#)main.c 5.19 (Berkeley) 6/18/90"; |
d2c7d54c | 28 | #endif /* not lint */ |
ed85a06f SL |
29 | |
30 | #include <sys/param.h> | |
d96df0d1 | 31 | #include <sys/vmmac.h> |
0be88646 | 32 | #include <sys/socket.h> |
d2c7d54c | 33 | #include <sys/file.h> |
7cd60ad6 | 34 | #include <machine/pte.h> |
ed85a06f SL |
35 | #include <ctype.h> |
36 | #include <errno.h> | |
37 | #include <netdb.h> | |
38 | #include <nlist.h> | |
39 | #include <stdio.h> | |
4390c68f | 40 | #include <paths.h> |
ed85a06f | 41 | |
c34ecf77 | 42 | #define nl netstatnl |
ed85a06f SL |
43 | struct nlist nl[] = { |
44 | #define N_MBSTAT 0 | |
45 | { "_mbstat" }, | |
46 | #define N_IPSTAT 1 | |
47 | { "_ipstat" }, | |
48 | #define N_TCB 2 | |
49 | { "_tcb" }, | |
50 | #define N_TCPSTAT 3 | |
51 | { "_tcpstat" }, | |
52 | #define N_UDB 4 | |
53 | { "_udb" }, | |
54 | #define N_UDPSTAT 5 | |
55 | { "_udpstat" }, | |
56 | #define N_RAWCB 6 | |
57 | { "_rawcb" }, | |
58 | #define N_SYSMAP 7 | |
59 | { "_Sysmap" }, | |
60 | #define N_SYSSIZE 8 | |
61 | { "_Syssize" }, | |
62 | #define N_IFNET 9 | |
63 | { "_ifnet" }, | |
0e710523 MK |
64 | #define N_IMP 10 |
65 | { "_imp_softc" }, | |
ed85a06f SL |
66 | #define N_RTHOST 11 |
67 | { "_rthost" }, | |
68 | #define N_RTNET 12 | |
69 | { "_rtnet" }, | |
7333c75b SL |
70 | #define N_ICMPSTAT 13 |
71 | { "_icmpstat" }, | |
bbd2d21e SL |
72 | #define N_RTSTAT 14 |
73 | { "_rtstat" }, | |
404a567d SL |
74 | #define N_NFILE 15 |
75 | { "_nfile" }, | |
76 | #define N_FILE 16 | |
77 | { "_file" }, | |
78 | #define N_UNIXSW 17 | |
79 | { "_unixsw" }, | |
f508555e MK |
80 | #define N_RTHASHSIZE 18 |
81 | { "_rthashsize" }, | |
0be88646 KS |
82 | #define N_IDP 19 |
83 | { "_nspcb"}, | |
84 | #define N_IDPSTAT 20 | |
85 | { "_idpstat"}, | |
86 | #define N_SPPSTAT 21 | |
87 | { "_spp_istat"}, | |
88 | #define N_NSERR 22 | |
89 | { "_ns_errstat"}, | |
5262655f KS |
90 | #define N_CLNPSTAT 23 |
91 | { "_clnp_stat"}, | |
92 | #define IN_TP 24 | |
93 | { "_tp_inpcb" }, | |
94 | #define ISO_TP 25 | |
95 | { "_tp_isopcb" }, | |
96 | #define ISO_X25 26 | |
0fa5c909 | 97 | { /*"_x25_isopcb"*/ "_file"}, /* fast gross hack to speed up */ |
5262655f KS |
98 | #define N_TPSTAT 27 |
99 | { "_tp_stat" }, | |
100 | #define N_X25STAT 28 | |
0fa5c909 | 101 | { /*"_x25_stat"*/ "_file"}, |
5262655f KS |
102 | #define N_ESISSTAT 29 |
103 | { "_esis_stat"}, | |
104 | #define N_NIMP 30 | |
0e710523 | 105 | { "_nimp"}, |
5262655f | 106 | #define N_RTREE 31 |
4390c68f | 107 | { "_radix_node_head"}, |
0fa5c909 KS |
108 | #define N_CLTP 32 |
109 | { "_cltb"}, | |
110 | #define N_CLTPSTAT 33 | |
111 | { "_cltpstat"}, | |
112 | ||
7333c75b | 113 | "", |
ed85a06f SL |
114 | }; |
115 | ||
404a567d | 116 | /* internet protocols */ |
6df0a927 | 117 | extern int protopr(); |
7333c75b | 118 | extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats(); |
6538ea31 | 119 | /* ns protocols */ |
0be88646 KS |
120 | extern int nsprotopr(); |
121 | extern int spp_stats(), idp_stats(), nserr_stats(); | |
5262655f KS |
122 | /* iso protocols */ |
123 | extern int iso_protopr(); | |
0fa5c909 | 124 | extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats(); |
6df0a927 | 125 | |
6538ea31 | 126 | #define NULLPROTOX ((struct protox *) 0) |
ed85a06f | 127 | struct protox { |
6df0a927 SL |
128 | u_char pr_index; /* index into nlist of cb head */ |
129 | u_char pr_sindex; /* index into nlist of stat block */ | |
130 | u_char pr_wanted; /* 1 if wanted, 0 otherwise */ | |
131 | int (*pr_cblocks)(); /* control blocks printing routine */ | |
132 | int (*pr_stats)(); /* statistics printing routine */ | |
133 | char *pr_name; /* well-known name */ | |
ed85a06f | 134 | } protox[] = { |
6df0a927 SL |
135 | { N_TCB, N_TCPSTAT, 1, protopr, |
136 | tcp_stats, "tcp" }, | |
137 | { N_UDB, N_UDPSTAT, 1, protopr, | |
138 | udp_stats, "udp" }, | |
5262655f KS |
139 | { IN_TP, N_TPSTAT, 1, protopr, |
140 | tp_stats, "tpip" }, | |
6df0a927 SL |
141 | { -1, N_IPSTAT, 1, 0, |
142 | ip_stats, "ip" }, | |
7333c75b SL |
143 | { -1, N_ICMPSTAT, 1, 0, |
144 | icmp_stats, "icmp" }, | |
6df0a927 SL |
145 | { -1, -1, 0, 0, |
146 | 0, 0 } | |
ed85a06f SL |
147 | }; |
148 | ||
0be88646 KS |
149 | struct protox nsprotox[] = { |
150 | { N_IDP, N_IDPSTAT, 1, nsprotopr, | |
151 | idp_stats, "idp" }, | |
152 | { N_IDP, N_SPPSTAT, 1, nsprotopr, | |
153 | spp_stats, "spp" }, | |
154 | { -1, N_NSERR, 1, 0, | |
155 | nserr_stats, "ns_err" }, | |
156 | { -1, -1, 0, 0, | |
157 | 0, 0 } | |
158 | }; | |
159 | ||
5262655f KS |
160 | struct protox isoprotox[] = { |
161 | { ISO_TP, N_TPSTAT, 1, iso_protopr, | |
162 | tp_stats, "tp" }, | |
0fa5c909 KS |
163 | { N_CLTP, N_CLTPSTAT, 1, iso_protopr, |
164 | cltp_stats, "cltp" }, | |
5262655f KS |
165 | #ifdef notdef |
166 | { ISO_X25, N_X25STAT, 1, x25_protopr, | |
167 | x25_stats, "x25" }, | |
168 | #endif | |
169 | { -1, N_CLNPSTAT, 1, 0, | |
170 | clnp_stats, "clnp"}, | |
171 | { -1, N_ESISSTAT, 1, 0, | |
172 | esis_stats, "esis"}, | |
173 | { -1, -1, 0, 0, | |
174 | 0, 0 } | |
175 | }; | |
176 | ||
177 | struct protox *protoprotox[] = { protox, nsprotox, isoprotox, NULLPROTOX }; | |
178 | ||
ed85a06f SL |
179 | struct pte *Sysmap; |
180 | ||
4390c68f | 181 | char *system = _PATH_UNIX; |
c34ecf77 | 182 | char *kmemf; |
ed85a06f SL |
183 | int kmem; |
184 | int kflag; | |
185 | int Aflag; | |
186 | int aflag; | |
187 | int hflag; | |
188 | int iflag; | |
189 | int mflag; | |
190 | int nflag; | |
6538ea31 | 191 | int pflag; |
ed85a06f SL |
192 | int rflag; |
193 | int sflag; | |
194 | int tflag; | |
2ebaad6c | 195 | int dflag; |
ed85a06f | 196 | int interval; |
79ddba48 EW |
197 | char *interface; |
198 | int unit; | |
ed85a06f | 199 | |
0be88646 | 200 | int af = AF_UNSPEC; |
2a893f10 | 201 | |
6538ea31 MK |
202 | extern char *malloc(); |
203 | extern off_t lseek(); | |
204 | ||
ed85a06f SL |
205 | main(argc, argv) |
206 | int argc; | |
207 | char *argv[]; | |
208 | { | |
d2c7d54c KB |
209 | extern char *optarg; |
210 | extern int optind; | |
ed85a06f | 211 | register struct protoent *p; |
6538ea31 MK |
212 | register struct protox *tp; /* for printing cblocks & stats */ |
213 | struct protox *name2protox(); /* for -p */ | |
d2c7d54c | 214 | int ch; |
ed85a06f | 215 | |
2ebaad6c | 216 | while ((ch = getopt(argc, argv, "AI:af:himnp:drstu")) != EOF) |
d2c7d54c | 217 | switch((char)ch) { |
ed85a06f SL |
218 | case 'A': |
219 | Aflag++; | |
220 | break; | |
d2c7d54c KB |
221 | case 'I': { |
222 | char *cp; | |
ed85a06f | 223 | |
d2c7d54c KB |
224 | iflag++; |
225 | for (cp = interface = optarg; isalpha(*cp); cp++); | |
226 | unit = atoi(cp); | |
227 | *cp = '\0'; | |
228 | break; | |
229 | } | |
ed85a06f SL |
230 | case 'a': |
231 | aflag++; | |
232 | break; | |
2ebaad6c MK |
233 | case 'd': |
234 | dflag++; | |
235 | break; | |
d2c7d54c KB |
236 | case 'f': |
237 | if (strcmp(optarg, "ns") == 0) | |
238 | af = AF_NS; | |
239 | else if (strcmp(optarg, "inet") == 0) | |
240 | af = AF_INET; | |
241 | else if (strcmp(optarg, "unix") == 0) | |
242 | af = AF_UNIX; | |
5262655f KS |
243 | else if (strcmp(optarg, "iso") == 0) |
244 | af = AF_ISO; | |
d2c7d54c KB |
245 | else { |
246 | fprintf(stderr, "%s: unknown address family\n", optarg); | |
247 | exit(10); | |
248 | } | |
249 | break; | |
ed85a06f SL |
250 | case 'h': |
251 | hflag++; | |
252 | break; | |
ed85a06f SL |
253 | case 'i': |
254 | iflag++; | |
255 | break; | |
ed85a06f SL |
256 | case 'm': |
257 | mflag++; | |
258 | break; | |
ed85a06f SL |
259 | case 'n': |
260 | nflag++; | |
261 | break; | |
d2c7d54c KB |
262 | case 'p': |
263 | if ((tp = name2protox(optarg)) == NULLPROTOX) { | |
264 | fprintf(stderr, "%s: unknown or uninstrumented protocol\n", optarg); | |
265 | exit(10); | |
266 | } | |
267 | pflag++; | |
268 | break; | |
ed85a06f SL |
269 | case 'r': |
270 | rflag++; | |
271 | break; | |
ed85a06f SL |
272 | case 's': |
273 | sflag++; | |
274 | break; | |
ed85a06f SL |
275 | case 't': |
276 | tflag++; | |
277 | break; | |
404a567d | 278 | case 'u': |
2a893f10 | 279 | af = AF_UNIX; |
404a567d | 280 | break; |
d2c7d54c KB |
281 | case '?': |
282 | default: | |
283 | usage(); | |
284 | } | |
285 | argv += optind; | |
286 | argc -= optind; | |
404a567d | 287 | |
d2c7d54c KB |
288 | if (argc > 0) { |
289 | if (isdigit(argv[0][0])) { | |
290 | interval = atoi(argv[0]); | |
291 | if (interval <= 0) | |
292 | usage(); | |
293 | argv++, argc--; | |
79ddba48 | 294 | iflag++; |
d2c7d54c KB |
295 | } |
296 | if (argc > 0) { | |
297 | system = *argv; | |
298 | argv++, argc--; | |
299 | if (argc > 0) { | |
300 | kmemf = *argv; | |
301 | kflag++; | |
79ddba48 | 302 | } |
ed85a06f | 303 | } |
ed85a06f | 304 | } |
c34ecf77 KS |
305 | if (kvm_openfiles(system, kmemf, (char *)0) == -1) { |
306 | fprintf("netstat(kvm_openfiles): %s\n", kvm_geterr()); | |
ed85a06f SL |
307 | exit(1); |
308 | } | |
c34ecf77 KS |
309 | if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) { |
310 | fprintf(stderr, "%s: no namelist\n", system); | |
ed85a06f SL |
311 | exit(1); |
312 | } | |
ed85a06f | 313 | if (mflag) { |
6538ea31 MK |
314 | mbpr((off_t)nl[N_MBSTAT].n_value); |
315 | exit(0); | |
316 | } | |
317 | if (pflag) { | |
318 | if (tp->pr_stats) | |
d2c7d54c | 319 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, |
6538ea31 MK |
320 | tp->pr_name); |
321 | else | |
322 | printf("%s: no stats routine\n", tp->pr_name); | |
ed85a06f SL |
323 | exit(0); |
324 | } | |
0e710523 MK |
325 | if (hflag) { |
326 | hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value); | |
327 | exit(0); | |
328 | } | |
ed85a06f SL |
329 | /* |
330 | * Keep file descriptors open to avoid overhead | |
331 | * of open/close on each call to get* routines. | |
332 | */ | |
ed85a06f SL |
333 | sethostent(1); |
334 | setnetent(1); | |
90cb8200 SL |
335 | if (iflag) { |
336 | intpr(interval, nl[N_IFNET].n_value); | |
337 | exit(0); | |
338 | } | |
ed85a06f | 339 | if (rflag) { |
bbd2d21e | 340 | if (sflag) |
6538ea31 | 341 | rt_stats((off_t)nl[N_RTSTAT].n_value); |
bbd2d21e | 342 | else |
6538ea31 MK |
343 | routepr((off_t)nl[N_RTHOST].n_value, |
344 | (off_t)nl[N_RTNET].n_value, | |
4390c68f KS |
345 | (off_t)nl[N_RTHASHSIZE].n_value, |
346 | (off_t)nl[N_RTREE].n_value); | |
ed85a06f SL |
347 | exit(0); |
348 | } | |
0be88646 | 349 | if (af == AF_INET || af == AF_UNSPEC) { |
90cb8200 SL |
350 | setprotoent(1); |
351 | setservent(1); | |
ed85a06f | 352 | while (p = getprotoent()) { |
ed85a06f | 353 | |
6df0a927 | 354 | for (tp = protox; tp->pr_name; tp++) |
ed85a06f SL |
355 | if (strcmp(tp->pr_name, p->p_name) == 0) |
356 | break; | |
6df0a927 | 357 | if (tp->pr_name == 0 || tp->pr_wanted == 0) |
ed85a06f | 358 | continue; |
a5545777 MK |
359 | if (sflag) { |
360 | if (tp->pr_stats) | |
95f51977 C |
361 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, |
362 | p->p_name); | |
363 | } else | |
364 | if (tp->pr_cblocks) | |
365 | (*tp->pr_cblocks)(nl[tp->pr_index].n_value, | |
366 | p->p_name); | |
ed85a06f SL |
367 | } |
368 | endprotoent(); | |
0be88646 KS |
369 | } |
370 | if (af == AF_NS || af == AF_UNSPEC) { | |
371 | for (tp = nsprotox; tp->pr_name; tp++) { | |
54c165a5 MK |
372 | if (sflag) { |
373 | if (tp->pr_stats) | |
374 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, | |
375 | tp->pr_name); | |
376 | } else | |
377 | if (tp->pr_cblocks) | |
378 | (*tp->pr_cblocks)(nl[tp->pr_index].n_value, | |
379 | tp->pr_name); | |
0be88646 KS |
380 | } |
381 | } | |
5262655f KS |
382 | if (af == AF_ISO || af == AF_UNSPEC) { |
383 | for (tp = isoprotox; tp->pr_name; tp++) { | |
384 | if (sflag) { | |
385 | if (tp->pr_stats) | |
386 | (*tp->pr_stats)(nl[tp->pr_sindex].n_value, | |
387 | tp->pr_name); | |
388 | } else | |
389 | if (tp->pr_cblocks) | |
390 | (*tp->pr_cblocks)(nl[tp->pr_index].n_value, | |
391 | tp->pr_name); | |
392 | } | |
393 | } | |
54c165a5 | 394 | if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) |
6538ea31 MK |
395 | unixpr((off_t)nl[N_NFILE].n_value, (off_t)nl[N_FILE].n_value, |
396 | (struct protosw *)nl[N_UNIXSW].n_value); | |
0e710523 MK |
397 | if (af == AF_UNSPEC && sflag) |
398 | impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value); | |
085b521c | 399 | exit(0); |
ed85a06f SL |
400 | } |
401 | ||
bbd2d21e SL |
402 | |
403 | char * | |
404 | plural(n) | |
405 | int n; | |
406 | { | |
407 | ||
408 | return (n != 1 ? "s" : ""); | |
409 | } | |
6538ea31 MK |
410 | |
411 | /* | |
412 | * Find the protox for the given "well-known" name. | |
413 | */ | |
414 | struct protox * | |
415 | knownname(name) | |
416 | char *name; | |
417 | { | |
5262655f | 418 | struct protox **tpp, *tp; |
d2c7d54c | 419 | |
5262655f KS |
420 | for (tpp = protoprotox; *tpp; tpp++) |
421 | for (tp = *tpp; tp->pr_name; tp++) | |
6538ea31 MK |
422 | if (strcmp(tp->pr_name, name) == 0) |
423 | return(tp); | |
424 | return(NULLPROTOX); | |
425 | } | |
426 | ||
427 | /* | |
428 | * Find the protox corresponding to name. | |
429 | */ | |
430 | struct protox * | |
431 | name2protox(name) | |
432 | char *name; | |
433 | { | |
434 | struct protox *tp; | |
435 | char **alias; /* alias from p->aliases */ | |
436 | struct protoent *p; | |
d2c7d54c | 437 | |
6538ea31 MK |
438 | /* |
439 | * Try to find the name in the list of "well-known" names. If that | |
440 | * fails, check if name is an alias for an Internet protocol. | |
441 | */ | |
442 | if (tp = knownname(name)) | |
443 | return(tp); | |
d2c7d54c | 444 | |
6538ea31 MK |
445 | setprotoent(1); /* make protocol lookup cheaper */ |
446 | while (p = getprotoent()) { | |
447 | /* assert: name not same as p->name */ | |
448 | for (alias = p->p_aliases; *alias; alias++) | |
449 | if (strcmp(name, *alias) == 0) { | |
450 | endprotoent(); | |
451 | return(knownname(p->p_name)); | |
452 | } | |
453 | } | |
454 | endprotoent(); | |
455 | return(NULLPROTOX); | |
456 | } | |
d2c7d54c KB |
457 | |
458 | usage() | |
459 | { | |
460 | fputs("usage: netstat [-Aan] [-f address_family] [system] [core]\n [-himnrs] [-f address_family] [system] [core]\n [-n] [-I interface] interval [system] [core]\n", stderr); | |
461 | exit(1); | |
462 | } |