main.c revision 1.3 1 /*
2 * Copyright (c) 1983, 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 /*static char sccsid[] = "from: @(#)main.c 5.23 (Berkeley) 7/1/91";*/
42 static char rcsid[] = "$Id: main.c,v 1.3 1993/12/22 04:00:31 cgd Exp $";
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/socket.h>
47 #include <sys/file.h>
48 #include <errno.h>
49 #include <netdb.h>
50 #include <nlist.h>
51 #include <kvm.h>
52 #include <stdio.h>
53 #include <ctype.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <paths.h>
57
58 struct nlist nl[] = {
59 #define N_MBSTAT 0
60 { "_mbstat" },
61 #define N_IPSTAT 1
62 { "_ipstat" },
63 #define N_TCB 2
64 { "_tcb" },
65 #define N_TCPSTAT 3
66 { "_tcpstat" },
67 #define N_UDB 4
68 { "_udb" },
69 #define N_UDPSTAT 5
70 { "_udpstat" },
71 #define N_IFNET 6
72 { "_ifnet" },
73 #define N_IMP 7
74 { "_imp_softc" },
75 #define N_RTHOST 8
76 { "_rthost" },
77 #define N_RTNET 9
78 { "_rtnet" },
79 #define N_ICMPSTAT 10
80 { "_icmpstat" },
81 #define N_RTSTAT 11
82 { "_rtstat" },
83 #define N_FILEHEAD 12
84 { "_filehead" },
85 #define N_FILES 13
86 { "_nfiles" },
87 #define N_UNIXSW 14
88 { "_unixsw" },
89 #define N_RTHASHSIZE 15
90 { "_rthashsize" },
91 #define N_IDP 16
92 { "_nspcb"},
93 #define N_IDPSTAT 17
94 { "_idpstat"},
95 #define N_SPPSTAT 18
96 { "_spp_istat"},
97 #define N_NSERR 19
98 { "_ns_errstat"},
99 #define N_CLNPSTAT 20
100 { "_clnp_stat"},
101 #define IN_TP 21
102 { "_tp_inpcb" },
103 #define ISO_TP 22
104 { "_tp_isopcb" },
105 #define N_TPSTAT 23
106 { "_tp_stat" },
107 #define N_ESISSTAT 24
108 { "_esis_stat"},
109 #define N_NIMP 25
110 { "_nimp"},
111 #define N_RTREE 26
112 { "_radix_node_head"},
113 #define N_CLTP 27
114 { "_cltb"},
115 #define N_CLTPSTAT 28
116 { "_cltpstat"},
117 "",
118 };
119
120 /* internet protocols */
121 extern int protopr();
122 extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
123 #ifdef NS
124 /* ns protocols */
125 extern int nsprotopr();
126 extern int spp_stats(), idp_stats(), nserr_stats();
127 #endif
128 #ifdef ISO
129 /* iso protocols */
130 extern int iso_protopr();
131 extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
132 #endif
133
134 struct protox {
135 u_char pr_index; /* index into nlist of cb head */
136 u_char pr_sindex; /* index into nlist of stat block */
137 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
138 int (*pr_cblocks)(); /* control blocks printing routine */
139 int (*pr_stats)(); /* statistics printing routine */
140 char *pr_name; /* well-known name */
141 } protox[] = {
142 { N_TCB, N_TCPSTAT, 1, protopr,
143 tcp_stats, "tcp" },
144 { N_UDB, N_UDPSTAT, 1, protopr,
145 udp_stats, "udp" },
146 #ifdef ISO
147 { IN_TP, N_TPSTAT, 1, protopr,
148 tp_stats, "tpip" },
149 #endif
150 { -1, N_IPSTAT, 1, 0,
151 ip_stats, "ip" },
152 { -1, N_ICMPSTAT, 1, 0,
153 icmp_stats, "icmp" },
154 { -1, -1, 0, 0,
155 0, 0 }
156 };
157
158 #ifdef NS
159 struct protox nsprotox[] = {
160 { N_IDP, N_IDPSTAT, 1, nsprotopr,
161 idp_stats, "idp" },
162 { N_IDP, N_SPPSTAT, 1, nsprotopr,
163 spp_stats, "spp" },
164 { -1, N_NSERR, 1, 0,
165 nserr_stats, "ns_err" },
166 { -1, -1, 0, 0,
167 0, 0 }
168 };
169 #endif
170
171 #ifdef ISO
172 struct protox isoprotox[] = {
173 { ISO_TP, N_TPSTAT, 1, iso_protopr,
174 tp_stats, "tp" },
175 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
176 cltp_stats, "cltp" },
177 { -1, N_CLNPSTAT, 1, 0,
178 clnp_stats, "clnp"},
179 { -1, N_ESISSTAT, 1, 0,
180 esis_stats, "esis"},
181 { -1, -1, 0, 0,
182 0, 0 }
183 };
184 #endif
185
186 struct protox *protoprotox[] = { protox,
187
188 #ifdef NS
189 nsprotox,
190 #endif
191
192 #ifdef ISO
193 isoprotox,
194 #endif
195
196 NULL };
197
198 char *vmunix = _PATH_UNIX;
199 char *kmemf;
200 int kmem;
201 int kflag;
202 int Aflag;
203 int aflag;
204 int hflag;
205 int iflag;
206 int mflag;
207 int nflag;
208 int pflag;
209 int rflag;
210 int sflag;
211 int tflag;
212 int dflag;
213 int interval;
214 char *interface;
215 int unit;
216
217 int af = AF_UNSPEC;
218
219 main(argc, argv)
220 int argc;
221 char **argv;
222 {
223 extern char *optarg;
224 extern int optind;
225 register struct protoent *p;
226 register struct protox *tp; /* for printing cblocks & stats */
227 struct protox *name2protox(); /* for -p */
228 int ch;
229 void usage();
230
231 while ((ch = getopt(argc, argv, "Aadf:hI:iM:mN:np:rstuw:")) != EOF)
232 switch((char)ch) {
233 case 'A':
234 Aflag = 1;
235 break;
236 case 'a':
237 aflag = 1;
238 break;
239 case 'd':
240 dflag = 1;
241 break;
242 case 'f':
243 if (strcmp(optarg, "ns") == 0)
244 af = AF_NS;
245 else if (strcmp(optarg, "inet") == 0)
246 af = AF_INET;
247 else if (strcmp(optarg, "unix") == 0)
248 af = AF_UNIX;
249 else if (strcmp(optarg, "iso") == 0)
250 af = AF_ISO;
251 else {
252 (void)fprintf(stderr,
253 "%s: unknown address family\n", optarg);
254 exit(1);
255 }
256 break;
257 case 'h':
258 hflag = 1;
259 break;
260 case 'I': {
261 char *cp;
262
263 iflag = 1;
264 for (cp = interface = optarg; isalpha(*cp); cp++);
265 unit = atoi(cp);
266 *cp = '\0';
267 break;
268 }
269 case 'i':
270 iflag = 1;
271 break;
272 case 'M':
273 kmemf = optarg;
274 kflag = 1;
275 break;
276 case 'm':
277 mflag = 1;
278 break;
279 case 'N':
280 vmunix = optarg;
281 break;
282 case 'n':
283 nflag = 1;
284 break;
285 case 'p':
286 if ((tp = name2protox(optarg)) == NULL) {
287 (void)fprintf(stderr,
288 "%s: unknown or uninstrumented protocol\n",
289 optarg);
290 exit(1);
291 }
292 pflag = 1;
293 break;
294 case 'r':
295 rflag = 1;
296 break;
297 case 's':
298 sflag = 1;
299 break;
300 case 't':
301 tflag = 1;
302 break;
303 case 'u':
304 af = AF_UNIX;
305 break;
306 case 'w':
307 interval = atoi(optarg);
308 iflag = 1;
309 break;
310 case '?':
311 default:
312 usage();
313 }
314 argv += optind;
315 argc -= optind;
316
317 #define BACKWARD_COMPATIBILITY
318 #ifdef BACKWARD_COMPATIBILITY
319 if (*argv) {
320 if (isdigit(**argv)) {
321 interval = atoi(*argv);
322 if (interval <= 0)
323 usage();
324 ++argv;
325 iflag = 1;
326 }
327 if (*argv) {
328 vmunix = *argv;
329 if (*++argv) {
330 kmemf = *argv;
331 kflag = 1;
332 }
333 }
334 }
335 #endif
336 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) {
337 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr());
338 exit(1);
339 }
340 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
341 fprintf(stderr, "%s: no namelist\n", vmunix);
342 exit(1);
343 }
344 if (mflag) {
345 mbpr((off_t)nl[N_MBSTAT].n_value);
346 exit(0);
347 }
348 if (pflag) {
349 if (tp->pr_stats)
350 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
351 tp->pr_name);
352 else
353 printf("%s: no stats routine\n", tp->pr_name);
354 exit(0);
355 }
356 if (hflag) {
357 #ifdef IMP
358 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
359 #else
360 (void)fprintf(stderr, "netstat: IMP code not compiled in\n");
361 #endif
362 exit(0);
363 }
364 /*
365 * Keep file descriptors open to avoid overhead
366 * of open/close on each call to get* routines.
367 */
368 sethostent(1);
369 setnetent(1);
370 if (iflag) {
371 intpr(interval, nl[N_IFNET].n_value);
372 exit(0);
373 }
374 if (rflag) {
375 if (sflag)
376 rt_stats((off_t)nl[N_RTSTAT].n_value);
377 else
378 routepr((off_t)nl[N_RTHOST].n_value,
379 (off_t)nl[N_RTNET].n_value,
380 (off_t)nl[N_RTHASHSIZE].n_value,
381 (off_t)nl[N_RTREE].n_value);
382 exit(0);
383 }
384 if (af == AF_INET || af == AF_UNSPEC) {
385 setprotoent(1);
386 setservent(1);
387 while (p = getprotoent()) {
388
389 for (tp = protox; tp->pr_name; tp++)
390 if (strcmp(tp->pr_name, p->p_name) == 0)
391 break;
392 if (tp->pr_name == 0 || tp->pr_wanted == 0)
393 continue;
394 if (sflag) {
395 if (tp->pr_stats)
396 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
397 p->p_name);
398 } else
399 if (tp->pr_cblocks)
400 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
401 p->p_name);
402 }
403 endprotoent();
404 }
405 if (af == AF_NS || af == AF_UNSPEC) {
406 #ifdef NS
407 for (tp = nsprotox; tp->pr_name; tp++) {
408 if (sflag) {
409 if (tp->pr_stats)
410 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
411 tp->pr_name);
412 } else
413 if (tp->pr_cblocks)
414 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
415 tp->pr_name);
416 }
417 #endif
418 }
419 if (af == AF_ISO || af == AF_UNSPEC) {
420 #ifdef ISO
421 for (tp = isoprotox; tp->pr_name; tp++) {
422 if (sflag) {
423 if (tp->pr_stats)
424 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
425 tp->pr_name);
426 } else
427 if (tp->pr_cblocks)
428 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
429 tp->pr_name);
430 }
431 #endif
432 }
433 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
434 unixpr((off_t)nl[N_FILEHEAD].n_value, (off_t)nl[N_FILES].n_value,
435 (struct protosw *)nl[N_UNIXSW].n_value);
436 if (af == AF_UNSPEC && sflag)
437 #ifdef IMP
438 impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value);
439 #endif
440 exit(0);
441 }
442
443 char *
444 plural(n)
445 int n;
446 {
447 return (n != 1 ? "s" : "");
448 }
449
450 /*
451 * Find the protox for the given "well-known" name.
452 */
453 struct protox *
454 knownname(name)
455 char *name;
456 {
457 struct protox **tpp, *tp;
458
459 for (tpp = protoprotox; *tpp; tpp++)
460 for (tp = *tpp; tp->pr_name; tp++)
461 if (strcmp(tp->pr_name, name) == 0)
462 return(tp);
463 return(NULL);
464 }
465
466 /*
467 * Find the protox corresponding to name.
468 */
469 struct protox *
470 name2protox(name)
471 char *name;
472 {
473 struct protox *tp;
474 char **alias; /* alias from p->aliases */
475 struct protoent *p;
476
477 /*
478 * Try to find the name in the list of "well-known" names. If that
479 * fails, check if name is an alias for an Internet protocol.
480 */
481 if (tp = knownname(name))
482 return(tp);
483
484 setprotoent(1); /* make protocol lookup cheaper */
485 while (p = getprotoent()) {
486 /* assert: name not same as p->name */
487 for (alias = p->p_aliases; *alias; alias++)
488 if (strcmp(name, *alias) == 0) {
489 endprotoent();
490 return(knownname(p->p_name));
491 }
492 }
493 endprotoent();
494 return(NULL);
495 }
496
497 void
498 usage()
499 {
500 (void)fprintf(stderr,
501 "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]\n");
502 (void)fprintf(stderr,
503 " [-himnrs] [-f address_family] [-M core] [-N system]\n");
504 (void)fprintf(stderr,
505 " [-n] [-I interface] [-M core] [-N system] [-w wait]\n");
506 (void)fprintf(stderr,
507 " [-M core] [-N system] [-p protocol]\n");
508 exit(1);
509 }
510