]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/main.c
network_cmds-307.1.1.tar.gz
[apple/network_cmds.git] / netstat.tproj / main.c
CommitLineData
b7080c8e
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
a2c93a76
A
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
b7080c8e
A
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
a2c93a76
A
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
b7080c8e
A
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright (c) 1983, 1988, 1993
26 * Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57#ifndef lint
58char const copyright[] =
59"@(#) Copyright (c) 1983, 1988, 1993\n\
60 Regents of the University of California. All rights reserved.\n";
61#endif /* not lint */
62
63#ifndef lint
64#if 0
65static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
66#endif
67static const char rcsid[] =
2b484d24 68 "$Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $";
b7080c8e
A
69#endif /* not lint */
70
71#include <sys/param.h>
72#include <sys/file.h>
b7080c8e
A
73#include <sys/socket.h>
74
75#include <netinet/in.h>
2b484d24 76#include <net/pfkeyv2.h>
b7080c8e
A
77
78#include <ctype.h>
79#include <err.h>
80#include <errno.h>
b7080c8e
A
81#include <limits.h>
82#include <netdb.h>
83#include <nlist.h>
84#include <paths.h>
85#include <stdio.h>
86#include <stdlib.h>
87#include <string.h>
88#include <unistd.h>
89#include "netstat.h"
90#include <sys/types.h>
91#include <sys/sysctl.h>
92
b8dff150
A
93#ifdef __APPLE__
94#include <TargetConditionals.h>
95#endif
b7080c8e
A
96
97/*
98 * ----------------------------------------------------------------------------
99 * "THE BEER-WARE LICENSE" (Revision 42):
100 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
101 * can do whatever you want with this stuff. If we meet some day, and you think
102 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
103 * ----------------------------------------------------------------------------
104 *
2b484d24 105 * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $
b7080c8e
A
106 *
107 */
108
b7080c8e
A
109static struct nlist nl[] = {
110#define N_IFNET 0
111 { "_ifnet" },
112#define N_IMP 1
113 { "_imp_softc" },
114#define N_RTSTAT 2
115 { "_rtstat" },
116#define N_UNIXSW 3
117 { "_localsw" },
118#define N_IDP 4
119 { "_nspcb"},
120#define N_IDPSTAT 5
121 { "_idpstat"},
122#define N_SPPSTAT 6
123 { "_spp_istat"},
124#define N_NSERR 7
125 { "_ns_errstat"},
126#define N_CLNPSTAT 8
127 { "_clnp_stat"},
128#define IN_NOTUSED 9
129 { "_tp_inpcb" },
130#define ISO_TP 10
131 { "_tp_refinfo" },
132#define N_TPSTAT 11
133 { "_tp_stat" },
134#define N_ESISSTAT 12
135 { "_esis_stat"},
136#define N_NIMP 13
137 { "_nimp"},
138#define N_RTREE 14
139 { "_rt_tables"},
140#define N_CLTP 15
141 { "_cltb"},
142#define N_CLTPSTAT 16
143 { "_cltpstat"},
144#define N_NFILE 17
145 { "_nfile" },
146#define N_FILE 18
147 { "_file" },
b7080c8e
A
148#define N_IPX 22
149 { "_ipxpcb"},
150#define N_IPXSTAT 23
151 { "_ipxstat"},
152#define N_SPXSTAT 24
153 { "_spx_istat"},
154#define N_DDPSTAT 25
155 { "_ddpstat"},
156#define N_DDPCB 26
157 { "_ddpcb"},
7ba0088d
A
158#define N_NGSOCKS 27
159 { "_ngsocklist"},
160#define N_IP6STAT 28
161 { "_ip6stat" },
162#define N_ICMP6STAT 29
163 { "_icmp6stat" },
164#define N_IPSECSTAT 30
165 { "_ipsecstat" },
166#define N_IPSEC6STAT 31
167 { "_ipsec6stat" },
168#define N_PIM6STAT 32
169 { "_pim6stat" },
170#define N_MRT6PROTO 33
171 { "_ip6_mrtproto" },
172#define N_MRT6STAT 34
173 { "_mrt6stat" },
174#define N_MF6CTABLE 35
175 { "_mf6ctable" },
176#define N_MIF6TABLE 36
177 { "_mif6table" },
178#define N_PFKEYSTAT 37
179 { "_pfkeystat" },
180#define N_MBSTAT 38
181 { "_mbstat" },
182#define N_MBTYPES 39
183 { "_mbtypes" },
184#define N_NMBCLUSTERS 40
185 { "_nmbclusters" },
186#define N_NMBUFS 41
187 { "_nmbufs" },
188#define N_RTTRASH 42
189 { "_rttrash" },
b7080c8e
A
190 { "" },
191};
192
193
b7080c8e
A
194struct protox {
195 u_char pr_index; /* index into nlist of cb head */
196 u_char pr_sindex; /* index into nlist of stat block */
197 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
7ba0088d
A
198 void (*pr_cblocks)(u_long, char *, int);
199 /* control blocks printing routine */
200 void (*pr_stats)(u_long, char *, int);
201 /* statistics printing routine */
202 void (*pr_istats)(char *); /* per/if statistics printing routine */
b7080c8e
A
203 char *pr_name; /* well-known name */
204 int pr_usesysctl; /* true if we use sysctl, not kvm */
205} protox[] = {
206 { -1, -1, 1, protopr,
7ba0088d 207 tcp_stats, NULL, "tcp", IPPROTO_TCP },
b7080c8e 208 { -1, -1, 1, protopr,
7ba0088d 209 udp_stats, NULL, "udp", IPPROTO_UDP },
b7080c8e 210 { -1, -1, 1, protopr,
7ba0088d 211 NULL, NULL, "divert",IPPROTO_DIVERT },
b7080c8e 212 { -1, -1, 1, protopr,
7ba0088d 213 ip_stats, NULL, "ip", IPPROTO_RAW },
b7080c8e 214 { -1, -1, 1, protopr,
7ba0088d 215 icmp_stats, NULL, "icmp", IPPROTO_ICMP },
b7080c8e 216 { -1, -1, 1, protopr,
7ba0088d
A
217 igmp_stats, NULL, "igmp", IPPROTO_IGMP },
218#ifdef IPSEC
2b484d24
A
219 { -1, -1, 1, 0,
220 ipsec_stats, NULL, "ipsec", IPPROTO_ESP},
7ba0088d
A
221#endif
222#if 0
223 { -1, -1, 1, 0,
224 bdg_stats, NULL, "bdg", 1 /* bridging... */ },
225#endif
226 { -1, -1, 0, 0,
227 0, NULL, 0 }
228};
229
230#ifdef INET6
231struct protox ip6protox[] = {
232 { -1, -1, 1, protopr,
233 tcp_stats, NULL, "tcp", IPPROTO_TCP },
234 { -1, -1, 1, protopr,
235 udp_stats, NULL, "udp", IPPROTO_UDP },
236 { -1, N_IP6STAT, 1, protopr,
237 ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW },
238 { -1, N_ICMP6STAT, 1, protopr,
239 icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 },
240#ifdef IPSEC
241 { -1, N_IPSEC6STAT, 1, 0,
2b484d24 242 ipsec_stats, NULL, "ipsec6",IPPROTO_ESP },
7ba0088d
A
243#endif
244#ifdef notyet
245 { -1, N_PIM6STAT, 1, 0,
246 pim6_stats, NULL, "pim6", 0 },
247#endif
248 { -1, -1, 1, 0,
2b484d24 249 rip6_stats, NULL, "rip6", IPPROTO_RAW },
7ba0088d
A
250#if 0
251 { -1, -1, 1, 0,
252 bdg_stats, NULL, "bdg", 1 /* bridging... */ },
253#endif
b7080c8e 254 { -1, -1, 0, 0,
7ba0088d 255 0, NULL, 0, 0 }
b7080c8e 256};
7ba0088d 257#endif /*INET6*/
b7080c8e 258
7ba0088d
A
259#ifdef IPSEC
260struct protox pfkeyprotox[] = {
261 { -1, N_PFKEYSTAT, 1, 0,
2b484d24 262 pfkey_stats, NULL, "pfkey", PF_KEY_V2 },
7ba0088d
A
263 { -1, -1, 0, 0,
264 0, NULL, 0, 0 }
265};
266#endif
267#ifndef __APPLE__
b7080c8e
A
268struct protox atalkprotox[] = {
269 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
7ba0088d 270 ddp_stats, NULL, "ddp" },
b7080c8e 271 { -1, -1, 0, 0,
7ba0088d
A
272 0, NULL, 0 }
273};
274
275struct protox netgraphprotox[] = {
276 { N_NGSOCKS, -1, 1, netgraphprotopr,
277 NULL, NULL, "ctrl" },
278 { N_NGSOCKS, -1, 1, netgraphprotopr,
279 NULL, NULL, "data" },
280 { -1, NULL, 0, 0,
281 0, NULL, 0 }
b7080c8e 282};
b7080c8e 283
b7080c8e
A
284struct protox ipxprotox[] = {
285 { N_IPX, N_IPXSTAT, 1, ipxprotopr,
7ba0088d 286 ipx_stats, NULL, "ipx", 0 },
b7080c8e 287 { N_IPX, N_SPXSTAT, 1, ipxprotopr,
7ba0088d 288 spx_stats, NULL, "spx", 0 },
b7080c8e 289 { -1, -1, 0, 0,
7ba0088d 290 0, NULL, 0, 0 }
b7080c8e
A
291};
292#endif
b7080c8e
A
293#ifdef NS
294struct protox nsprotox[] = {
295 { N_IDP, N_IDPSTAT, 1, nsprotopr,
7ba0088d 296 idp_stats, NULL, "idp" },
b7080c8e 297 { N_IDP, N_SPPSTAT, 1, nsprotopr,
7ba0088d 298 spp_stats, NULL, "spp" },
b7080c8e 299 { -1, N_NSERR, 1, 0,
7ba0088d 300 nserr_stats, NULL, "ns_err" },
b7080c8e 301 { -1, -1, 0, 0,
7ba0088d 302 0, NULL, 0 }
b7080c8e
A
303};
304#endif
305
306#ifdef ISO
307struct protox isoprotox[] = {
308 { ISO_TP, N_TPSTAT, 1, iso_protopr,
7ba0088d 309 tp_stats, NULL, "tp" },
b7080c8e 310 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
7ba0088d 311 cltp_stats, NULL, "cltp" },
b7080c8e 312 { -1, N_CLNPSTAT, 1, 0,
7ba0088d 313 clnp_stats, NULL, "clnp"},
b7080c8e 314 { -1, N_ESISSTAT, 1, 0,
7ba0088d 315 esis_stats, NULL, "esis"},
b7080c8e 316 { -1, -1, 0, 0,
7ba0088d 317 0, NULL, 0 }
b7080c8e
A
318};
319#endif
320
7ba0088d
A
321struct protox *protoprotox[] = {
322 protox,
323#ifdef INET6
324 ip6protox,
b7080c8e 325#endif
7ba0088d
A
326#ifdef IPSEC
327 pfkeyprotox,
328#endif
329#ifndef __APPLE__
330 ipxprotox, atalkprotox,
b7080c8e 331#endif
b7080c8e
A
332#ifdef NS
333 nsprotox,
334#endif
335#ifdef ISO
336 isoprotox,
337#endif
338 NULL };
339
7ba0088d
A
340static void printproto (struct protox *, char *);
341static void usage (void);
342static struct protox *name2protox (char *);
343static struct protox *knownname (char *);
ac2f15b3
A
344#ifdef SRVCACHE
345extern void _serv_cache_close();
346#endif
b7080c8e 347
7ba0088d
A
348int Aflag; /* show addresses of protocol control block */
349int aflag; /* show all sockets (including servers) */
350int bflag; /* show i/f total bytes in/out */
351int dflag; /* show i/f dropped packets */
b8dff150 352#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
7ba0088d 353int gflag; /* show group (multicast) routing or stats */
b8dff150 354#endif
7ba0088d
A
355int iflag; /* show interfaces */
356int lflag; /* show routing table with use and ref */
357int Lflag; /* show size of listen queues */
358int mflag; /* show memory stats */
359int nflag; /* show addresses numerically */
360static int pflag; /* show given protocol */
361int rflag; /* show routing tables (or routing stats) */
362int sflag; /* show protocol statistics */
363int tflag; /* show i/f watchdog timers */
364int Wflag; /* wide display */
365
366int interval; /* repeat interval for i/f stats */
367
368char *interface; /* desired i/f for stats, or NULL for all i/fs */
369int unit; /* unit number for above */
370
371int af; /* address family */
b7080c8e
A
372
373int
374main(argc, argv)
375 int argc;
376 char *argv[];
377{
7ba0088d 378 register struct protox *tp = NULL; /* for printing cblocks & stats */
b7080c8e
A
379 int ch;
380
381 af = AF_UNSPEC;
382
b8dff150 383 while ((ch = getopt(argc, argv, "Aabdf:gI:iLlmnp:rRstuWw:")) != -1)
b7080c8e
A
384 switch(ch) {
385 case 'A':
386 Aflag = 1;
387 break;
388 case 'a':
389 aflag = 1;
390 break;
391 case 'b':
392 bflag = 1;
393 break;
394 case 'd':
395 dflag = 1;
396 break;
397 case 'f':
398#ifdef NS
399 if (strcmp(optarg, "ns") == 0)
400 af = AF_NS;
401 else
402#endif
403 if (strcmp(optarg, "ipx") == 0)
404 af = AF_IPX;
405 else if (strcmp(optarg, "inet") == 0)
406 af = AF_INET;
7ba0088d
A
407#ifdef INET6
408 else if (strcmp(optarg, "inet6") == 0)
409 af = AF_INET6;
410#endif /*INET6*/
411#ifdef INET6
412 else if (strcmp(optarg, "pfkey") == 0)
413 af = PF_KEY;
414#endif /*INET6*/
b7080c8e
A
415 else if (strcmp(optarg, "unix") == 0)
416 af = AF_UNIX;
7ba0088d 417#ifndef __APPLE__
b7080c8e
A
418 else if (strcmp(optarg, "atalk") == 0)
419 af = AF_APPLETALK;
7ba0088d
A
420 else if (strcmp(optarg, "ng") == 0
421 || strcmp(optarg, "netgraph") == 0)
422 af = AF_NETGRAPH;
423#endif
b7080c8e
A
424#ifdef ISO
425 else if (strcmp(optarg, "iso") == 0)
426 af = AF_ISO;
427#endif
428 else {
429 errx(1, "%s: unknown address family", optarg);
430 }
431 break;
b8dff150 432#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
b7080c8e
A
433 case 'g':
434 gflag = 1;
435 break;
b8dff150 436#endif
b7080c8e
A
437 case 'I': {
438 char *cp;
439
440 iflag = 1;
441 for (cp = interface = optarg; isalpha(*cp); cp++)
442 continue;
443 unit = atoi(cp);
444 break;
445 }
446 case 'i':
447 iflag = 1;
448 break;
7ba0088d
A
449 case 'l':
450 lflag = 1;
451 break;
452 case 'L':
453 Lflag = 1;
454 break;
b7080c8e 455 case 'm':
b8dff150 456 mflag++;
b7080c8e
A
457 break;
458 case 'n':
459 nflag = 1;
460 break;
461 case 'p':
462 if ((tp = name2protox(optarg)) == NULL) {
463 errx(1,
464 "%s: unknown or uninstrumented protocol",
465 optarg);
466 }
467 pflag = 1;
468 break;
469 case 'r':
470 rflag = 1;
471 break;
472 case 's':
473 ++sflag;
474 break;
475 case 't':
476 tflag = 1;
477 break;
478 case 'u':
479 af = AF_UNIX;
480 break;
7ba0088d
A
481 case 'W':
482 Wflag = 1;
483 break;
b7080c8e
A
484 case 'w':
485 interval = atoi(optarg);
486 iflag = 1;
487 break;
488 case '?':
489 default:
490 usage();
491 }
492 argv += optind;
493 argc -= optind;
494
495#define BACKWARD_COMPATIBILITY
496#ifdef BACKWARD_COMPATIBILITY
497 if (*argv) {
498 if (isdigit(**argv)) {
499 interval = atoi(*argv);
500 if (interval <= 0)
501 usage();
502 ++argv;
503 iflag = 1;
504 }
b7080c8e
A
505 }
506#endif
507
b7080c8e 508 if (mflag) {
2b484d24 509 mbpr();
b7080c8e
A
510 exit(0);
511 }
512#if 0
513 /*
514 * Keep file descriptors open to avoid overhead
515 * of open/close on each call to get* routines.
516 */
517 sethostent(1);
518 setnetent(1);
519#else
520 /*
521 * This does not make sense any more with DNS being default over
522 * the files. Doing a setXXXXent(1) causes a tcp connection to be
523 * used for the queries, which is slower.
524 */
525#endif
7ba0088d 526 if (iflag && !sflag) {
2b484d24 527 intpr(NULL);
b7080c8e
A
528 exit(0);
529 }
530 if (rflag) {
b7080c8e 531 if (sflag)
2b484d24 532 rt_stats();
b7080c8e
A
533 else
534 routepr(nl[N_RTREE].n_value);
535 exit(0);
536 }
b8dff150 537#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
b7080c8e 538 if (gflag) {
7ba0088d
A
539 if (sflag) {
540 if (af == AF_INET || af == AF_UNSPEC)
2b484d24 541 mrt_stats();
7ba0088d
A
542#ifdef INET6
543 if (af == AF_INET6 || af == AF_UNSPEC)
2b484d24 544 mrt6_stats();
7ba0088d
A
545#endif
546 } else {
547 if (af == AF_INET || af == AF_UNSPEC)
2b484d24 548 mroutepr();
7ba0088d
A
549#ifdef INET6
550 if (af == AF_INET6 || af == AF_UNSPEC)
2b484d24 551 mroute6pr();
7ba0088d 552#endif
b7080c8e 553 }
b8dff150 554 ifmalist_dump();
7ba0088d 555 exit(0);
b7080c8e 556 }
b8dff150 557#endif
b7080c8e 558
7ba0088d
A
559 if (tp) {
560 printproto(tp, tp->pr_name);
561 exit(0);
562 }
563 if (af == AF_INET || af == AF_UNSPEC)
564 for (tp = protox; tp->pr_name; tp++)
565 printproto(tp, tp->pr_name);
566#ifdef INET6
567 if (af == AF_INET6 || af == AF_UNSPEC)
568 for (tp = ip6protox; tp->pr_name; tp++)
569 printproto(tp, tp->pr_name);
570#endif /*INET6*/
571#ifdef IPSEC
572 if (af == PF_KEY || af == AF_UNSPEC)
573 for (tp = pfkeyprotox; tp->pr_name; tp++)
574 printproto(tp, tp->pr_name);
575#endif /*IPSEC*/
576#ifndef __APPLE__
b7080c8e 577 if (af == AF_IPX || af == AF_UNSPEC) {
b7080c8e
A
578 for (tp = ipxprotox; tp->pr_name; tp++)
579 printproto(tp, tp->pr_name);
580 }
b7080c8e
A
581 if (af == AF_APPLETALK || af == AF_UNSPEC)
582 for (tp = atalkprotox; tp->pr_name; tp++)
583 printproto(tp, tp->pr_name);
7ba0088d
A
584 if (af == AF_NETGRAPH || af == AF_UNSPEC)
585 for (tp = netgraphprotox; tp->pr_name; tp++)
586 printproto(tp, tp->pr_name);
b7080c8e
A
587#endif
588#ifdef NS
589 if (af == AF_NS || af == AF_UNSPEC)
590 for (tp = nsprotox; tp->pr_name; tp++)
591 printproto(tp, tp->pr_name);
592#endif
593#ifdef ISO
594 if (af == AF_ISO || af == AF_UNSPEC)
595 for (tp = isoprotox; tp->pr_name; tp++)
596 printproto(tp, tp->pr_name);
597#endif
7ba0088d 598 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
b7080c8e 599 unixpr();
ac2f15b3
A
600#ifdef SRVCACHE
601 _serv_cache_close();
602#endif
b7080c8e
A
603 exit(0);
604}
605
606/*
607 * Print out protocol statistics or control blocks (per sflag).
608 * If the interface was not specifically requested, and the symbol
609 * is not in the namelist, ignore this one.
610 */
611static void
612printproto(tp, name)
613 register struct protox *tp;
614 char *name;
615{
7ba0088d 616 void (*pr)(u_long, char *, int);
b7080c8e
A
617 u_long off;
618
619 if (sflag) {
b8dff150 620 if (iflag && !pflag) {
7ba0088d 621 if (tp->pr_istats)
2b484d24 622 intpr(tp->pr_istats);
b8dff150 623 else
7ba0088d
A
624 printf("%s: no per-interface stats routine\n",
625 tp->pr_name);
626 return;
627 }
628 else {
629 pr = tp->pr_stats;
630 if (!pr) {
631 if (pflag)
632 printf("%s: no stats routine\n",
633 tp->pr_name);
634 return;
635 }
636 off = tp->pr_usesysctl ? tp->pr_usesysctl
637 : nl[tp->pr_sindex].n_value;
638 }
b7080c8e
A
639 } else {
640 pr = tp->pr_cblocks;
7ba0088d
A
641 if (!pr) {
642 if (pflag)
643 printf("%s: no PCB routine\n", tp->pr_name);
644 return;
645 }
b7080c8e
A
646 off = tp->pr_usesysctl ? tp->pr_usesysctl
647 : nl[tp->pr_index].n_value;
648 }
b8dff150
A
649 if (pr != NULL && (off || af != AF_UNSPEC)) {
650 if (sflag && iflag && pflag)
651 intervalpr(pr, off, name, af);
652 else
653 (*pr)(off, name, af);
654 } else {
2b484d24 655 printf("### no stats for %s\n", name);
b7080c8e 656 }
b7080c8e
A
657}
658
659char *
7ba0088d 660plural(int n)
b7080c8e
A
661{
662 return (n != 1 ? "s" : "");
663}
664
665char *
7ba0088d 666plurales(int n)
b7080c8e
A
667{
668 return (n != 1 ? "es" : "");
669}
670
671/*
672 * Find the protox for the given "well-known" name.
673 */
674static struct protox *
7ba0088d 675knownname(char *name)
b7080c8e
A
676{
677 struct protox **tpp, *tp;
678
679 for (tpp = protoprotox; *tpp; tpp++)
680 for (tp = *tpp; tp->pr_name; tp++)
681 if (strcmp(tp->pr_name, name) == 0)
682 return (tp);
683 return (NULL);
684}
685
686/*
687 * Find the protox corresponding to name.
688 */
689static struct protox *
7ba0088d 690name2protox(char *name)
b7080c8e
A
691{
692 struct protox *tp;
693 char **alias; /* alias from p->aliases */
694 struct protoent *p;
695
696 /*
697 * Try to find the name in the list of "well-known" names. If that
698 * fails, check if name is an alias for an Internet protocol.
699 */
7ba0088d 700 if ((tp = knownname(name)) != NULL)
b7080c8e
A
701 return (tp);
702
703 setprotoent(1); /* make protocol lookup cheaper */
7ba0088d 704 while ((p = getprotoent()) != NULL) {
b7080c8e
A
705 /* assert: name not same as p->name */
706 for (alias = p->p_aliases; *alias; alias++)
707 if (strcmp(name, *alias) == 0) {
708 endprotoent();
709 return (knownname(p->p_name));
710 }
711 }
712 endprotoent();
713 return (NULL);
714}
715
b8dff150
A
716#define NETSTAT_USAGE "\
717Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
718 netstat [-gilns] [-f address_family]\n\
719 netstat -i | -I interface [-w wait] [-abdgt]\n\
720 netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
721 netstat -i | -I interface -s [-f address_family | -p protocol]\n\
722 netstat -m [-m]\n\
723 netstat -r [-Aaln] [-f address_family]\n\
724 netstat -rs [-s]\n\
725"
726
b7080c8e 727static void
7ba0088d 728usage(void)
b7080c8e 729{
b8dff150 730 (void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
b7080c8e
A
731 exit(1);
732}
b8dff150 733