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