]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/main.c
network_cmds-115.2.tar.gz
[apple/network_cmds.git] / netstat.tproj / main.c
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
58 char 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
65 static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
66 #endif
67 static const char rcsid[] =
68 "$Id: main.c,v 1.4 2002/03/05 20:35:14 lindak Exp $";
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 *
103 * $Id: main.c,v 1.4 2002/03/05 20:35:14 lindak Exp $
104 *
105 */
106
107
108 static 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"},
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" },
195 { "" },
196 };
197
198
199
200 struct 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 */
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 */
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,
213 tcp_stats, NULL, "tcp", IPPROTO_TCP },
214 { -1, -1, 1, protopr,
215 udp_stats, NULL, "udp", IPPROTO_UDP },
216 { -1, -1, 1, protopr,
217 NULL, NULL, "divert",IPPROTO_DIVERT },
218 { -1, -1, 1, protopr,
219 ip_stats, NULL, "ip", IPPROTO_RAW },
220 { -1, -1, 1, protopr,
221 icmp_stats, NULL, "icmp", IPPROTO_ICMP },
222 { -1, -1, 1, protopr,
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
237 struct 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
260 { -1, -1, 0, 0,
261 0, NULL, 0, 0 }
262 };
263 #endif /*INET6*/
264
265 #ifdef IPSEC
266 struct 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__
274 struct protox atalkprotox[] = {
275 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
276 ddp_stats, NULL, "ddp" },
277 { -1, -1, 0, 0,
278 0, NULL, 0 }
279 };
280
281 struct 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 }
288 };
289
290 struct protox ipxprotox[] = {
291 { N_IPX, N_IPXSTAT, 1, ipxprotopr,
292 ipx_stats, NULL, "ipx", 0 },
293 { N_IPX, N_SPXSTAT, 1, ipxprotopr,
294 spx_stats, NULL, "spx", 0 },
295 { -1, -1, 0, 0,
296 0, NULL, 0, 0 }
297 };
298 #endif
299 #ifdef NS
300 struct protox nsprotox[] = {
301 { N_IDP, N_IDPSTAT, 1, nsprotopr,
302 idp_stats, NULL, "idp" },
303 { N_IDP, N_SPPSTAT, 1, nsprotopr,
304 spp_stats, NULL, "spp" },
305 { -1, N_NSERR, 1, 0,
306 nserr_stats, NULL, "ns_err" },
307 { -1, -1, 0, 0,
308 0, NULL, 0 }
309 };
310 #endif
311
312 #ifdef ISO
313 struct protox isoprotox[] = {
314 { ISO_TP, N_TPSTAT, 1, iso_protopr,
315 tp_stats, NULL, "tp" },
316 { N_CLTP, N_CLTPSTAT, 1, iso_protopr,
317 cltp_stats, NULL, "cltp" },
318 { -1, N_CLNPSTAT, 1, 0,
319 clnp_stats, NULL, "clnp"},
320 { -1, N_ESISSTAT, 1, 0,
321 esis_stats, NULL, "esis"},
322 { -1, -1, 0, 0,
323 0, NULL, 0 }
324 };
325 #endif
326
327 struct protox *protoprotox[] = {
328 protox,
329 #ifdef INET6
330 ip6protox,
331 #endif
332 #ifdef IPSEC
333 pfkeyprotox,
334 #endif
335 #ifndef __APPLE__
336 ipxprotox, atalkprotox,
337 #endif
338 #ifdef NS
339 nsprotox,
340 #endif
341 #ifdef ISO
342 isoprotox,
343 #endif
344 NULL };
345
346 static void printproto (struct protox *, char *);
347 static void usage (void);
348 static struct protox *name2protox (char *);
349 static struct protox *knownname (char *);
350
351 static kvm_t *kvmd;
352 static char *nlistf = NULL, *memf = NULL;
353
354 int Aflag; /* show addresses of protocol control block */
355 int aflag; /* show all sockets (including servers) */
356 int bflag; /* show i/f total bytes in/out */
357 int dflag; /* show i/f dropped packets */
358 int gflag; /* show group (multicast) routing or stats */
359 int iflag; /* show interfaces */
360 int lflag; /* show routing table with use and ref */
361 int Lflag; /* show size of listen queues */
362 int mflag; /* show memory stats */
363 int nflag; /* show addresses numerically */
364 static int pflag; /* show given protocol */
365 int rflag; /* show routing tables (or routing stats) */
366 int sflag; /* show protocol statistics */
367 int tflag; /* show i/f watchdog timers */
368 int Wflag; /* wide display */
369
370 int interval; /* repeat interval for i/f stats */
371
372 char *interface; /* desired i/f for stats, or NULL for all i/fs */
373 int unit; /* unit number for above */
374
375 int af; /* address family */
376
377 int
378 main(argc, argv)
379 int argc;
380 char *argv[];
381 {
382 register struct protox *tp = NULL; /* for printing cblocks & stats */
383 int ch;
384
385 af = AF_UNSPEC;
386
387 while ((ch = getopt(argc, argv, "Aabdf:gI:iLlM:mN:np:rstuWw:")) != -1)
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;
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*/
419 else if (strcmp(optarg, "unix") == 0)
420 af = AF_UNIX;
421 #ifndef __APPLE__
422 else if (strcmp(optarg, "atalk") == 0)
423 af = AF_APPLETALK;
424 else if (strcmp(optarg, "ng") == 0
425 || strcmp(optarg, "netgraph") == 0)
426 af = AF_NETGRAPH;
427 #endif
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;
451 case 'l':
452 lflag = 1;
453 break;
454 case 'L':
455 Lflag = 1;
456 break;
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;
489 case 'W':
490 Wflag = 1;
491 break;
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) {
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) ;
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
555 if (iflag && !sflag) {
556 kread(0, 0, 0);
557 intpr(interval, nl[N_IFNET].n_value, NULL);
558 exit(0);
559 }
560 if (rflag) {
561 kread(0, 0, 0);
562 if (sflag)
563 rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
564 else
565 routepr(nl[N_RTREE].n_value);
566 exit(0);
567 }
568 if (gflag) {
569 kread(0, 0, 0);
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
586 }
587 exit(0);
588 }
589
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__
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 }
614 if (af == AF_APPLETALK || af == AF_UNSPEC)
615 for (tp = atalkprotox; tp->pr_name; tp++)
616 printproto(tp, tp->pr_name);
617 if (af == AF_NETGRAPH || af == AF_UNSPEC)
618 for (tp = netgraphprotox; tp->pr_name; tp++)
619 printproto(tp, tp->pr_name);
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
631 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
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 */
641 static void
642 printproto(tp, name)
643 register struct protox *tp;
644 char *name;
645 {
646 void (*pr)(u_long, char *, int);
647 u_long off;
648
649 if (sflag) {
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 }
670 } else {
671 pr = tp->pr_cblocks;
672 if (!pr) {
673 if (pflag)
674 printf("%s: no PCB routine\n", tp->pr_name);
675 return;
676 }
677 off = tp->pr_usesysctl ? tp->pr_usesysctl
678 : nl[tp->pr_index].n_value;
679 }
680 if (pr != NULL && (off || af != AF_UNSPEC))
681 (*pr)(off, name, af);
682 }
683
684 /*
685 * Read kernel memory, return 0 on success.
686 */
687 int
688 kread(u_long addr, char *buf, int size)
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
724 char *
725 plural(int n)
726 {
727 return (n != 1 ? "s" : "");
728 }
729
730 char *
731 plurales(int n)
732 {
733 return (n != 1 ? "es" : "");
734 }
735
736 /*
737 * Find the protox for the given "well-known" name.
738 */
739 static struct protox *
740 knownname(char *name)
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 */
754 static struct protox *
755 name2protox(char *name)
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 */
765 if ((tp = knownname(name)) != NULL)
766 return (tp);
767
768 setprotoent(1); /* make protocol lookup cheaper */
769 while ((p = getprotoent()) != NULL) {
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
781 static void
782 usage(void)
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]",
788 " netstat -m [-M core] [-N system]",
789 " netstat [-M core] [-N system] [-p protocol]");
790 exit(1);
791 }