]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/main.c
network_cmds-176.4.1.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.5 2003/07/08 22:49:49 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.5 2003/07/08 22:49:49 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 #ifdef SRVCACHE
351 extern void _serv_cache_close();
352 #endif
353
354 static kvm_t *kvmd;
355 static char *nlistf = NULL, *memf = NULL;
356
357 int Aflag; /* show addresses of protocol control block */
358 int aflag; /* show all sockets (including servers) */
359 int bflag; /* show i/f total bytes in/out */
360 int dflag; /* show i/f dropped packets */
361 int gflag; /* show group (multicast) routing or stats */
362 int iflag; /* show interfaces */
363 int lflag; /* show routing table with use and ref */
364 int Lflag; /* show size of listen queues */
365 int mflag; /* show memory stats */
366 int nflag; /* show addresses numerically */
367 static int pflag; /* show given protocol */
368 int rflag; /* show routing tables (or routing stats) */
369 int sflag; /* show protocol statistics */
370 int tflag; /* show i/f watchdog timers */
371 int Wflag; /* wide display */
372
373 int interval; /* repeat interval for i/f stats */
374
375 char *interface; /* desired i/f for stats, or NULL for all i/fs */
376 int unit; /* unit number for above */
377
378 int af; /* address family */
379
380 int
381 main(argc, argv)
382 int argc;
383 char *argv[];
384 {
385 register struct protox *tp = NULL; /* for printing cblocks & stats */
386 int ch;
387
388 af = AF_UNSPEC;
389
390 while ((ch = getopt(argc, argv, "Aabdf:gI:iLlM:mN:np:rstuWw:")) != -1)
391 switch(ch) {
392 case 'A':
393 Aflag = 1;
394 break;
395 case 'a':
396 aflag = 1;
397 break;
398 case 'b':
399 bflag = 1;
400 break;
401 case 'd':
402 dflag = 1;
403 break;
404 case 'f':
405 #ifdef NS
406 if (strcmp(optarg, "ns") == 0)
407 af = AF_NS;
408 else
409 #endif
410 if (strcmp(optarg, "ipx") == 0)
411 af = AF_IPX;
412 else if (strcmp(optarg, "inet") == 0)
413 af = AF_INET;
414 #ifdef INET6
415 else if (strcmp(optarg, "inet6") == 0)
416 af = AF_INET6;
417 #endif /*INET6*/
418 #ifdef INET6
419 else if (strcmp(optarg, "pfkey") == 0)
420 af = PF_KEY;
421 #endif /*INET6*/
422 else if (strcmp(optarg, "unix") == 0)
423 af = AF_UNIX;
424 #ifndef __APPLE__
425 else if (strcmp(optarg, "atalk") == 0)
426 af = AF_APPLETALK;
427 else if (strcmp(optarg, "ng") == 0
428 || strcmp(optarg, "netgraph") == 0)
429 af = AF_NETGRAPH;
430 #endif
431 #ifdef ISO
432 else if (strcmp(optarg, "iso") == 0)
433 af = AF_ISO;
434 #endif
435 else {
436 errx(1, "%s: unknown address family", optarg);
437 }
438 break;
439 case 'g':
440 gflag = 1;
441 break;
442 case 'I': {
443 char *cp;
444
445 iflag = 1;
446 for (cp = interface = optarg; isalpha(*cp); cp++)
447 continue;
448 unit = atoi(cp);
449 break;
450 }
451 case 'i':
452 iflag = 1;
453 break;
454 case 'l':
455 lflag = 1;
456 break;
457 case 'L':
458 Lflag = 1;
459 break;
460 case 'M':
461 memf = optarg;
462 break;
463 case 'm':
464 mflag = 1;
465 break;
466 case 'N':
467 nlistf = optarg;
468 break;
469 case 'n':
470 nflag = 1;
471 break;
472 case 'p':
473 if ((tp = name2protox(optarg)) == NULL) {
474 errx(1,
475 "%s: unknown or uninstrumented protocol",
476 optarg);
477 }
478 pflag = 1;
479 break;
480 case 'r':
481 rflag = 1;
482 break;
483 case 's':
484 ++sflag;
485 break;
486 case 't':
487 tflag = 1;
488 break;
489 case 'u':
490 af = AF_UNIX;
491 break;
492 case 'W':
493 Wflag = 1;
494 break;
495 case 'w':
496 interval = atoi(optarg);
497 iflag = 1;
498 break;
499 case '?':
500 default:
501 usage();
502 }
503 argv += optind;
504 argc -= optind;
505
506 #define BACKWARD_COMPATIBILITY
507 #ifdef BACKWARD_COMPATIBILITY
508 if (*argv) {
509 if (isdigit(**argv)) {
510 interval = atoi(*argv);
511 if (interval <= 0)
512 usage();
513 ++argv;
514 iflag = 1;
515 }
516 if (*argv) {
517 nlistf = *argv;
518 if (*++argv)
519 memf = *argv;
520 }
521 }
522 #endif
523
524 /*
525 * Discard setgid privileges if not the running kernel so that bad
526 * guys can't print interesting stuff from kernel memory.
527 */
528 if (nlistf != NULL || memf != NULL)
529 setgid(getgid());
530
531 if (mflag) {
532 //if (memf != NULL) {
533 if (kread(0, 0, 0) == 0)
534 mbpr(nl[N_MBSTAT].n_value);
535 //mbpr(nl[N_MBSTAT].n_value,
536 // nl[N_MBTYPES].n_value,
537 // nl[N_NMBCLUSTERS].n_value,
538 // nl[N_NMBUFS].n_value);
539 //} else
540 // mbpr(0, 0, 0, 0);
541 //mbpr(0) ;
542 exit(0);
543 }
544 #if 0
545 /*
546 * Keep file descriptors open to avoid overhead
547 * of open/close on each call to get* routines.
548 */
549 sethostent(1);
550 setnetent(1);
551 #else
552 /*
553 * This does not make sense any more with DNS being default over
554 * the files. Doing a setXXXXent(1) causes a tcp connection to be
555 * used for the queries, which is slower.
556 */
557 #endif
558 if (iflag && !sflag) {
559 kread(0, 0, 0);
560 intpr(interval, nl[N_IFNET].n_value, NULL);
561 exit(0);
562 }
563 if (rflag) {
564 kread(0, 0, 0);
565 if (sflag)
566 rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
567 else
568 routepr(nl[N_RTREE].n_value);
569 exit(0);
570 }
571 if (gflag) {
572 kread(0, 0, 0);
573 if (sflag) {
574 if (af == AF_INET || af == AF_UNSPEC)
575 mrt_stats(nl[N_MRTSTAT].n_value);
576 #ifdef INET6
577 if (af == AF_INET6 || af == AF_UNSPEC)
578 mrt6_stats(nl[N_MRT6STAT].n_value);
579 #endif
580 } else {
581 if (af == AF_INET || af == AF_UNSPEC)
582 mroutepr(nl[N_MFCTABLE].n_value,
583 nl[N_VIFTABLE].n_value);
584 #ifdef INET6
585 if (af == AF_INET6 || af == AF_UNSPEC)
586 mroute6pr(nl[N_MF6CTABLE].n_value,
587 nl[N_MIF6TABLE].n_value);
588 #endif
589 }
590 exit(0);
591 }
592
593 kread(0, 0, 0);
594 if (tp) {
595 printproto(tp, tp->pr_name);
596 exit(0);
597 }
598 if (af == AF_INET || af == AF_UNSPEC)
599 for (tp = protox; tp->pr_name; tp++)
600 printproto(tp, tp->pr_name);
601 #ifdef INET6
602 if (af == AF_INET6 || af == AF_UNSPEC)
603 for (tp = ip6protox; tp->pr_name; tp++)
604 printproto(tp, tp->pr_name);
605 #endif /*INET6*/
606 #ifdef IPSEC
607 if (af == PF_KEY || af == AF_UNSPEC)
608 for (tp = pfkeyprotox; tp->pr_name; tp++)
609 printproto(tp, tp->pr_name);
610 #endif /*IPSEC*/
611 #ifndef __APPLE__
612 if (af == AF_IPX || af == AF_UNSPEC) {
613 kread(0, 0, 0);
614 for (tp = ipxprotox; tp->pr_name; tp++)
615 printproto(tp, tp->pr_name);
616 }
617 if (af == AF_APPLETALK || af == AF_UNSPEC)
618 for (tp = atalkprotox; tp->pr_name; tp++)
619 printproto(tp, tp->pr_name);
620 if (af == AF_NETGRAPH || af == AF_UNSPEC)
621 for (tp = netgraphprotox; tp->pr_name; tp++)
622 printproto(tp, tp->pr_name);
623 #endif
624 #ifdef NS
625 if (af == AF_NS || af == AF_UNSPEC)
626 for (tp = nsprotox; tp->pr_name; tp++)
627 printproto(tp, tp->pr_name);
628 #endif
629 #ifdef ISO
630 if (af == AF_ISO || af == AF_UNSPEC)
631 for (tp = isoprotox; tp->pr_name; tp++)
632 printproto(tp, tp->pr_name);
633 #endif
634 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
635 unixpr();
636 #ifdef SRVCACHE
637 _serv_cache_close();
638 #endif
639 exit(0);
640 }
641
642 /*
643 * Print out protocol statistics or control blocks (per sflag).
644 * If the interface was not specifically requested, and the symbol
645 * is not in the namelist, ignore this one.
646 */
647 static void
648 printproto(tp, name)
649 register struct protox *tp;
650 char *name;
651 {
652 void (*pr)(u_long, char *, int);
653 u_long off;
654
655 if (sflag) {
656 if (iflag) {
657 if (tp->pr_istats)
658 intpr(interval, nl[N_IFNET].n_value,
659 tp->pr_istats);
660 else if (pflag)
661 printf("%s: no per-interface stats routine\n",
662 tp->pr_name);
663 return;
664 }
665 else {
666 pr = tp->pr_stats;
667 if (!pr) {
668 if (pflag)
669 printf("%s: no stats routine\n",
670 tp->pr_name);
671 return;
672 }
673 off = tp->pr_usesysctl ? tp->pr_usesysctl
674 : nl[tp->pr_sindex].n_value;
675 }
676 } else {
677 pr = tp->pr_cblocks;
678 if (!pr) {
679 if (pflag)
680 printf("%s: no PCB routine\n", tp->pr_name);
681 return;
682 }
683 off = tp->pr_usesysctl ? tp->pr_usesysctl
684 : nl[tp->pr_index].n_value;
685 }
686 if (pr != NULL && (off || af != AF_UNSPEC))
687 (*pr)(off, name, af);
688 }
689
690 /*
691 * Read kernel memory, return 0 on success.
692 */
693 int
694 kread(u_long addr, char *buf, int size)
695 {
696 if (kvmd == 0) {
697 /*
698 * XXX.
699 */
700 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
701 if (kvmd != NULL) {
702 if (kvm_nlist(kvmd, nl) < 0) {
703 if(nlistf)
704 errx(1, "%s: kvm_nlist: %s", nlistf,
705 kvm_geterr(kvmd));
706 else
707 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
708 }
709
710 if (nl[0].n_type == 0) {
711 if(nlistf)
712 errx(1, "%s: no namelist", nlistf);
713 else
714 errx(1, "no namelist");
715 }
716 } else {
717 warnx("kvm not available");
718 return(-1);
719 }
720 }
721 if (!buf)
722 return (0);
723 if (kvm_read(kvmd, addr, buf, size) != size) {
724 warnx("%s", kvm_geterr(kvmd));
725 return (-1);
726 }
727 return (0);
728 }
729
730 char *
731 plural(int n)
732 {
733 return (n != 1 ? "s" : "");
734 }
735
736 char *
737 plurales(int n)
738 {
739 return (n != 1 ? "es" : "");
740 }
741
742 /*
743 * Find the protox for the given "well-known" name.
744 */
745 static struct protox *
746 knownname(char *name)
747 {
748 struct protox **tpp, *tp;
749
750 for (tpp = protoprotox; *tpp; tpp++)
751 for (tp = *tpp; tp->pr_name; tp++)
752 if (strcmp(tp->pr_name, name) == 0)
753 return (tp);
754 return (NULL);
755 }
756
757 /*
758 * Find the protox corresponding to name.
759 */
760 static struct protox *
761 name2protox(char *name)
762 {
763 struct protox *tp;
764 char **alias; /* alias from p->aliases */
765 struct protoent *p;
766
767 /*
768 * Try to find the name in the list of "well-known" names. If that
769 * fails, check if name is an alias for an Internet protocol.
770 */
771 if ((tp = knownname(name)) != NULL)
772 return (tp);
773
774 setprotoent(1); /* make protocol lookup cheaper */
775 while ((p = getprotoent()) != NULL) {
776 /* assert: name not same as p->name */
777 for (alias = p->p_aliases; *alias; alias++)
778 if (strcmp(name, *alias) == 0) {
779 endprotoent();
780 return (knownname(p->p_name));
781 }
782 }
783 endprotoent();
784 return (NULL);
785 }
786
787 static void
788 usage(void)
789 {
790 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
791 "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
792 " netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
793 " netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
794 " netstat -m [-M core] [-N system]",
795 " netstat [-M core] [-N system] [-p protocol]");
796 exit(1);
797 }