etc/services - sync with NetBSD-8
[minix.git] / usr.bin / netstat / main.c
blob04d93aa97531274027fc7226ab8693723edcf9f9
1 /* $NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $ */
3 /*
4 * Copyright (c) 1983, 1988, 1993
5 * Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\
35 Regents of the University of California. All rights reserved.");
36 #endif /* not lint */
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94";
41 #else
42 __RCSID("$NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $");
43 #endif
44 #endif /* not lint */
46 #include <sys/param.h>
47 #include <sys/file.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
51 #include <net/if.h>
52 #include <netinet/in.h>
54 #include <ctype.h>
55 #include <err.h>
56 #include <errno.h>
57 #include <kvm.h>
58 #include <limits.h>
59 #include <netdb.h>
60 #include <nlist.h>
61 #include <paths.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include "netstat.h"
67 #include "rtutil.h"
68 #include "prog_ops.h"
70 struct nlist nl[] = {
71 #define N_MBSTAT 0
72 { "_mbstat", 0, 0, 0, 0 },
73 #define N_IPSTAT 1
74 { "_ipstat", 0, 0, 0, 0 }, /* not available via kvm */
75 #define N_TCBTABLE 2
76 { "_tcbtable", 0, 0, 0, 0 },
77 #define N_TCPSTAT 3
78 { "_tcpstat", 0, 0, 0, 0 }, /* not available via kvm */
79 #define N_UDBTABLE 4
80 { "_udbtable", 0, 0, 0, 0 },
81 #define N_UDPSTAT 5
82 { "_udpstat", 0, 0, 0, 0 }, /* not available via kvm */
83 #define N_IFNET_LIST 6
84 { "_ifnet_list", 0, 0, 0, 0 },
85 #define N_ICMPSTAT 7
86 { "_icmpstat", 0, 0, 0, 0 }, /* not available via kvm */
87 #define N_RTSTAT 8
88 { "_rtstat", 0, 0, 0, 0 },
89 #define N_UNIXSW 9
90 { "_unixsw", 0, 0, 0, 0 },
91 #define N_RTREE 10
92 { "_rt_tables", 0, 0, 0, 0 },
93 #define N_NFILE 11
94 { "_nfile", 0, 0, 0, 0 },
95 #define N_IGMPSTAT 12
96 { "_igmpstat", 0, 0, 0, 0 }, /* not available via kvm */
97 #define N_MRTPROTO 13
98 { "_ip_mrtproto", 0, 0, 0, 0 },
99 #define N_MRTSTAT 14
100 { "_mrtstat", 0, 0, 0, 0 },
101 #define N_MFCHASHTBL 15
102 { "_mfchashtbl", 0, 0, 0, 0 },
103 #define N_MFCHASH 16
104 { "_mfchash", 0, 0, 0, 0 },
105 #define N_VIFTABLE 17
106 { "_viftable", 0, 0, 0, 0 },
107 #define N_MSIZE 18
108 { "_msize", 0, 0, 0, 0 },
109 #define N_MCLBYTES 19
110 { "_mclbytes", 0, 0, 0, 0 },
111 #define N_DDPSTAT 20
112 { "_ddpstat", 0, 0, 0, 0 }, /* not available via kvm */
113 #define N_DDPCB 21
114 { "_ddpcb", 0, 0, 0, 0 },
115 #define N_MBPOOL 22
116 { "_mbpool", 0, 0, 0, 0 },
117 #define N_MCLPOOL 23
118 { "_mclpool", 0, 0, 0, 0 },
119 #define N_IP6STAT 24
120 { "_ip6stat", 0, 0, 0, 0 }, /* not available via kvm */
121 #define N_TCP6STAT 25
122 { "_tcp6stat", 0, 0, 0, 0 }, /* not available via kvm */
123 #define N_UDP6STAT 26
124 { "_udp6stat", 0, 0, 0, 0 }, /* not available via kvm */
125 #define N_ICMP6STAT 27
126 { "_icmp6stat", 0, 0, 0, 0 }, /* not available via kvm */
127 #define N_IPSECSTAT 28
128 { "_ipsecstat", 0, 0, 0, 0 }, /* not available via kvm */
129 #define N_IPSEC6STAT 29
130 { "_ipsec6stat", 0, 0, 0, 0 }, /* not available via kvm */
131 #define N_PIM6STAT 30
132 { "_pim6stat", 0, 0, 0, 0 }, /* not available via kvm */
133 #define N_MRT6PROTO 31
134 { "_ip6_mrtproto", 0, 0, 0, 0 },
135 #define N_MRT6STAT 32
136 { "_mrt6stat", 0, 0, 0, 0 },
137 #define N_MF6CTABLE 33
138 { "_mf6ctable", 0, 0, 0, 0 },
139 #define N_MIF6TABLE 34
140 { "_mif6table", 0, 0, 0, 0 },
141 #define N_PFKEYSTAT 35
142 { "_pfkeystat", 0, 0, 0, 0 }, /* not available via kvm */
143 #define N_ARPSTAT 36
144 { "_arpstat", 0, 0, 0, 0 }, /* not available via kvm */
145 #define N_RIP6STAT 37
146 { "_rip6stat", 0, 0, 0, 0 }, /* not available via kvm */
147 #define N_ARPINTRQ 38
148 { "_arpintrq", 0, 0, 0, 0 },
149 #define N_IPINTRQ 39
150 { "_ipintrq", 0, 0, 0, 0 },
151 #define N_IP6INTRQ 40
152 { "_ip6intrq", 0, 0, 0, 0 },
153 #define N_ATINTRQ1 41
154 { "_atintrq1", 0, 0, 0, 0 },
155 #define N_ATINTRQ2 42
156 { "_atintrq2", 0, 0, 0, 0 },
157 #define N_NSINTRQ 43
158 { "_nsintrq", 0, 0, 0, 0 },
159 #define N_LLCINTRQ 44
160 { "_llcintrq", 0, 0, 0, 0 },
161 #define N_HDINTRQ 45
162 { "_hdintrq", 0, 0, 0, 0 },
163 #define N_NATMINTRQ 46
164 { "_natmintrq", 0, 0, 0, 0 },
165 #define N_PPPOEDISCINQ 47
166 { "_ppoediscinq", 0, 0, 0, 0 },
167 #define N_PPPOEINQ 48
168 { "_ppoeinq", 0, 0, 0, 0 },
169 #define N_PKINTRQ 49
170 { "_pkintrq", 0, 0, 0, 0 },
171 #define N_HARDCLOCK_TICKS 50
172 { "_hardclock_ticks", 0, 0, 0, 0 },
173 #define N_PIMSTAT 51
174 { "_pimstat", 0, 0, 0, 0 },
175 #define N_CARPSTAT 52
176 { "_carpstats", 0, 0, 0, 0 }, /* not available via kvm */
177 #define N_PFSYNCSTAT 53
178 { "_pfsyncstats", 0, 0, 0, 0}, /* not available via kvm */
179 { "", 0, 0, 0, 0 },
182 struct protox {
183 u_char pr_index; /* index into nlist of cb head */
184 u_char pr_sindex; /* index into nlist of stat block */
185 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
186 void (*pr_cblocks) /* control blocks printing routine */
187 __P((u_long, const char *));
188 void (*pr_stats) /* statistics printing routine */
189 __P((u_long, const char *));
190 void (*pr_istats)
191 __P((const char *)); /* per/if statistics printing routine */
192 void (*pr_dump) /* PCB state dump routine */
193 __P((u_long, const char *, u_long));
194 const char *pr_name; /* well-known name */
195 } protox[] = {
196 { N_TCBTABLE, N_TCPSTAT, 1, protopr,
197 tcp_stats, NULL, tcp_dump, "tcp" },
198 { N_UDBTABLE, N_UDPSTAT, 1, protopr,
199 udp_stats, NULL, 0, "udp" },
200 { -1, N_IPSTAT, 1, 0,
201 ip_stats, NULL, 0, "ip" },
202 { -1, N_ICMPSTAT, 1, 0,
203 icmp_stats, NULL, 0, "icmp" },
204 { -1, N_IGMPSTAT, 1, 0,
205 igmp_stats, NULL, 0, "igmp" },
206 { -1, N_CARPSTAT, 1, 0,
207 carp_stats, NULL, 0, "carp" },
208 #ifdef IPSEC
209 { -1, N_IPSECSTAT, 1, 0,
210 fast_ipsec_stats, NULL, 0, "ipsec" },
211 #endif
212 { -1, N_PIMSTAT, 1, 0,
213 pim_stats, NULL, 0, "pim" },
214 { -1, N_PFSYNCSTAT, 1, 0,
215 pfsync_stats, NULL, 0, "pfsync" },
216 { -1, -1, 0, 0,
217 0, NULL, 0, 0 }
220 #ifdef INET6
221 struct protox ip6protox[] = {
222 { -1, N_IP6STAT, 1, 0,
223 ip6_stats, ip6_ifstats, 0, "ip6" },
224 { -1, N_ICMP6STAT, 1, 0,
225 icmp6_stats, icmp6_ifstats, 0, "icmp6" },
226 #ifdef TCP6
227 { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
228 tcp6_stats, NULL, tcp6_dump, "tcp6" },
229 #else
230 { N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
231 tcp_stats, NULL, tcp6_dump, "tcp6" },
232 #endif
233 { N_UDBTABLE, N_UDP6STAT, 1, ip6protopr,
234 udp6_stats, NULL, 0, "udp6" },
235 #ifdef IPSEC
236 { -1, N_IPSEC6STAT, 1, 0,
237 fast_ipsec_stats, NULL, 0, "ipsec6" },
238 #endif
239 { -1, N_PIM6STAT, 1, 0,
240 pim6_stats, NULL, 0, "pim6" },
241 { -1, N_RIP6STAT, 1, 0,
242 rip6_stats, NULL, 0, "rip6" },
243 { -1, -1, 0, 0,
244 0, NULL, 0, 0 }
246 #endif
248 struct protox arpprotox[] = {
249 { -1, N_ARPSTAT, 1, 0,
250 arp_stats, NULL, 0, "arp" },
251 { -1, -1, 0, 0,
252 0, NULL, 0, 0 }
255 #ifdef IPSEC
256 struct protox pfkeyprotox[] = {
257 { -1, N_PFKEYSTAT, 1, 0,
258 pfkey_stats, NULL, 0, "pfkey" },
259 { -1, -1, 0, 0,
260 0, NULL, 0, 0 }
262 #endif
264 #ifndef SMALL
265 struct protox atalkprotox[] = {
266 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
267 ddp_stats, NULL, 0, "ddp" },
268 { -1, -1, 0, 0,
269 0, NULL, 0, NULL }
271 #endif
273 struct protox *protoprotox[] = { protox,
274 #ifdef INET6
275 ip6protox,
276 #endif
277 arpprotox,
278 #ifdef IPSEC
279 pfkeyprotox,
280 #endif
281 #ifndef SMALL
282 atalkprotox,
283 #endif
284 NULL };
286 const struct softintrq {
287 const char *siq_name;
288 int siq_index;
289 } softintrq[] = {
290 { "arpintrq", N_ARPINTRQ },
291 { "ipintrq", N_IPINTRQ },
292 { "ip6intrq", N_IP6INTRQ },
293 { "atintrq1", N_ATINTRQ1 },
294 { "atintrq2", N_ATINTRQ2 },
295 { "llcintrq", N_LLCINTRQ },
296 { "hdintrq", N_HDINTRQ },
297 { "natmintrq", N_NATMINTRQ },
298 { "ppoediscinq", N_PPPOEDISCINQ },
299 { "ppoeinq", N_PPPOEINQ },
300 { "pkintrq", N_PKINTRQ },
301 { NULL, -1 },
304 int main __P((int, char *[]));
305 static void printproto __P((struct protox *, const char *));
306 static void print_softintrq __P((void));
307 __dead static void usage(void);
308 static struct protox *name2protox __P((const char *));
309 static struct protox *knownname __P((const char *));
310 static void prepare(const char *, const char *, struct protox *tp);
311 static kvm_t *prepare_kvmd(const char *, const char *, char *);
313 static kvm_t *kvmd = NULL;
314 gid_t egid;
315 int interval; /* repeat interval for i/f stats */
316 static const char *nlistf = NULL, *memf = NULL;
318 kvm_t *
319 get_kvmd(void)
321 char buf[_POSIX2_LINE_MAX];
323 if (kvmd != NULL)
324 return kvmd;
325 if ((kvmd = prepare_kvmd(nlistf, memf, buf)) == NULL)
326 errx(1, "kvm error: %s", buf);
327 return kvmd;
330 static kvm_t *
331 prepare_kvmd(const char *nf, const char *mf, char *errbuf)
333 kvm_t *k;
335 (void)setegid(egid);
336 k = kvm_openfiles(nf, mf, NULL, O_RDONLY, errbuf);
337 (void)setgid(getgid());
338 return k;
341 void
342 prepare(const char *nf, const char *mf, struct protox *tp)
344 char buf[_POSIX2_LINE_MAX];
346 * Try to figure out if we can use sysctl or not.
348 if (nf != NULL || mf != NULL) {
349 /* Of course, we can't use sysctl with dumps. */
350 if (force_sysctl)
351 errx(EXIT_FAILURE, "can't use sysctl with dumps");
354 * If we have -M or -N, we're not dealing with live memory
355 * or want to use kvm interface explicitly. It is sometimes
356 * useful to dig inside of kernel without extending
357 * sysctl interface (i.e., without rebuilding kernel).
359 use_sysctl = 0;
360 } else if (qflag ||
361 iflag ||
362 #ifndef SMALL
363 gflag ||
364 #endif
365 (pflag && tp->pr_sindex == N_PIMSTAT) ||
366 Pflag) {
367 /* These flags are not yet supported via sysctl(3). */
368 use_sysctl = 0;
369 } else {
370 /* We can use sysctl(3). */
371 use_sysctl = 1;
374 if (force_sysctl && !use_sysctl) {
375 /* Let the user know what's about to happen. */
376 warnx("forcing sysctl usage even though it might not be "\
377 "supported");
378 use_sysctl = 1;
381 #ifdef __minix
382 use_sysctl = 1;
383 #endif /* __minix */
385 kvmd = prepare_kvmd(nf, mf, buf);
387 if (!use_sysctl) {
389 if (kvmd == NULL)
390 errx(1, "kvm error: %s", buf);
391 if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
392 if (nf)
393 errx(1, "%s: no namelist", nf);
394 else
395 errx(1, "no namelist");
397 } else
398 (void)setgid(getgid());
402 main(int argc, char *argv[])
404 struct protoent *p;
405 struct protox *tp; /* for printing cblocks & stats */
406 int ch;
407 char *cp;
408 char *afname, *afnames;
409 u_long pcbaddr;
411 if (prog_init) {
412 if (prog_init() == -1)
413 err(1, "init failed");
414 force_sysctl = 1; /* cheap trick */
417 egid = getegid();
418 (void)setegid(getgid());
419 tp = NULL;
420 af = AF_UNSPEC;
421 afnames = NULL;
422 pcbaddr = 0;
424 while ((ch = getopt(argc, argv,
425 "AabBdf:ghI:LliM:mN:nP:p:qrsStTuVvw:X")) != -1)
426 switch (ch) {
427 case 'A':
428 Aflag = RT_AFLAG;
429 break;
430 case 'a':
431 aflag = 1;
432 break;
433 case 'b':
434 bflag = 1;
435 break;
436 case 'B':
437 Bflag = 1;
438 break;
439 case 'd':
440 dflag = 1;
441 break;
442 case 'f':
443 afnames = optarg;
444 break;
445 #ifndef SMALL
446 case 'g':
447 gflag = 1;
448 break;
449 #endif
450 case 'h':
451 hflag = 1;
452 break;
453 case 'I':
454 iflag = 1;
455 interface = optarg;
456 break;
457 case 'i':
458 iflag = 1;
459 break;
460 case 'L':
461 Lflag = RT_LFLAG;
462 break;
463 case 'l':
464 lflag = 1;
465 break;
466 case 'M':
467 memf = optarg;
468 break;
469 case 'm':
470 mflag = 1;
471 break;
472 case 'N':
473 nlistf = optarg;
474 break;
475 case 'n':
476 numeric_addr = numeric_port = nflag = RT_NFLAG;
477 break;
478 case 'P':
479 errno = 0;
480 pcbaddr = strtoul(optarg, &cp, 16);
481 if (*cp != '\0' || errno == ERANGE)
482 errx(1, "invalid PCB address %s",
483 optarg);
484 Pflag = 1;
485 break;
486 case 'p':
487 if ((tp = name2protox(optarg)) == NULL)
488 errx(1, "%s: unknown or uninstrumented protocol",
489 optarg);
490 pflag = 1;
491 break;
492 case 'q':
493 qflag = 1;
494 break;
495 case 'r':
496 rflag = 1;
497 break;
498 case 's':
499 ++sflag;
500 break;
501 case 'S':
502 numeric_addr = 1;
503 break;
504 case 't':
505 tflag = 1;
506 break;
507 case 'T':
508 tagflag = RT_TFLAG;
509 break;
510 case 'u':
511 af = AF_LOCAL;
512 break;
513 case 'V':
514 Vflag++;
515 break;
516 case 'v':
517 vflag = RT_VFLAG;
518 break;
519 case 'w':
520 interval = atoi(optarg);
521 iflag = 1;
522 break;
523 case 'X':
524 force_sysctl = 1;
525 break;
526 case '?':
527 default:
528 usage();
530 argv += optind;
531 argc -= optind;
533 #define BACKWARD_COMPATIBILITY
534 #ifdef BACKWARD_COMPATIBILITY
535 if (*argv) {
536 if (isdigit((unsigned char)**argv)) {
537 interval = atoi(*argv);
538 if (interval <= 0)
539 usage();
540 ++argv;
541 iflag = 1;
543 if (*argv) {
544 nlistf = *argv;
545 if (*++argv)
546 memf = *argv;
549 #endif
551 prepare(nlistf, memf, tp);
553 #ifndef SMALL
554 if (Bflag) {
555 if (sflag)
556 bpf_stats();
557 else
558 bpf_dump(interface);
559 exit(0);
561 #endif
563 if (mflag) {
564 mbpr(nl[N_MBSTAT].n_value, nl[N_MSIZE].n_value,
565 nl[N_MCLBYTES].n_value, nl[N_MBPOOL].n_value,
566 nl[N_MCLPOOL].n_value);
567 exit(0);
569 if (Pflag) {
570 if (tp == NULL) {
571 /* Default to TCP. */
572 tp = name2protox("tcp");
574 if (tp->pr_dump)
575 (*tp->pr_dump)(nl[tp->pr_index].n_value, tp->pr_name,
576 pcbaddr);
577 else
578 printf("%s: no PCB dump routine\n", tp->pr_name);
579 exit(0);
581 if (pflag) {
582 if (iflag && tp->pr_istats)
583 intpr(interval, nl[N_IFNET_LIST].n_value, tp->pr_istats);
584 else if (tp->pr_stats)
585 (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
586 tp->pr_name);
587 else
588 printf("%s: no stats routine\n", tp->pr_name);
589 exit(0);
591 if (qflag) {
592 print_softintrq();
593 exit(0);
596 * Keep file descriptors open to avoid overhead
597 * of open/close on each call to get* routines.
599 sethostent(1);
600 setnetent(1);
602 * If -f was used afnames != NULL, loop over the address families.
603 * Otherwise do this at least once (with af == AF_UNSPEC).
605 afname = NULL;
606 do {
607 if (afnames != NULL) {
608 afname = strsep(&afnames, ",");
609 if (afname == NULL)
610 break; /* Exit early */
611 if (strcmp(afname, "inet") == 0)
612 af = AF_INET;
613 else if (strcmp(afname, "inet6") == 0)
614 af = AF_INET6;
615 else if (strcmp(afname, "arp") == 0)
616 af = AF_ARP;
617 else if (strcmp(afname, "pfkey") == 0)
618 af = PF_KEY;
619 else if (strcmp(afname, "unix") == 0
620 || strcmp(afname, "local") == 0)
621 af = AF_LOCAL;
622 else if (strcmp(afname, "atalk") == 0)
623 af = AF_APPLETALK;
624 else if (strcmp(afname, "mpls") == 0)
625 af = AF_MPLS;
626 else {
627 warnx("%s: unknown address family",
628 afname);
629 continue;
633 if (iflag) {
634 if (af != AF_UNSPEC)
635 goto protostat;
637 intpr(interval, nl[N_IFNET_LIST].n_value, NULL);
638 break;
640 if (rflag) {
641 if (sflag)
642 rt_stats(use_sysctl ? 0 : nl[N_RTSTAT].n_value);
643 else {
644 if (use_sysctl)
645 p_rttables(af,
646 nflag|tagflag|vflag|Lflag, 0, ~0);
647 else
648 routepr(nl[N_RTREE].n_value);
650 break;
652 #ifndef SMALL
653 if (gflag) {
654 if (sflag) {
655 if (af == AF_INET || af == AF_UNSPEC)
656 mrt_stats(nl[N_MRTPROTO].n_value,
657 nl[N_MRTSTAT].n_value);
658 #ifdef INET6
659 if (af == AF_INET6 || af == AF_UNSPEC)
660 mrt6_stats(nl[N_MRT6PROTO].n_value,
661 nl[N_MRT6STAT].n_value);
662 #endif
664 else {
665 if (af == AF_INET || af == AF_UNSPEC)
666 mroutepr(nl[N_MRTPROTO].n_value,
667 nl[N_MFCHASHTBL].n_value,
668 nl[N_MFCHASH].n_value,
669 nl[N_VIFTABLE].n_value);
670 #ifdef INET6
671 if (af == AF_INET6 || af == AF_UNSPEC)
672 mroute6pr(nl[N_MRT6PROTO].n_value,
673 nl[N_MF6CTABLE].n_value,
674 nl[N_MIF6TABLE].n_value);
675 #endif
677 break;
679 #endif
680 protostat:
681 if (af == AF_INET || af == AF_UNSPEC) {
682 setprotoent(1);
683 setservent(1);
684 /* ugh, this is O(MN) ... why do we do this? */
685 while ((p = getprotoent()) != NULL) {
686 for (tp = protox; tp->pr_name; tp++)
687 if (strcmp(tp->pr_name, p->p_name) == 0)
688 break;
689 if (tp->pr_name == 0 || tp->pr_wanted == 0)
690 continue;
691 printproto(tp, p->p_name);
692 tp->pr_wanted = 0;
694 endprotoent();
695 for (tp = protox; tp->pr_name; tp++)
696 if (tp->pr_wanted)
697 printproto(tp, tp->pr_name);
699 #ifdef INET6
700 if (af == AF_INET6 || af == AF_UNSPEC)
701 for (tp = ip6protox; tp->pr_name; tp++)
702 printproto(tp, tp->pr_name);
703 #endif
704 if (af == AF_ARP || af == AF_UNSPEC)
705 for (tp = arpprotox; tp->pr_name; tp++)
706 printproto(tp, tp->pr_name);
707 #ifdef IPSEC
708 if (af == PF_KEY || af == AF_UNSPEC)
709 for (tp = pfkeyprotox; tp->pr_name; tp++)
710 printproto(tp, tp->pr_name);
711 #endif
712 #ifndef SMALL
713 if (af == AF_APPLETALK || af == AF_UNSPEC)
714 for (tp = atalkprotox; tp->pr_name; tp++)
715 printproto(tp, tp->pr_name);
716 if ((af == AF_LOCAL || af == AF_UNSPEC) && !sflag)
717 unixpr(nl[N_UNIXSW].n_value);
718 #endif
719 } while (afnames != NULL && afname != NULL);
720 exit(0);
724 * Print out protocol statistics or control blocks (per sflag).
725 * If the interface was not specifically requested, and the symbol
726 * is not in the namelist, ignore this one.
728 static void
729 printproto(struct protox *tp, const char *name)
731 void (*pr) __P((u_long, const char *));
732 u_long off;
734 if (sflag) {
735 if (iflag) {
736 if (tp->pr_istats)
737 intpr(interval, nl[N_IFNET_LIST].n_value,
738 tp->pr_istats);
739 return;
741 else {
742 pr = tp->pr_stats;
743 off = nl[tp->pr_sindex].n_value;
745 } else {
746 pr = tp->pr_cblocks;
747 off = nl[tp->pr_index].n_value;
749 if (pr != NULL && ((off || af != AF_UNSPEC) || use_sysctl)) {
750 (*pr)(off, name);
755 * Print softintrq status.
757 void
758 print_softintrq(void)
760 struct ifqueue intrq, *ifq = &intrq;
761 const struct softintrq *siq;
762 u_long off;
764 for (siq = softintrq; siq->siq_name != NULL; siq++) {
765 off = nl[siq->siq_index].n_value;
766 if (off == 0)
767 continue;
769 kread(off, (char *)ifq, sizeof(*ifq));
770 printf("%s:\n", siq->siq_name);
771 printf("\tqueue length: %d\n", ifq->ifq_len);
772 printf("\tmaximum queue length: %d\n", ifq->ifq_maxlen);
773 printf("\tpackets dropped: %d\n", ifq->ifq_drops);
778 * Read kernel memory, return 0 on success.
781 kread(u_long addr, char *buf, int size)
784 if (kvm_read(kvmd, addr, buf, size) != size) {
785 warnx("%s", kvm_geterr(kvmd));
786 return (-1);
788 return (0);
791 const char *
792 plural(int n)
795 return (n != 1 ? "s" : "");
798 const char *
799 plurales(int n)
802 return (n != 1 ? "es" : "");
806 get_hardticks(void)
808 int hardticks;
810 kread(nl[N_HARDCLOCK_TICKS].n_value, (char *)&hardticks,
811 sizeof(hardticks));
812 return (hardticks);
816 * Find the protox for the given "well-known" name.
818 static struct protox *
819 knownname(const char *name)
821 struct protox **tpp, *tp;
823 for (tpp = protoprotox; *tpp; tpp++)
824 for (tp = *tpp; tp->pr_name; tp++)
825 if (strcmp(tp->pr_name, name) == 0)
826 return (tp);
827 return (NULL);
831 * Find the protox corresponding to name.
833 static struct protox *
834 name2protox(const char *name)
836 struct protox *tp;
837 char **alias; /* alias from p->aliases */
838 struct protoent *p;
841 * Try to find the name in the list of "well-known" names. If that
842 * fails, check if name is an alias for an Internet protocol.
844 if ((tp = knownname(name)) != NULL)
845 return (tp);
847 setprotoent(1); /* make protocol lookup cheaper */
848 while ((p = getprotoent()) != NULL) {
849 /* assert: name not same as p->name */
850 for (alias = p->p_aliases; *alias; alias++)
851 if (strcmp(name, *alias) == 0) {
852 endprotoent();
853 return (knownname(p->p_name));
856 endprotoent();
857 return (NULL);
860 static void
861 usage(void)
863 const char *progname = getprogname();
865 (void)fprintf(stderr,
866 "usage: %s [-Aan] [-f address_family[,family ...]] [-M core] [-N system]\n", progname);
867 (void)fprintf(stderr,
868 " %s [-bdgiLmnqrsSv] [-f address_family[,family ...]] [-M core] [-N system]\n",
869 progname);
870 (void)fprintf(stderr,
871 " %s [-dn] [-I interface] [-M core] [-N system] [-w wait]\n", progname);
872 (void)fprintf(stderr,
873 " %s [-p protocol] [-M core] [-N system]\n", progname);
874 (void)fprintf(stderr,
875 " %s [-p protocol] [-M core] [-N system] -P pcbaddr\n", progname);
876 (void)fprintf(stderr,
877 " %s [-p protocol] [-i] [-I Interface] \n", progname);
878 (void)fprintf(stderr,
879 " %s [-s] [-f address_family[,family ...]] [-i] [-I Interface]\n", progname);
880 (void)fprintf(stderr,
881 " %s [-s] [-B] [-I interface]\n", progname);
882 exit(1);