]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/main.c
network_cmds-115.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 *
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.
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,
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."
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[] =
7ba0088d 68 "$Id: main.c,v 1.4 2002/03/05 20:35:14 lindak Exp $";
b7080c8e
A
69#endif /* not lint */
70
71#include <sys/param.h>
72#include <sys/file.h>
73#include <sys/protosw.h>
74#include <sys/socket.h>
75
76#include <netinet/in.h>
77
78#include <ctype.h>
79#include <err.h>
80#include <errno.h>
81#include <kvm.h>
82#include <limits.h>
83#include <netdb.h>
84#include <nlist.h>
85#include <paths.h>
86#include <stdio.h>
87#include <stdlib.h>
88#include <string.h>
89#include <unistd.h>
90#include "netstat.h"
91#include <sys/types.h>
92#include <sys/sysctl.h>
93
94
95/*
96 * ----------------------------------------------------------------------------
97 * "THE BEER-WARE LICENSE" (Revision 42):
98 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
99 * can do whatever you want with this stuff. If we meet some day, and you think
100 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
101 * ----------------------------------------------------------------------------
102 *
7ba0088d 103 * $Id: main.c,v 1.4 2002/03/05 20:35:14 lindak Exp $
b7080c8e
A
104 *
105 */
106
107
108static struct nlist nl[] = {
109#define N_IFNET 0
110 { "_ifnet" },
111#define N_IMP 1
112 { "_imp_softc" },
113#define N_RTSTAT 2
114 { "_rtstat" },
115#define N_UNIXSW 3
116 { "_localsw" },
117#define N_IDP 4
118 { "_nspcb"},
119#define N_IDPSTAT 5
120 { "_idpstat"},
121#define N_SPPSTAT 6
122 { "_spp_istat"},
123#define N_NSERR 7
124 { "_ns_errstat"},
125#define N_CLNPSTAT 8
126 { "_clnp_stat"},
127#define IN_NOTUSED 9
128 { "_tp_inpcb" },
129#define ISO_TP 10
130 { "_tp_refinfo" },
131#define N_TPSTAT 11
132 { "_tp_stat" },
133#define N_ESISSTAT 12
134 { "_esis_stat"},
135#define N_NIMP 13
136 { "_nimp"},
137#define N_RTREE 14
138 { "_rt_tables"},
139#define N_CLTP 15
140 { "_cltb"},
141#define N_CLTPSTAT 16
142 { "_cltpstat"},
143#define N_NFILE 17
144 { "_nfile" },
145#define N_FILE 18
146 { "_file" },
147#define N_MRTSTAT 19
148 { "_mrtstat" },
149#define N_MFCTABLE 20
150 { "_mfctable" },
151#define N_VIFTABLE 21
152 { "_viftable" },
153#define N_IPX 22
154 { "_ipxpcb"},
155#define N_IPXSTAT 23
156 { "_ipxstat"},
157#define N_SPXSTAT 24
158 { "_spx_istat"},
159#define N_DDPSTAT 25
160 { "_ddpstat"},
161#define N_DDPCB 26
162 { "_ddpcb"},
7ba0088d
A
163#define N_NGSOCKS 27
164 { "_ngsocklist"},
165#define N_IP6STAT 28
166 { "_ip6stat" },
167#define N_ICMP6STAT 29
168 { "_icmp6stat" },
169#define N_IPSECSTAT 30
170 { "_ipsecstat" },
171#define N_IPSEC6STAT 31
172 { "_ipsec6stat" },
173#define N_PIM6STAT 32
174 { "_pim6stat" },
175#define N_MRT6PROTO 33
176 { "_ip6_mrtproto" },
177#define N_MRT6STAT 34
178 { "_mrt6stat" },
179#define N_MF6CTABLE 35
180 { "_mf6ctable" },
181#define N_MIF6TABLE 36
182 { "_mif6table" },
183#define N_PFKEYSTAT 37
184 { "_pfkeystat" },
185#define N_MBSTAT 38
186 { "_mbstat" },
187#define N_MBTYPES 39
188 { "_mbtypes" },
189#define N_NMBCLUSTERS 40
190 { "_nmbclusters" },
191#define N_NMBUFS 41
192 { "_nmbufs" },
193#define N_RTTRASH 42
194 { "_rttrash" },
b7080c8e
A
195 { "" },
196};
197
198
199
200struct protox {
201 u_char pr_index; /* index into nlist of cb head */
202 u_char pr_sindex; /* index into nlist of stat block */
203 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
7ba0088d
A
204 void (*pr_cblocks)(u_long, char *, int);
205 /* control blocks printing routine */
206 void (*pr_stats)(u_long, char *, int);
207 /* statistics printing routine */
208 void (*pr_istats)(char *); /* per/if statistics printing routine */
b7080c8e
A
209 char *pr_name; /* well-known name */
210 int pr_usesysctl; /* true if we use sysctl, not kvm */
211} protox[] = {
212 { -1, -1, 1, protopr,
7ba0088d 213 tcp_stats, NULL, "tcp", IPPROTO_TCP },
b7080c8e 214 { -1, -1, 1, protopr,
7ba0088d 215 udp_stats, NULL, "udp", IPPROTO_UDP },
b7080c8e 216 { -1, -1, 1, protopr,
7ba0088d 217 NULL, NULL, "divert",IPPROTO_DIVERT },
b7080c8e 218 { -1, -1, 1, protopr,
7ba0088d 219 ip_stats, NULL, "ip", IPPROTO_RAW },
b7080c8e 220 { -1, -1, 1, protopr,
7ba0088d 221 icmp_stats, NULL, "icmp", IPPROTO_ICMP },
b7080c8e 222 { -1, -1, 1, protopr,
7ba0088d
A
223 igmp_stats, NULL, "igmp", IPPROTO_IGMP },
224#ifdef IPSEC
225 { -1, N_IPSECSTAT, 1, 0,
226 ipsec_stats, NULL, "ipsec", 0},
227#endif
228#if 0
229 { -1, -1, 1, 0,
230 bdg_stats, NULL, "bdg", 1 /* bridging... */ },
231#endif
232 { -1, -1, 0, 0,
233 0, NULL, 0 }
234};
235
236#ifdef INET6
237struct protox ip6protox[] = {
238 { -1, -1, 1, protopr,
239 tcp_stats, NULL, "tcp", IPPROTO_TCP },
240 { -1, -1, 1, protopr,
241 udp_stats, NULL, "udp", IPPROTO_UDP },
242 { -1, N_IP6STAT, 1, protopr,
243 ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW },
244 { -1, N_ICMP6STAT, 1, protopr,
245 icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 },
246#ifdef IPSEC
247 { -1, N_IPSEC6STAT, 1, 0,
248 ipsec_stats, NULL, "ipsec6",0 },
249#endif
250#ifdef notyet
251 { -1, N_PIM6STAT, 1, 0,
252 pim6_stats, NULL, "pim6", 0 },
253#endif
254 { -1, -1, 1, 0,
255 rip6_stats, NULL, "rip6", 0 },
256#if 0
257 { -1, -1, 1, 0,
258 bdg_stats, NULL, "bdg", 1 /* bridging... */ },
259#endif
b7080c8e 260 { -1, -1, 0, 0,
7ba0088d 261 0, NULL, 0, 0 }
b7080c8e 262};
7ba0088d 263#endif /*INET6*/
b7080c8e 264
7ba0088d
A
265#ifdef IPSEC
266struct protox pfkeyprotox[] = {
267 { -1, N_PFKEYSTAT, 1, 0,
268 pfkey_stats, NULL, "pfkey", 0 },
269 { -1, -1, 0, 0,
270 0, NULL, 0, 0 }
271};
272#endif
273#ifndef __APPLE__
b7080c8e
A
274struct protox atalkprotox[] = {
275 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
7ba0088d 276 ddp_stats, NULL, "ddp" },
b7080c8e 277 { -1, -1, 0, 0,
7ba0088d
A
278 0, NULL, 0 }
279};
280
281struct protox netgraphprotox[] = {
282 { N_NGSOCKS, -1, 1, netgraphprotopr,
283 NULL, NULL, "ctrl" },
284 { N_NGSOCKS, -1, 1, netgraphprotopr,
285 NULL, NULL, "data" },
286 { -1, NULL, 0, 0,
287 0, NULL, 0 }
b7080c8e 288};
b7080c8e 289
b7080c8e
A
290struct protox ipxprotox[] = {
291 { N_IPX, N_IPXSTAT, 1, ipxprotopr,
7ba0088d 292 ipx_stats, NULL, "ipx", 0 },
b7080c8e 293 { N_IPX, N_SPXSTAT, 1, ipxprotopr,
7ba0088d 294 spx_stats, NULL, "spx", 0 },
b7080c8e 295 { -1, -1, 0, 0,
7ba0088d 296 0, NULL, 0, 0 }
b7080c8e
A
297};
298#endif
b7080c8e
A
299#ifdef NS
300struct protox nsprotox[] = {
301 { N_IDP, N_IDPSTAT, 1, nsprotopr,
7ba0088d 302 idp_stats, NULL, "idp" },
b7080c8e 303 { N_IDP, N_SPPSTAT, 1, nsprotopr,
7ba0088d 304 spp_stats, NULL, "spp" },
b7080c8e 305 { -1, N_NSERR, 1, 0,
7ba0088d 306 nserr_stats, NULL, "ns_err" },
b7080c8e 307 { -1, -1, 0, 0,
7ba0088d 308 0, NULL, 0 }
b7080c8e
A
309};
310#endif
311
312#ifdef ISO
313struct protox isoprotox[] = {
314 { ISO_TP, N_TPSTAT, 1, iso_protopr,
7ba0088d 315 tp_stats, NULL, "tp" },
b7080c8e 316 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
7ba0088d 317 cltp_stats, NULL, "cltp" },
b7080c8e 318 { -1, N_CLNPSTAT, 1, 0,
7ba0088d 319 clnp_stats, NULL, "clnp"},
b7080c8e 320 { -1, N_ESISSTAT, 1, 0,
7ba0088d 321 esis_stats, NULL, "esis"},
b7080c8e 322 { -1, -1, 0, 0,
7ba0088d 323 0, NULL, 0 }
b7080c8e
A
324};
325#endif
326
7ba0088d
A
327struct protox *protoprotox[] = {
328 protox,
329#ifdef INET6
330 ip6protox,
b7080c8e 331#endif
7ba0088d
A
332#ifdef IPSEC
333 pfkeyprotox,
334#endif
335#ifndef __APPLE__
336 ipxprotox, atalkprotox,
b7080c8e 337#endif
b7080c8e
A
338#ifdef NS
339 nsprotox,
340#endif
341#ifdef ISO
342 isoprotox,
343#endif
344 NULL };
345
7ba0088d
A
346static void printproto (struct protox *, char *);
347static void usage (void);
348static struct protox *name2protox (char *);
349static struct protox *knownname (char *);
b7080c8e
A
350
351static kvm_t *kvmd;
7ba0088d
A
352static char *nlistf = NULL, *memf = NULL;
353
354int Aflag; /* show addresses of protocol control block */
355int aflag; /* show all sockets (including servers) */
356int bflag; /* show i/f total bytes in/out */
357int dflag; /* show i/f dropped packets */
358int gflag; /* show group (multicast) routing or stats */
359int iflag; /* show interfaces */
360int lflag; /* show routing table with use and ref */
361int Lflag; /* show size of listen queues */
362int mflag; /* show memory stats */
363int nflag; /* show addresses numerically */
364static int pflag; /* show given protocol */
365int rflag; /* show routing tables (or routing stats) */
366int sflag; /* show protocol statistics */
367int tflag; /* show i/f watchdog timers */
368int Wflag; /* wide display */
369
370int interval; /* repeat interval for i/f stats */
371
372char *interface; /* desired i/f for stats, or NULL for all i/fs */
373int unit; /* unit number for above */
374
375int af; /* address family */
b7080c8e
A
376
377int
378main(argc, argv)
379 int argc;
380 char *argv[];
381{
7ba0088d 382 register struct protox *tp = NULL; /* for printing cblocks & stats */
b7080c8e
A
383 int ch;
384
385 af = AF_UNSPEC;
386
7ba0088d 387 while ((ch = getopt(argc, argv, "Aabdf:gI:iLlM:mN:np:rstuWw:")) != -1)
b7080c8e
A
388 switch(ch) {
389 case 'A':
390 Aflag = 1;
391 break;
392 case 'a':
393 aflag = 1;
394 break;
395 case 'b':
396 bflag = 1;
397 break;
398 case 'd':
399 dflag = 1;
400 break;
401 case 'f':
402#ifdef NS
403 if (strcmp(optarg, "ns") == 0)
404 af = AF_NS;
405 else
406#endif
407 if (strcmp(optarg, "ipx") == 0)
408 af = AF_IPX;
409 else if (strcmp(optarg, "inet") == 0)
410 af = AF_INET;
7ba0088d
A
411#ifdef INET6
412 else if (strcmp(optarg, "inet6") == 0)
413 af = AF_INET6;
414#endif /*INET6*/
415#ifdef INET6
416 else if (strcmp(optarg, "pfkey") == 0)
417 af = PF_KEY;
418#endif /*INET6*/
b7080c8e
A
419 else if (strcmp(optarg, "unix") == 0)
420 af = AF_UNIX;
7ba0088d 421#ifndef __APPLE__
b7080c8e
A
422 else if (strcmp(optarg, "atalk") == 0)
423 af = AF_APPLETALK;
7ba0088d
A
424 else if (strcmp(optarg, "ng") == 0
425 || strcmp(optarg, "netgraph") == 0)
426 af = AF_NETGRAPH;
427#endif
b7080c8e
A
428#ifdef ISO
429 else if (strcmp(optarg, "iso") == 0)
430 af = AF_ISO;
431#endif
432 else {
433 errx(1, "%s: unknown address family", optarg);
434 }
435 break;
436 case 'g':
437 gflag = 1;
438 break;
439 case 'I': {
440 char *cp;
441
442 iflag = 1;
443 for (cp = interface = optarg; isalpha(*cp); cp++)
444 continue;
445 unit = atoi(cp);
446 break;
447 }
448 case 'i':
449 iflag = 1;
450 break;
7ba0088d
A
451 case 'l':
452 lflag = 1;
453 break;
454 case 'L':
455 Lflag = 1;
456 break;
b7080c8e
A
457 case 'M':
458 memf = optarg;
459 break;
460 case 'm':
461 mflag = 1;
462 break;
463 case 'N':
464 nlistf = optarg;
465 break;
466 case 'n':
467 nflag = 1;
468 break;
469 case 'p':
470 if ((tp = name2protox(optarg)) == NULL) {
471 errx(1,
472 "%s: unknown or uninstrumented protocol",
473 optarg);
474 }
475 pflag = 1;
476 break;
477 case 'r':
478 rflag = 1;
479 break;
480 case 's':
481 ++sflag;
482 break;
483 case 't':
484 tflag = 1;
485 break;
486 case 'u':
487 af = AF_UNIX;
488 break;
7ba0088d
A
489 case 'W':
490 Wflag = 1;
491 break;
b7080c8e
A
492 case 'w':
493 interval = atoi(optarg);
494 iflag = 1;
495 break;
496 case '?':
497 default:
498 usage();
499 }
500 argv += optind;
501 argc -= optind;
502
503#define BACKWARD_COMPATIBILITY
504#ifdef BACKWARD_COMPATIBILITY
505 if (*argv) {
506 if (isdigit(**argv)) {
507 interval = atoi(*argv);
508 if (interval <= 0)
509 usage();
510 ++argv;
511 iflag = 1;
512 }
513 if (*argv) {
514 nlistf = *argv;
515 if (*++argv)
516 memf = *argv;
517 }
518 }
519#endif
520
521 /*
522 * Discard setgid privileges if not the running kernel so that bad
523 * guys can't print interesting stuff from kernel memory.
524 */
525 if (nlistf != NULL || memf != NULL)
526 setgid(getgid());
527
528 if (mflag) {
7ba0088d
A
529 //if (memf != NULL) {
530 if (kread(0, 0, 0) == 0)
531 mbpr(nl[N_MBSTAT].n_value);
532 //mbpr(nl[N_MBSTAT].n_value,
533 // nl[N_MBTYPES].n_value,
534 // nl[N_NMBCLUSTERS].n_value,
535 // nl[N_NMBUFS].n_value);
536 //} else
537 // mbpr(0, 0, 0, 0);
538 //mbpr(0) ;
b7080c8e
A
539 exit(0);
540 }
541#if 0
542 /*
543 * Keep file descriptors open to avoid overhead
544 * of open/close on each call to get* routines.
545 */
546 sethostent(1);
547 setnetent(1);
548#else
549 /*
550 * This does not make sense any more with DNS being default over
551 * the files. Doing a setXXXXent(1) causes a tcp connection to be
552 * used for the queries, which is slower.
553 */
554#endif
7ba0088d 555 if (iflag && !sflag) {
b7080c8e 556 kread(0, 0, 0);
7ba0088d 557 intpr(interval, nl[N_IFNET].n_value, NULL);
b7080c8e
A
558 exit(0);
559 }
560 if (rflag) {
561 kread(0, 0, 0);
562 if (sflag)
7ba0088d 563 rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
b7080c8e
A
564 else
565 routepr(nl[N_RTREE].n_value);
566 exit(0);
567 }
568 if (gflag) {
569 kread(0, 0, 0);
7ba0088d
A
570 if (sflag) {
571 if (af == AF_INET || af == AF_UNSPEC)
572 mrt_stats(nl[N_MRTSTAT].n_value);
573#ifdef INET6
574 if (af == AF_INET6 || af == AF_UNSPEC)
575 mrt6_stats(nl[N_MRT6STAT].n_value);
576#endif
577 } else {
578 if (af == AF_INET || af == AF_UNSPEC)
579 mroutepr(nl[N_MFCTABLE].n_value,
580 nl[N_VIFTABLE].n_value);
581#ifdef INET6
582 if (af == AF_INET6 || af == AF_UNSPEC)
583 mroute6pr(nl[N_MF6CTABLE].n_value,
584 nl[N_MIF6TABLE].n_value);
585#endif
b7080c8e 586 }
7ba0088d 587 exit(0);
b7080c8e
A
588 }
589
7ba0088d
A
590 kread(0, 0, 0);
591 if (tp) {
592 printproto(tp, tp->pr_name);
593 exit(0);
594 }
595 if (af == AF_INET || af == AF_UNSPEC)
596 for (tp = protox; tp->pr_name; tp++)
597 printproto(tp, tp->pr_name);
598#ifdef INET6
599 if (af == AF_INET6 || af == AF_UNSPEC)
600 for (tp = ip6protox; tp->pr_name; tp++)
601 printproto(tp, tp->pr_name);
602#endif /*INET6*/
603#ifdef IPSEC
604 if (af == PF_KEY || af == AF_UNSPEC)
605 for (tp = pfkeyprotox; tp->pr_name; tp++)
606 printproto(tp, tp->pr_name);
607#endif /*IPSEC*/
608#ifndef __APPLE__
b7080c8e
A
609 if (af == AF_IPX || af == AF_UNSPEC) {
610 kread(0, 0, 0);
611 for (tp = ipxprotox; tp->pr_name; tp++)
612 printproto(tp, tp->pr_name);
613 }
b7080c8e
A
614 if (af == AF_APPLETALK || af == AF_UNSPEC)
615 for (tp = atalkprotox; tp->pr_name; tp++)
616 printproto(tp, tp->pr_name);
7ba0088d
A
617 if (af == AF_NETGRAPH || af == AF_UNSPEC)
618 for (tp = netgraphprotox; tp->pr_name; tp++)
619 printproto(tp, tp->pr_name);
b7080c8e
A
620#endif
621#ifdef NS
622 if (af == AF_NS || af == AF_UNSPEC)
623 for (tp = nsprotox; tp->pr_name; tp++)
624 printproto(tp, tp->pr_name);
625#endif
626#ifdef ISO
627 if (af == AF_ISO || af == AF_UNSPEC)
628 for (tp = isoprotox; tp->pr_name; tp++)
629 printproto(tp, tp->pr_name);
630#endif
7ba0088d 631 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
b7080c8e
A
632 unixpr();
633 exit(0);
634}
635
636/*
637 * Print out protocol statistics or control blocks (per sflag).
638 * If the interface was not specifically requested, and the symbol
639 * is not in the namelist, ignore this one.
640 */
641static void
642printproto(tp, name)
643 register struct protox *tp;
644 char *name;
645{
7ba0088d 646 void (*pr)(u_long, char *, int);
b7080c8e
A
647 u_long off;
648
649 if (sflag) {
7ba0088d
A
650 if (iflag) {
651 if (tp->pr_istats)
652 intpr(interval, nl[N_IFNET].n_value,
653 tp->pr_istats);
654 else if (pflag)
655 printf("%s: no per-interface stats routine\n",
656 tp->pr_name);
657 return;
658 }
659 else {
660 pr = tp->pr_stats;
661 if (!pr) {
662 if (pflag)
663 printf("%s: no stats routine\n",
664 tp->pr_name);
665 return;
666 }
667 off = tp->pr_usesysctl ? tp->pr_usesysctl
668 : nl[tp->pr_sindex].n_value;
669 }
b7080c8e
A
670 } else {
671 pr = tp->pr_cblocks;
7ba0088d
A
672 if (!pr) {
673 if (pflag)
674 printf("%s: no PCB routine\n", tp->pr_name);
675 return;
676 }
b7080c8e
A
677 off = tp->pr_usesysctl ? tp->pr_usesysctl
678 : nl[tp->pr_index].n_value;
679 }
680 if (pr != NULL && (off || af != AF_UNSPEC))
7ba0088d 681 (*pr)(off, name, af);
b7080c8e
A
682}
683
684/*
685 * Read kernel memory, return 0 on success.
686 */
687int
7ba0088d 688kread(u_long addr, char *buf, int size)
b7080c8e
A
689{
690 if (kvmd == 0) {
691 /*
692 * XXX.
693 */
694 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
695 if (kvmd != NULL) {
696 if (kvm_nlist(kvmd, nl) < 0) {
697 if(nlistf)
698 errx(1, "%s: kvm_nlist: %s", nlistf,
699 kvm_geterr(kvmd));
700 else
701 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
702 }
703
704 if (nl[0].n_type == 0) {
705 if(nlistf)
706 errx(1, "%s: no namelist", nlistf);
707 else
708 errx(1, "no namelist");
709 }
710 } else {
711 warnx("kvm not available");
712 return(-1);
713 }
714 }
715 if (!buf)
716 return (0);
717 if (kvm_read(kvmd, addr, buf, size) != size) {
718 warnx("%s", kvm_geterr(kvmd));
719 return (-1);
720 }
721 return (0);
722}
723
724char *
7ba0088d 725plural(int n)
b7080c8e
A
726{
727 return (n != 1 ? "s" : "");
728}
729
730char *
7ba0088d 731plurales(int n)
b7080c8e
A
732{
733 return (n != 1 ? "es" : "");
734}
735
736/*
737 * Find the protox for the given "well-known" name.
738 */
739static struct protox *
7ba0088d 740knownname(char *name)
b7080c8e
A
741{
742 struct protox **tpp, *tp;
743
744 for (tpp = protoprotox; *tpp; tpp++)
745 for (tp = *tpp; tp->pr_name; tp++)
746 if (strcmp(tp->pr_name, name) == 0)
747 return (tp);
748 return (NULL);
749}
750
751/*
752 * Find the protox corresponding to name.
753 */
754static struct protox *
7ba0088d 755name2protox(char *name)
b7080c8e
A
756{
757 struct protox *tp;
758 char **alias; /* alias from p->aliases */
759 struct protoent *p;
760
761 /*
762 * Try to find the name in the list of "well-known" names. If that
763 * fails, check if name is an alias for an Internet protocol.
764 */
7ba0088d 765 if ((tp = knownname(name)) != NULL)
b7080c8e
A
766 return (tp);
767
768 setprotoent(1); /* make protocol lookup cheaper */
7ba0088d 769 while ((p = getprotoent()) != NULL) {
b7080c8e
A
770 /* assert: name not same as p->name */
771 for (alias = p->p_aliases; *alias; alias++)
772 if (strcmp(name, *alias) == 0) {
773 endprotoent();
774 return (knownname(p->p_name));
775 }
776 }
777 endprotoent();
778 return (NULL);
779}
780
781static void
7ba0088d 782usage(void)
b7080c8e
A
783{
784 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
785"usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
786" netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
787" netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
7ba0088d 788" netstat -m [-M core] [-N system]",
b7080c8e
A
789" netstat [-M core] [-N system] [-p protocol]");
790 exit(1);
791}