Make loses argument information.
[unix-history] / usr.bin / netstat / main.c
CommitLineData
15637ed4
RG
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
35char 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
49f80972
GW
41/* From: static char sccsid[] = "@(#)main.c 5.23 (Berkeley) 7/1/91"; */
42const char main_c_rcsid[] =
7d937176 43 "$Id: main.c,v 1.4 1994/05/17 21:10:16 jkh Exp $";
15637ed4
RG
44#endif /* not lint */
45
46#include <sys/param.h>
47#include <sys/socket.h>
48#include <sys/file.h>
49#include <errno.h>
50#include <netdb.h>
51#include <nlist.h>
52#include <kvm.h>
53#include <stdio.h>
54#include <ctype.h>
55#include <stdlib.h>
56#include <string.h>
57#include <paths.h>
58
59struct nlist nl[] = {
60#define N_MBSTAT 0
61 { "_mbstat" },
62#define N_IPSTAT 1
63 { "_ipstat" },
64#define N_TCB 2
65 { "_tcb" },
66#define N_TCPSTAT 3
67 { "_tcpstat" },
68#define N_UDB 4
69 { "_udb" },
70#define N_UDPSTAT 5
71 { "_udpstat" },
72#define N_IFNET 6
73 { "_ifnet" },
74#define N_IMP 7
75 { "_imp_softc" },
76#define N_RTHOST 8
77 { "_rthost" },
78#define N_RTNET 9
79 { "_rtnet" },
80#define N_ICMPSTAT 10
81 { "_icmpstat" },
82#define N_RTSTAT 11
83 { "_rtstat" },
84#define N_FILEHEAD 12
85 { "_filehead" },
86#define N_FILES 13
87 { "_nfiles" },
88#define N_UNIXSW 14
89 { "_unixsw" },
90#define N_RTHASHSIZE 15
91 { "_rthashsize" },
92#define N_IDP 16
93 { "_nspcb"},
94#define N_IDPSTAT 17
95 { "_idpstat"},
96#define N_SPPSTAT 18
97 { "_spp_istat"},
98#define N_NSERR 19
99 { "_ns_errstat"},
100#define N_CLNPSTAT 20
101 { "_clnp_stat"},
102#define IN_TP 21
103 { "_tp_inpcb" },
104#define ISO_TP 22
105 { "_tp_isopcb" },
106#define N_TPSTAT 23
107 { "_tp_stat" },
108#define N_ESISSTAT 24
109 { "_esis_stat"},
110#define N_NIMP 25
111 { "_nimp"},
112#define N_RTREE 26
113 { "_radix_node_head"},
114#define N_CLTP 27
115 { "_cltb"},
116#define N_CLTPSTAT 28
117 { "_cltpstat"},
06131096
JH
118#define N_IGMPSTAT 29
119 { "_igmpstat" },
120#define N_MRTPROTO 30
121 { "_ip_mrtproto" },
122#define N_MRTSTAT 31
123 { "_mrtstat" },
124#define N_MRTTABLE 32
125 { "_mrttable" },
126#define N_VIFTABLE 33
127 { "_viftable" },
15637ed4
RG
128 "",
129};
130
131/* internet protocols */
132extern int protopr();
133extern int tcp_stats(), udp_stats(), ip_stats(), icmp_stats();
06131096 134extern int igmp_stats();
15637ed4
RG
135#ifdef NS
136/* ns protocols */
137extern int nsprotopr();
138extern int spp_stats(), idp_stats(), nserr_stats();
139#endif
140#ifdef ISO
141/* iso protocols */
142extern int iso_protopr();
143extern int tp_stats(), esis_stats(), clnp_stats(), cltp_stats();
144#endif
145
146struct protox {
147 u_char pr_index; /* index into nlist of cb head */
148 u_char pr_sindex; /* index into nlist of stat block */
149 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
150 int (*pr_cblocks)(); /* control blocks printing routine */
151 int (*pr_stats)(); /* statistics printing routine */
152 char *pr_name; /* well-known name */
153} protox[] = {
154 { N_TCB, N_TCPSTAT, 1, protopr,
155 tcp_stats, "tcp" },
156 { N_UDB, N_UDPSTAT, 1, protopr,
157 udp_stats, "udp" },
158#ifdef ISO
159 { IN_TP, N_TPSTAT, 1, protopr,
160 tp_stats, "tpip" },
161#endif
162 { -1, N_IPSTAT, 1, 0,
163 ip_stats, "ip" },
164 { -1, N_ICMPSTAT, 1, 0,
165 icmp_stats, "icmp" },
06131096
JH
166 { -1, N_IGMPSTAT, 1, 0,
167 igmp_stats, "igmp"},
15637ed4
RG
168 { -1, -1, 0, 0,
169 0, 0 }
170};
171
172#ifdef NS
173struct protox nsprotox[] = {
174 { N_IDP, N_IDPSTAT, 1, nsprotopr,
175 idp_stats, "idp" },
176 { N_IDP, N_SPPSTAT, 1, nsprotopr,
177 spp_stats, "spp" },
178 { -1, N_NSERR, 1, 0,
179 nserr_stats, "ns_err" },
180 { -1, -1, 0, 0,
181 0, 0 }
182};
183#endif
184
185#ifdef ISO
186struct protox isoprotox[] = {
187 { ISO_TP, N_TPSTAT, 1, iso_protopr,
188 tp_stats, "tp" },
189 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
190 cltp_stats, "cltp" },
191 { -1, N_CLNPSTAT, 1, 0,
192 clnp_stats, "clnp"},
193 { -1, N_ESISSTAT, 1, 0,
194 esis_stats, "esis"},
195 { -1, -1, 0, 0,
196 0, 0 }
197};
198#endif
199
200struct protox *protoprotox[] = { protox,
201
202#ifdef NS
203nsprotox,
204#endif
205
206#ifdef ISO
207isoprotox,
208#endif
209
210NULL };
211
212char *vmunix = _PATH_UNIX;
213char *kmemf;
214int kmem;
215int kflag;
216int Aflag;
217int aflag;
218int hflag;
219int iflag;
220int mflag;
221int nflag;
222int pflag;
223int rflag;
06131096 224int Rflag; /* Multicast routing stats */
15637ed4
RG
225int sflag;
226int tflag;
227int dflag;
228int interval;
229char *interface;
230int unit;
231
232int af = AF_UNSPEC;
233
234main(argc, argv)
235 int argc;
236 char **argv;
237{
238 extern char *optarg;
239 extern int optind;
240 register struct protoent *p;
241 register struct protox *tp; /* for printing cblocks & stats */
242 struct protox *name2protox(); /* for -p */
243 int ch;
244 void usage();
245
7d937176 246 while ((ch = getopt(argc, argv, "Aadf:ghI:iM:mN:np:rstuw:")) != EOF)
15637ed4
RG
247 switch((char)ch) {
248 case 'A':
249 Aflag = 1;
250 break;
251 case 'a':
252 aflag = 1;
253 break;
254 case 'd':
255 dflag = 1;
256 break;
257 case 'f':
258 if (strcmp(optarg, "ns") == 0)
259 af = AF_NS;
260 else if (strcmp(optarg, "inet") == 0)
261 af = AF_INET;
262 else if (strcmp(optarg, "unix") == 0)
263 af = AF_UNIX;
264 else if (strcmp(optarg, "iso") == 0)
265 af = AF_ISO;
266 else {
267 (void)fprintf(stderr,
268 "%s: unknown address family\n", optarg);
269 exit(1);
270 }
271 break;
272 case 'h':
273 hflag = 1;
274 break;
275 case 'I': {
276 char *cp;
277
278 iflag = 1;
279 for (cp = interface = optarg; isalpha(*cp); cp++);
280 unit = atoi(cp);
281 *cp = '\0';
282 break;
283 }
284 case 'i':
285 iflag = 1;
286 break;
287 case 'M':
288 kmemf = optarg;
289 kflag = 1;
290 break;
291 case 'm':
292 mflag = 1;
293 break;
294 case 'N':
295 vmunix = optarg;
296 break;
297 case 'n':
298 nflag = 1;
299 break;
300 case 'p':
301 if ((tp = name2protox(optarg)) == NULL) {
302 (void)fprintf(stderr,
303 "%s: unknown or uninstrumented protocol\n",
304 optarg);
305 exit(1);
306 }
307 pflag = 1;
308 break;
309 case 'r':
310 rflag = 1;
311 break;
7d937176 312 case 'g':
06131096
JH
313 Rflag = 1;
314 break;
15637ed4
RG
315 case 's':
316 sflag = 1;
317 break;
318 case 't':
319 tflag = 1;
320 break;
321 case 'u':
322 af = AF_UNIX;
323 break;
324 case 'w':
325 interval = atoi(optarg);
326 break;
327 case '?':
328 default:
329 usage();
330 }
331 argv += optind;
332 argc -= optind;
333
334#define BACKWARD_COMPATIBILITY
335#ifdef BACKWARD_COMPATIBILITY
336 if (*argv) {
337 if (isdigit(**argv)) {
338 interval = atoi(*argv);
339 if (interval <= 0)
340 usage();
341 ++argv;
342 iflag = 1;
343 }
344 if (*argv) {
345 vmunix = *argv;
346 if (*++argv) {
347 kmemf = *argv;
348 kflag = 1;
349 }
350 }
351 }
352#endif
353 if (kvm_openfiles(vmunix, kmemf, NULL) == -1) {
354 fprintf(stderr, "netstat: kvm_openfiles: %s\n", kvm_geterr());
355 exit(1);
356 }
357 if (kvm_nlist(nl) < 0 || nl[0].n_type == 0) {
358 fprintf(stderr, "%s: no namelist\n", vmunix);
359 exit(1);
360 }
361 if (mflag) {
362 mbpr((off_t)nl[N_MBSTAT].n_value);
363 exit(0);
364 }
365 if (pflag) {
366 if (tp->pr_stats)
367 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
368 tp->pr_name);
369 else
370 printf("%s: no stats routine\n", tp->pr_name);
371 exit(0);
372 }
373 if (hflag) {
374#ifdef IMP
375 hostpr(nl[N_IMP].n_value, nl[N_NIMP].n_value);
376#else
377 (void)fprintf(stderr, "netstat: IMP code not compiled in\n");
378#endif
379 exit(0);
380 }
381 /*
382 * Keep file descriptors open to avoid overhead
383 * of open/close on each call to get* routines.
384 */
385 sethostent(1);
386 setnetent(1);
387 if (iflag) {
388 intpr(interval, nl[N_IFNET].n_value);
389 exit(0);
390 }
391 if (rflag) {
392 if (sflag)
393 rt_stats((off_t)nl[N_RTSTAT].n_value);
394 else
395 routepr((off_t)nl[N_RTHOST].n_value,
396 (off_t)nl[N_RTNET].n_value,
397 (off_t)nl[N_RTHASHSIZE].n_value,
398 (off_t)nl[N_RTREE].n_value);
399 exit(0);
400 }
06131096
JH
401 if (Rflag) {
402 if (sflag)
403 mrt_stats((off_t)nl[N_MRTPROTO].n_value,
404 (off_t)nl[N_MRTSTAT].n_value);
405 else
406 mroutepr((off_t)nl[N_MRTPROTO].n_value,
407 (off_t)nl[N_MRTTABLE].n_value,
408 (off_t)nl[N_VIFTABLE].n_value);
409 exit(0);
410 }
15637ed4
RG
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
470char *
471plural(n)
472 int n;
473{
474 return (n != 1 ? "s" : "");
475}
476
477/*
478 * Find the protox for the given "well-known" name.
479 */
480struct protox *
481knownname(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 */
496struct protox *
497name2protox(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
524void
525usage()
526{
527 (void)fprintf(stderr,
528"usage: netstat [-Aan] [-f address_family] [-M core] [-N system]\n");
529 (void)fprintf(stderr,
06131096 530" [-himnrRs] [-f address_family] [-M core] [-N system]\n");
15637ed4
RG
531 (void)fprintf(stderr,
532" [-n] [-I interface] [-M core] [-N system] [-w wait]\n");
533 (void)fprintf(stderr,
534" [-M core] [-N system] [-p protocol]\n");
535 exit(1);
536}