main.c revision 1.4 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.4 1994/01/11 19:42:53 brezak 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 #define N_IGMPSTAT 29
118 { "_igmpstat" },
119 #define N_MRTPROTO 30
120 { "_ip_mrtproto" },
121 #define N_MRTSTAT 31
122 { "_mrtstat" },
123 #define N_MRTTABLE 32
124 { "_mrttable" },
125 #define N_VIFTABLE 33
126 { "_viftable" },
127 "",
128 };
129
130 /* internet protocols */
131 extern int protopr();
132 extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
133 extern int igmp_stats();
134 #ifdef NS
135 /* ns protocols */
136 extern int nsprotopr();
137 extern int spp_stats(), idp_stats(), nserr_stats();
138 #endif
139 #ifdef ISO
140 /* iso protocols */
141 extern int iso_protopr();
142 extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
143 #endif
144
145 struct protox {
146 u_char pr_index; /* index into nlist of cb head */
147 u_char pr_sindex; /* index into nlist of stat block */
148 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
149 int (*pr_cblocks)(); /* control blocks printing routine */
150 int (*pr_stats)(); /* statistics printing routine */
151 char *pr_name; /* well-known name */
152 } protox[] = {
153 { N_TCB, N_TCPSTAT, 1, protopr,
154 tcp_stats, "tcp" },
155 { N_UDB, N_UDPSTAT, 1, protopr,
156 udp_stats, "udp" },
157 #ifdef ISO
158 { IN_TP, N_TPSTAT, 1, protopr,
159 tp_stats, "tpip" },
160 #endif
161 { -1, N_IPSTAT, 1, 0,
162 ip_stats, "ip" },
163 { -1, N_ICMPSTAT, 1, 0,
164 icmp_stats, "icmp" },
165 { -1, N_IGMPSTAT, 1, 0,
166 igmp_stats, "igmp" },
167 { -1, -1, 0, 0,
168 0, 0 }
169 };
170
171 #ifdef NS
172 struct protox nsprotox[] = {
173 { N_IDP, N_IDPSTAT, 1, nsprotopr,
174 idp_stats, "idp" },
175 { N_IDP, N_SPPSTAT, 1, nsprotopr,
176 spp_stats, "spp" },
177 { -1, N_NSERR, 1, 0,
178 nserr_stats, "ns_err" },
179 { -1, -1, 0, 0,
180 0, 0 }
181 };
182 #endif
183
184 #ifdef ISO
185 struct protox isoprotox[] = {
186 { ISO_TP, N_TPSTAT, 1, iso_protopr,
187 tp_stats, "tp" },
188 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
189 cltp_stats, "cltp" },
190 { -1, N_CLNPSTAT, 1, 0,
191 clnp_stats, "clnp"},
192 { -1, N_ESISSTAT, 1, 0,
193 esis_stats, "esis"},
194 { -1, -1, 0, 0,
195 0, 0 }
196 };
197 #endif
198
199 struct protox *protoprotox[] = { protox,
200
201 #ifdef NS
202 nsprotox,
203 #endif
204
205 #ifdef ISO
206 isoprotox,
207 #endif
208
209 NULL };
210
211 char *vmunix = _PATH_UNIX;
212 char *kmemf;
213 int kmem;
214 int kflag;
215 int Aflag;
216 int aflag;
217 int hflag;
218 int iflag;
219 int Mflag;
220 int mflag;
221 int nflag;
222 int pflag;
223 int rflag;
224 int sflag;
225 int tflag;
226 int dflag;
227 int interval;
228 char *interface;
229 int unit;
230
231 int af = AF_UNSPEC;
232
233 main(argc, argv)
234 int argc;
235 char **argv;
236 {
237 extern char *optarg;
238 extern int optind;
239 register struct protoent *p;
240 register struct protox *tp; /* for printing cblocks & stats */
241 struct protox *name2protox(); /* for -p */
242 int ch;
243 void usage();
244
245 while ((ch = getopt(argc, argv, "Aac:df:hI:iMmN:np:rstuw:")) != EOF)
246 switch((char)ch) {
247 case 'A':
248 Aflag = 1;
249 break;
250 case 'a':
251 aflag = 1;
252 break;
253 case 'c':
254 kmemf = optarg;
255 kflag = 1;
256 break;
257 case 'd':
258 dflag = 1;
259 break;
260 case 'f':
261 if (strcmp(optarg, "ns") == 0)
262 af = AF_NS;
263 else if (strcmp(optarg, "inet") == 0)
264 af = AF_INET;
265 else if (strcmp(optarg, "unix") == 0)
266 af = AF_UNIX;
267 else if (strcmp(optarg, "iso") == 0)
268 af = AF_ISO;
269 else {
270 (void)fprintf(stderr,
271 "%s: unknown address family\n", optarg);
272 exit(1);
273 }
274 break;
275 case 'h':
276 hflag = 1;
277 break;
278 case 'I': {
279 char *cp;
280
281 iflag = 1;
282 for (cp = interface = optarg; isalpha(*cp); cp++);
283 unit = atoi(cp);
284 *cp = '\0';
285 break;
286 }
287 case 'i':
288 iflag = 1;
289 break;
290 case 'M':
291 Mflag++;
292 break;
293 case 'm':
294 mflag = 1;
295 break;
296 case 'N':
297 vmunix = optarg;
298 break;
299 case 'n':
300 nflag = 1;
301 break;
302 case 'p':
303 if ((tp = name2protox(optarg)) == NULL) {
304 (void)fprintf(stderr,
305 "%s: unknown or uninstrumented protocol\n",
306 optarg);
307 exit(1);
308 }
309 pflag = 1;
310 break;
311 case 'r':
312 rflag = 1;
313 break;
314 case 's':
315 sflag = 1;
316 break;
317 case 't':
318 tflag = 1;
319 break;
320 case 'u':
321 af = AF_UNIX;
322 break;
323 case 'w':
324 interval = atoi(optarg);
325 break;
326 case '?':
327 default:
328 usage();
329 }
330 argv += optind;
331 argc -= optind;
332
333 #define BACKWARD_COMPATIBILITY
334 #ifdef BACKWARD_COMPATIBILITY
335 if (*argv) {
336 if (isdigit(**argv)) {
337 interval = atoi(*argv);
338 if (interval <= 0)
339 usage();
340 ++argv;
341 iflag = 1;
342 }
343 if (*argv) {
344 vmunix = *argv;
345 if (*++argv) {
346 kmemf = *argv;
347 kflag = 1;
348 }
349 }
350 }
351 #endif
352 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) {
353 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr());
354 exit(1);
355 }
356 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
357 fprintf(stderr, "%s: no namelist\n", vmunix);
358 exit(1);
359 }
360 if (mflag) {
361 mbpr((off_t)nl[N_MBSTAT].n_value);
362 exit(0);
363 }
364 if (pflag) {
365 if (tp->pr_stats)
366 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
367 tp->pr_name);
368 else
369 printf("%s: no stats routine\n", tp->pr_name);
370 exit(0);
371 }
372 if (hflag) {
373 #ifdef IMP
374 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
375 #else
376 (void)fprintf(stderr, "netstat: IMP code not compiled in\n");
377 #endif
378 exit(0);
379 }
380 /*
381 * Keep file descriptors open to avoid overhead
382 * of open/close on each call to get* routines.
383 */
384 sethostent(1);
385 setnetent(1);
386 if (iflag) {
387 intpr(interval, nl[N_IFNET].n_value);
388 exit(0);
389 }
390 if (rflag) {
391 if (sflag)
392 rt_stats((off_t)nl[N_RTSTAT].n_value);
393 else
394 routepr((off_t)nl[N_RTHOST].n_value,
395 (off_t)nl[N_RTNET].n_value,
396 (off_t)nl[N_RTHASHSIZE].n_value,
397 (off_t)nl[N_RTREE].n_value);
398 exit(0);
399 }
400 if (Mflag) {
401 if (sflag)
402 mrt_stats((off_t)nl[N_MRTPROTO].n_value,
403 (off_t)nl[N_MRTSTAT].n_value);
404 else
405 mroutepr((off_t)nl[N_MRTPROTO].n_value,
406 (off_t)nl[N_MRTTABLE].n_value,
407 (off_t)nl[N_VIFTABLE].n_value);
408 exit(0);
409 }
410
411 if (af == AF_INET || af == AF_UNSPEC) {
412 setprotoent(1);
413 setservent(1);
414 while (p = getprotoent()) {
415
416 for (tp = protox; tp->pr_name; tp++)
417 if (strcmp(tp->pr_name, p->p_name) == 0)
418 break;
419 if (tp->pr_name == 0 || tp->pr_wanted == 0)
420 continue;
421 if (sflag) {
422 if (tp->pr_stats)
423 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
424 p->p_name);
425 } else
426 if (tp->pr_cblocks)
427 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
428 p->p_name);
429 }
430 endprotoent();
431 }
432 if (af == AF_NS || af == AF_UNSPEC) {
433 #ifdef NS
434 for (tp = nsprotox; tp->pr_name; tp++) {
435 if (sflag) {
436 if (tp->pr_stats)
437 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
438 tp->pr_name);
439 } else
440 if (tp->pr_cblocks)
441 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
442 tp->pr_name);
443 }
444 #endif
445 }
446 if (af == AF_ISO || af == AF_UNSPEC) {
447 #ifdef ISO
448 for (tp = isoprotox; tp->pr_name; tp++) {
449 if (sflag) {
450 if (tp->pr_stats)
451 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
452 tp->pr_name);
453 } else
454 if (tp->pr_cblocks)
455 (*tp->pr_cblocks)(nl[tp->pr_index].n_value,
456 tp->pr_name);
457 }
458 #endif
459 }
460 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
461 unixpr((off_t)nl[N_FILEHEAD].n_value, (off_t)nl[N_FILES].n_value,
462 (struct protosw *)nl[N_UNIXSW].n_value);
463 if (af == AF_UNSPEC && sflag)
464 #ifdef IMP
465 impstats(nl[N_IMP].n_value, nl[N_NIMP].n_value);
466 #endif
467 exit(0);
468 }
469
470 char *
471 plural(n)
472 int n;
473 {
474 return (n != 1 ? "s" : "");
475 }
476
477 /*
478 * Find the protox for the given "well-known" name.
479 */
480 struct protox *
481 knownname(name)
482 char *name;
483 {
484 struct protox **tpp, *tp;
485
486 for (tpp = protoprotox; *tpp; tpp++)
487 for (tp = *tpp; tp->pr_name; tp++)
488 if (strcmp(tp->pr_name, name) == 0)
489 return(tp);
490 return(NULL);
491 }
492
493 /*
494 * Find the protox corresponding to name.
495 */
496 struct protox *
497 name2protox(name)
498 char *name;
499 {
500 struct protox *tp;
501 char **alias; /* alias from p->aliases */
502 struct protoent *p;
503
504 /*
505 * Try to find the name in the list of "well-known" names. If that
506 * fails, check if name is an alias for an Internet protocol.
507 */
508 if (tp = knownname(name))
509 return(tp);
510
511 setprotoent(1); /* make protocol lookup cheaper */
512 while (p = getprotoent()) {
513 /* assert: name not same as p->name */
514 for (alias = p->p_aliases; *alias; alias++)
515 if (strcmp(name, *alias) == 0) {
516 endprotoent();
517 return(knownname(p->p_name));
518 }
519 }
520 endprotoent();
521 return(NULL);
522 }
523
524 void
525 usage()
526 {
527 (void)fprintf(stderr,
528 "usage: netstat [-Aan] [-f address_family] [-c core] [-N system]\n");
529 (void)fprintf(stderr,
530 " [-himnrs] [-f address_family] [-c core] [-N system]\n");
531 (void)fprintf(stderr,
532 " [-n] [-I interface] [-c core] [-N system] [-w wait]\n");
533 (void)fprintf(stderr,
534 " [-c core] [-N system] [-p protocol]\n");
535 exit(1);
536 }
537