1 /* $NetBSD: main.c,v 1.41 2003/04/18 03:21:01 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993 5 * Regents of the University of California. All rights reserved. 6 * 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n\ 39 Regents of the University of California. All rights reserved.\n"); 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94"; 45 #else 46 __RCSID("$NetBSD: main.c,v 1.41 2003/04/18 03:21:01 lukem Exp $"); 47 #endif 48 #endif /* not lint */ 49 50 #include <sys/param.h> 51 #include <sys/file.h> 52 #include <sys/protosw.h> 53 #include <sys/socket.h> 54 55 #include <net/if.h> 56 #include <netinet/in.h> 57 58 #include <ctype.h> 59 #include <err.h> 60 #include <errno.h> 61 #include <kvm.h> 62 #include <limits.h> 63 #include <netdb.h> 64 #include <nlist.h> 65 #include <paths.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <unistd.h> 70 #include "netstat.h" 71 72 struct nlist nl[] = { 73 #define N_MBSTAT 0 74 { "_mbstat" }, 75 #define N_IPSTAT 1 76 { "_ipstat" }, 77 #define N_TCBTABLE 2 78 { "_tcbtable" }, 79 #define N_TCPSTAT 3 80 { "_tcpstat" }, 81 #define N_UDBTABLE 4 82 { "_udbtable" }, 83 #define N_UDPSTAT 5 84 { "_udpstat" }, 85 #define N_IFNET 6 86 { "_ifnet" }, 87 #define N_IMP 7 88 { "_imp_softc" }, 89 #define N_ICMPSTAT 8 90 { "_icmpstat" }, 91 #define N_RTSTAT 9 92 { "_rtstat" }, 93 #define N_UNIXSW 10 94 { "_unixsw" }, 95 #define N_IDP 11 96 { "_nspcb"}, 97 #define N_IDPSTAT 12 98 { "_idpstat"}, 99 #define N_SPPSTAT 13 100 { "_spp_istat"}, 101 #define N_NSERR 14 102 { "_ns_errstat"}, 103 #define N_CLNPSTAT 15 104 { "_clnp_stat"}, 105 #define IN_NOTUSED 16 106 { "_tp_inpcb" }, 107 #define ISO_TP 17 108 { "_tp_refinfo" }, 109 #define N_TPSTAT 18 110 { "_tp_stat" }, 111 #define N_ESISSTAT 19 112 { "_esis_stat"}, 113 #define N_NIMP 20 114 { "_nimp"}, 115 #define N_RTREE 21 116 { "_rt_tables"}, 117 #define N_CLTP 22 118 { "_cltb"}, 119 #define N_CLTPSTAT 23 120 { "_cltpstat"}, 121 #define N_NFILE 24 122 { "_nfile" }, 123 #define N_FILE 25 124 { "_file" }, 125 #define N_IGMPSTAT 26 126 { "_igmpstat" }, 127 #define N_MRTPROTO 27 128 { "_ip_mrtproto" }, 129 #define N_MRTSTAT 28 130 { "_mrtstat" }, 131 #define N_MFCHASHTBL 29 132 { "_mfchashtbl" }, 133 #define N_MFCHASH 30 134 { "_mfchash" }, 135 #define N_VIFTABLE 31 136 { "_viftable" }, 137 #define N_MSIZE 32 138 { "_msize" }, 139 #define N_MCLBYTES 33 140 { "_mclbytes" }, 141 #define N_DDPSTAT 34 142 { "_ddpstat"}, 143 #define N_DDPCB 35 144 { "_ddpcb"}, 145 #define N_MBPOOL 36 146 { "_mbpool" }, 147 #define N_MCLPOOL 37 148 { "_mclpool" }, 149 #define N_DIVPCB 38 150 { "_divcb"}, 151 #define N_DIVSTAT 39 152 { "_divstat"}, 153 #define N_IP6STAT 40 154 { "_ip6stat" }, 155 #define N_TCB6 41 156 { "_tcb6" }, 157 #define N_TCP6STAT 42 158 { "_tcp6stat" }, 159 #define N_UDB6 43 160 { "_udb6" }, 161 #define N_UDP6STAT 44 162 { "_udp6stat" }, 163 #define N_ICMP6STAT 45 164 { "_icmp6stat" }, 165 #define N_IPSECSTAT 46 166 { "_ipsecstat" }, 167 #define N_IPSEC6STAT 47 168 { "_ipsec6stat" }, 169 #define N_PIM6STAT 48 170 { "_pim6stat" }, 171 #define N_MRT6PROTO 49 172 { "_ip6_mrtproto" }, 173 #define N_MRT6STAT 50 174 { "_mrt6stat" }, 175 #define N_MF6CTABLE 51 176 { "_mf6ctable" }, 177 #define N_MIF6TABLE 52 178 { "_mif6table" }, 179 #define N_PFKEYSTAT 53 180 { "_pfkeystat" }, 181 #define N_ARPSTAT 54 182 { "_arpstat" }, 183 #define N_RIP6STAT 55 184 { "_rip6stat" }, 185 #define N_ARPINTRQ 56 186 { "_arpintrq" }, 187 #define N_IPINTRQ 57 188 { "_ipintrq" }, 189 #define N_IP6INTRQ 58 190 { "_ip6intrq" }, 191 #define N_ATINTRQ1 59 192 { "_atintrq1" }, 193 #define N_ATINTRQ2 60 194 { "_atintrq2" }, 195 #define N_NSINTRQ 61 196 { "_nsintrq" }, 197 #define N_CLNLINTRQ 62 198 { "_clnlintrq" }, 199 #define N_LLCINTRQ 63 200 { "_llcintrq" }, 201 #define N_HDINTRQ 64 202 { "_hdintrq" }, 203 #define N_NATMINTRQ 65 204 { "_natmintrq" }, 205 #define N_PPPOEDISCINQ 66 206 { "_ppoediscinq" }, 207 #define N_PPPOEINQ 67 208 { "_ppoeinq" }, 209 #define N_PKINTRQ 68 210 { "_pkintrq" }, 211 #define N_HARDCLOCK_TICKS 69 212 { "_hardclock_ticks" }, 213 { "" }, 214 }; 215 216 struct protox { 217 u_char pr_index; /* index into nlist of cb head */ 218 u_char pr_sindex; /* index into nlist of stat block */ 219 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 220 void (*pr_cblocks) /* control blocks printing routine */ 221 __P((u_long, char *)); 222 void (*pr_stats) /* statistics printing routine */ 223 __P((u_long, char *)); 224 void (*pr_istats) 225 __P((char *)); /* per/if statistics printing routine */ 226 void (*pr_dump) /* PCB state dump routine */ 227 __P((u_long)); 228 char *pr_name; /* well-known name */ 229 } protox[] = { 230 { N_TCBTABLE, N_TCPSTAT, 1, protopr, 231 tcp_stats, NULL, tcp_dump, "tcp" }, 232 { N_UDBTABLE, N_UDPSTAT, 1, protopr, 233 udp_stats, NULL, 0, "udp" }, 234 { -1, N_IPSTAT, 1, 0, 235 ip_stats, NULL, 0, "ip" }, 236 { -1, N_ICMPSTAT, 1, 0, 237 icmp_stats, NULL, 0, "icmp" }, 238 { -1, N_IGMPSTAT, 1, 0, 239 igmp_stats, NULL, 0, "igmp" }, 240 #ifdef IPSEC 241 { -1, N_IPSECSTAT, 1, 0, 242 ipsec_stats, NULL, 0, "ipsec" }, 243 #endif 244 { -1, -1, 0, 0, 245 0, NULL, 0, 0 } 246 }; 247 248 #ifdef INET6 249 struct protox ip6protox[] = { 250 { -1, N_IP6STAT, 1, 0, 251 ip6_stats, ip6_ifstats, 0, "ip6" }, 252 { -1, N_ICMP6STAT, 1, 0, 253 icmp6_stats, icmp6_ifstats, 0, "icmp6" }, 254 #ifdef TCP6 255 { N_TCB6, N_TCP6STAT, 1, ip6protopr, 256 tcp6_stats, NULL, tcp6_dump, "tcp6" }, 257 #else 258 { N_TCB6, N_TCP6STAT, 1, ip6protopr, 259 tcp_stats, NULL, tcp_dump, "tcp6" }, 260 #endif 261 { N_UDB6, N_UDP6STAT, 1, ip6protopr, 262 udp6_stats, NULL, 0, "udp6" }, 263 #ifdef IPSEC 264 { -1, N_IPSEC6STAT, 1, 0, 265 ipsec_stats, NULL, 0, "ipsec6" }, 266 #endif 267 { -1, N_PIM6STAT, 1, 0, 268 pim6_stats, NULL, 0, "pim6" }, 269 { -1, N_RIP6STAT, 1, 0, 270 rip6_stats, NULL, 0, "rip6" }, 271 { -1, -1, 0, 0, 272 0, NULL, 0, 0 } 273 }; 274 #endif 275 276 struct protox arpprotox[] = { 277 { -1, N_ARPSTAT, 1, 0, 278 arp_stats, NULL, 0, "arp" }, 279 { -1, -1, 0, 0, 280 0, NULL, 0, 0 } 281 }; 282 283 #ifdef IPSEC 284 struct protox pfkeyprotox[] = { 285 { -1, N_PFKEYSTAT, 1, 0, 286 pfkey_stats, NULL, 0, "pfkey" }, 287 { -1, -1, 0, 0, 288 0, NULL, 0, 0 } 289 }; 290 #endif 291 292 #ifndef SMALL 293 struct protox atalkprotox[] = { 294 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, 295 ddp_stats, NULL, 0, "ddp" }, 296 { -1, -1, 0, 0, 297 0, NULL, 0 } 298 }; 299 300 struct protox nsprotox[] = { 301 { N_IDP, N_IDPSTAT, 1, nsprotopr, 302 idp_stats, NULL, 0, "idp" }, 303 { N_IDP, N_SPPSTAT, 1, nsprotopr, 304 spp_stats, NULL, 0, "spp" }, 305 { -1, N_NSERR, 1, 0, 306 nserr_stats, NULL, 0, "ns_err" }, 307 { -1, -1, 0, 0, 308 0, NULL, 0 } 309 }; 310 311 struct protox isoprotox[] = { 312 { ISO_TP, N_TPSTAT, 1, iso_protopr, 313 tp_stats, NULL, 0, "tp" }, 314 { N_CLTP, N_CLTPSTAT, 1, iso_protopr, 315 cltp_stats, NULL, 0, "cltp" }, 316 { -1, N_CLNPSTAT, 1, 0, 317 clnp_stats, NULL, 0, "clnp"}, 318 { -1, N_ESISSTAT, 1, 0, 319 esis_stats, NULL, 0, "esis"}, 320 { -1, -1, 0, 0, 321 0, NULL, 0, 0 } 322 }; 323 #endif 324 325 struct protox *protoprotox[] = { protox, 326 #ifdef INET6 327 ip6protox, 328 #endif 329 arpprotox, 330 #ifdef IPSEC 331 pfkeyprotox, 332 #endif 333 #ifndef SMALL 334 atalkprotox, nsprotox, isoprotox, 335 #endif 336 NULL }; 337 338 const struct softintrq { 339 const char *siq_name; 340 int siq_index; 341 } softintrq[] = { 342 { "arpintrq", N_ARPINTRQ }, 343 { "ipintrq", N_IPINTRQ }, 344 { "ip6intrq", N_IP6INTRQ }, 345 { "atintrq1", N_ATINTRQ1 }, 346 { "atintrq2", N_ATINTRQ2 }, 347 { "nsintrq", N_NSINTRQ }, 348 { "clnlintrq", N_CLNLINTRQ }, 349 { "llcintrq", N_LLCINTRQ }, 350 { "hdintrq", N_HDINTRQ }, 351 { "natmintrq", N_NATMINTRQ }, 352 { "ppoediscinq", N_PPPOEDISCINQ }, 353 { "ppoeinq", N_PPPOEINQ }, 354 { "pkintrq", N_PKINTRQ }, 355 { NULL, -1 }, 356 }; 357 358 int main __P((int, char *[])); 359 static void printproto __P((struct protox *, char *)); 360 static void print_softintrq __P((void)); 361 static void usage __P((void)); 362 static struct protox *name2protox __P((char *)); 363 static struct protox *knownname __P((char *)); 364 365 kvm_t *kvmd; 366 367 int 368 main(argc, argv) 369 int argc; 370 char *argv[]; 371 { 372 struct protoent *p; 373 struct protox *tp; /* for printing cblocks & stats */ 374 int ch; 375 char *nlistf = NULL, *memf = NULL; 376 char buf[_POSIX2_LINE_MAX], *cp; 377 u_long pcbaddr; 378 gid_t egid = getegid(); 379 380 (void)setegid(getgid()); 381 tp = NULL; 382 af = AF_UNSPEC; 383 pcbaddr = 0; 384 385 while ((ch = getopt(argc, argv, 386 "Aabdf:ghI:LliM:mN:nP:p:qrsStuvw:")) != -1) 387 switch (ch) { 388 case 'A': 389 Aflag = 1; 390 break; 391 case 'a': 392 aflag = 1; 393 break; 394 case 'b': 395 bflag = 1; 396 break; 397 case 'd': 398 dflag = 1; 399 break; 400 case 'f': 401 if (strcmp(optarg, "ns") == 0) 402 af = AF_NS; 403 else if (strcmp(optarg, "inet") == 0) 404 af = AF_INET; 405 else if (strcmp(optarg, "inet6") == 0) 406 af = AF_INET6; 407 else if (strcmp(optarg, "arp") == 0) 408 af = AF_ARP; 409 else if (strcmp(optarg, "pfkey") == 0) 410 af = PF_KEY; 411 else if (strcmp(optarg, "unix") == 0 412 || strcmp(optarg, "local") == 0) 413 af = AF_LOCAL; 414 else if (strcmp(optarg, "iso") == 0) 415 af = AF_ISO; 416 else if (strcmp(optarg, "atalk") == 0) 417 af = AF_APPLETALK; 418 else 419 errx(1, "%s: unknown address family", 420 optarg); 421 break; 422 #ifndef SMALL 423 case 'g': 424 gflag = 1; 425 break; 426 #endif 427 case 'I': 428 iflag = 1; 429 interface = optarg; 430 break; 431 case 'i': 432 iflag = 1; 433 break; 434 case 'L': 435 Lflag = 1; 436 break; 437 case 'l': 438 lflag = 1; 439 break; 440 case 'M': 441 memf = optarg; 442 break; 443 case 'm': 444 mflag = 1; 445 break; 446 case 'N': 447 nlistf = optarg; 448 break; 449 case 'n': 450 numeric_addr = numeric_port = 1; 451 break; 452 case 'P': 453 errno = 0; 454 pcbaddr = strtoul(optarg, &cp, 16); 455 if (*cp != '\0' || errno == ERANGE) 456 errx(1, "invalid PCB address %s", 457 optarg); 458 Pflag = 1; 459 break; 460 case 'p': 461 if ((tp = name2protox(optarg)) == NULL) 462 errx(1, "%s: unknown or uninstrumented protocol", 463 optarg); 464 pflag = 1; 465 break; 466 case 'q': 467 qflag = 1; 468 break; 469 case 'r': 470 rflag = 1; 471 break; 472 case 's': 473 ++sflag; 474 break; 475 case 'S': 476 numeric_addr = 1; 477 break; 478 case 't': 479 tflag = 1; 480 break; 481 case 'u': 482 af = AF_LOCAL; 483 break; 484 case 'v': 485 vflag++; 486 break; 487 case 'w': 488 interval = atoi(optarg); 489 iflag = 1; 490 break; 491 case '?': 492 default: 493 usage(); 494 } 495 argv += optind; 496 argc -= optind; 497 498 #define BACKWARD_COMPATIBILITY 499 #ifdef BACKWARD_COMPATIBILITY 500 if (*argv) { 501 if (isdigit(**argv)) { 502 interval = atoi(*argv); 503 if (interval <= 0) 504 usage(); 505 ++argv; 506 iflag = 1; 507 } 508 if (*argv) { 509 nlistf = *argv; 510 if (*++argv) 511 memf = *argv; 512 } 513 } 514 #endif 515 516 /* 517 * Discard setgid privileges. If not the running kernel, we toss 518 * them away totally so that bad guys can't print interesting stuff 519 * from kernel memory, otherwise switch back to kmem for the 520 * duration of the kvm_openfiles() call. 521 */ 522 if (nlistf != NULL || memf != NULL || Pflag) 523 (void)setgid(getgid()); 524 else 525 (void)setegid(egid); 526 527 use_sysctl = (nlistf == NULL && memf == NULL); 528 529 if ((kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, 530 buf)) == NULL) 531 errx(1, "%s", buf); 532 533 /* do this now anyway */ 534 if (nlistf == NULL && memf == NULL) 535 (void)setgid(getgid()); 536 537 if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) { 538 if (nlistf) 539 errx(1, "%s: no namelist", nlistf); 540 else 541 errx(1, "no namelist"); 542 } 543 if (mflag) { 544 mbpr(nl[N_MBSTAT].n_value, nl[N_MSIZE].n_value, 545 nl[N_MCLBYTES].n_value, nl[N_MBPOOL].n_value, 546 nl[N_MCLPOOL].n_value); 547 exit(0); 548 } 549 if (Pflag) { 550 if (tp == NULL) { 551 /* Default to TCP. */ 552 tp = name2protox("tcp"); 553 } 554 if (tp->pr_dump) 555 (*tp->pr_dump)(pcbaddr); 556 else 557 printf("%s: no PCB dump routine\n", tp->pr_name); 558 exit(0); 559 } 560 if (pflag) { 561 if (iflag && tp->pr_istats) 562 intpr(interval, nl[N_IFNET].n_value, tp->pr_istats); 563 else if (tp->pr_stats) 564 (*tp->pr_stats)(nl[tp->pr_sindex].n_value, 565 tp->pr_name); 566 else 567 printf("%s: no stats routine\n", tp->pr_name); 568 exit(0); 569 } 570 if (qflag) { 571 print_softintrq(); 572 exit(0); 573 } 574 /* 575 * Keep file descriptors open to avoid overhead 576 * of open/close on each call to get* routines. 577 */ 578 sethostent(1); 579 setnetent(1); 580 if (iflag) { 581 if (af != AF_UNSPEC) 582 goto protostat; 583 584 intpr(interval, nl[N_IFNET].n_value, NULL); 585 exit(0); 586 } 587 if (rflag) { 588 if (sflag) 589 rt_stats(nl[N_RTSTAT].n_value); 590 else 591 routepr(nl[N_RTREE].n_value); 592 exit(0); 593 } 594 #ifndef SMALL 595 if (gflag) { 596 if (sflag) { 597 if (af == AF_INET || af == AF_UNSPEC) 598 mrt_stats(nl[N_MRTPROTO].n_value, 599 nl[N_MRTSTAT].n_value); 600 #ifdef INET6 601 if (af == AF_INET6 || af == AF_UNSPEC) 602 mrt6_stats(nl[N_MRT6PROTO].n_value, 603 nl[N_MRT6STAT].n_value); 604 #endif 605 } 606 else { 607 if (af == AF_INET || af == AF_UNSPEC) 608 mroutepr(nl[N_MRTPROTO].n_value, 609 nl[N_MFCHASHTBL].n_value, 610 nl[N_MFCHASH].n_value, 611 nl[N_VIFTABLE].n_value); 612 #ifdef INET6 613 if (af == AF_INET6 || af == AF_UNSPEC) 614 mroute6pr(nl[N_MRT6PROTO].n_value, 615 nl[N_MF6CTABLE].n_value, 616 nl[N_MIF6TABLE].n_value); 617 #endif 618 } 619 exit(0); 620 } 621 #endif 622 protostat: 623 if (af == AF_INET || af == AF_UNSPEC) { 624 setprotoent(1); 625 setservent(1); 626 /* ugh, this is O(MN) ... why do we do this? */ 627 while ((p = getprotoent()) != NULL) { 628 for (tp = protox; tp->pr_name; tp++) 629 if (strcmp(tp->pr_name, p->p_name) == 0) 630 break; 631 if (tp->pr_name == 0 || tp->pr_wanted == 0) 632 continue; 633 printproto(tp, p->p_name); 634 tp->pr_wanted = 0; 635 } 636 endprotoent(); 637 for (tp = protox; tp->pr_name; tp++) 638 if (tp->pr_wanted) 639 printproto(tp, tp->pr_name); 640 } 641 #ifdef INET6 642 if (af == AF_INET6 || af == AF_UNSPEC) 643 for (tp = ip6protox; tp->pr_name; tp++) 644 printproto(tp, tp->pr_name); 645 #endif 646 if (af == AF_ARP || af == AF_UNSPEC) 647 for (tp = arpprotox; tp->pr_name; tp++) 648 printproto(tp, tp->pr_name); 649 #ifdef IPSEC 650 if (af == PF_KEY || af == AF_UNSPEC) 651 for (tp = pfkeyprotox; tp->pr_name; tp++) 652 printproto(tp, tp->pr_name); 653 #endif 654 #ifndef SMALL 655 if (af == AF_APPLETALK || af == AF_UNSPEC) 656 for (tp = atalkprotox; tp->pr_name; tp++) 657 printproto(tp, tp->pr_name); 658 if (af == AF_NS || af == AF_UNSPEC) 659 for (tp = nsprotox; tp->pr_name; tp++) 660 printproto(tp, tp->pr_name); 661 if (af == AF_ISO || af == AF_UNSPEC) 662 for (tp = isoprotox; tp->pr_name; tp++) 663 printproto(tp, tp->pr_name); 664 if ((af == AF_LOCAL || af == AF_UNSPEC) && !sflag) 665 unixpr(nl[N_UNIXSW].n_value); 666 #endif 667 exit(0); 668 } 669 670 /* 671 * Print out protocol statistics or control blocks (per sflag). 672 * If the interface was not specifically requested, and the symbol 673 * is not in the namelist, ignore this one. 674 */ 675 static void 676 printproto(tp, name) 677 struct protox *tp; 678 char *name; 679 { 680 void (*pr) __P((u_long, char *)); 681 u_long off; 682 683 if (sflag) { 684 if (iflag) { 685 if (tp->pr_istats) 686 intpr(interval, nl[N_IFNET].n_value, 687 tp->pr_istats); 688 return; 689 } 690 else { 691 pr = tp->pr_stats; 692 off = nl[tp->pr_sindex].n_value; 693 } 694 } else { 695 pr = tp->pr_cblocks; 696 off = nl[tp->pr_index].n_value; 697 } 698 if (pr != NULL && (off || af != AF_UNSPEC)) 699 (*pr)(off, name); 700 } 701 702 /* 703 * Print softintrq status. 704 */ 705 void 706 print_softintrq() 707 { 708 struct ifqueue intrq, *ifq = &intrq; 709 const struct softintrq *siq; 710 u_long off; 711 712 for (siq = softintrq; siq->siq_name != NULL; siq++) { 713 off = nl[siq->siq_index].n_value; 714 if (off == 0) 715 continue; 716 717 kread(off, (char *)ifq, sizeof(*ifq)); 718 printf("%s:\n", siq->siq_name); 719 printf("\tqueue length: %d\n", ifq->ifq_len); 720 printf("\tmaximum queue length: %d\n", ifq->ifq_maxlen); 721 printf("\tpackets dropped: %d\n", ifq->ifq_drops); 722 } 723 } 724 725 /* 726 * Read kernel memory, return 0 on success. 727 */ 728 int 729 kread(addr, buf, size) 730 u_long addr; 731 char *buf; 732 int size; 733 { 734 735 if (kvm_read(kvmd, addr, buf, size) != size) { 736 warnx("%s", kvm_geterr(kvmd)); 737 return (-1); 738 } 739 return (0); 740 } 741 742 char * 743 plural(n) 744 int n; 745 { 746 747 return (n != 1 ? "s" : ""); 748 } 749 750 char * 751 plurales(n) 752 int n; 753 { 754 755 return (n != 1 ? "es" : ""); 756 } 757 758 int 759 get_hardticks(void) 760 { 761 int hardticks; 762 763 kread(nl[N_HARDCLOCK_TICKS].n_value, (char *)&hardticks, 764 sizeof(hardticks)); 765 return (hardticks); 766 } 767 768 /* 769 * Find the protox for the given "well-known" name. 770 */ 771 static struct protox * 772 knownname(name) 773 char *name; 774 { 775 struct protox **tpp, *tp; 776 777 for (tpp = protoprotox; *tpp; tpp++) 778 for (tp = *tpp; tp->pr_name; tp++) 779 if (strcmp(tp->pr_name, name) == 0) 780 return (tp); 781 return (NULL); 782 } 783 784 /* 785 * Find the protox corresponding to name. 786 */ 787 static struct protox * 788 name2protox(name) 789 char *name; 790 { 791 struct protox *tp; 792 char **alias; /* alias from p->aliases */ 793 struct protoent *p; 794 795 /* 796 * Try to find the name in the list of "well-known" names. If that 797 * fails, check if name is an alias for an Internet protocol. 798 */ 799 if ((tp = knownname(name)) != NULL) 800 return (tp); 801 802 setprotoent(1); /* make protocol lookup cheaper */ 803 while ((p = getprotoent()) != NULL) { 804 /* assert: name not same as p->name */ 805 for (alias = p->p_aliases; *alias; alias++) 806 if (strcmp(name, *alias) == 0) { 807 endprotoent(); 808 return (knownname(p->p_name)); 809 } 810 } 811 endprotoent(); 812 return (NULL); 813 } 814 815 static void 816 usage() 817 { 818 const char *progname = getprogname(); 819 820 (void)fprintf(stderr, 821 "usage: %s [-Aan] [-f address_family] [-M core] [-N system]\n", progname); 822 (void)fprintf(stderr, 823 " %s [-bdgiLmnqrsSv] [-f address_family] [-M core] [-N system]\n", 824 progname); 825 (void)fprintf(stderr, 826 " %s [-dn] [-I interface] [-M core] [-N system] [-w wait]\n", progname); 827 (void)fprintf(stderr, 828 " %s [-p protocol] [-M core] [-N system]\n", progname); 829 (void)fprintf(stderr, 830 " %s [-p protocol] [-M core] [-N system] -P pcbaddr\n", progname); 831 (void)fprintf(stderr, 832 " %s [-p protocol] [-i] [-I Interface] \n", progname); 833 (void)fprintf(stderr, 834 " %s [-s] [-f address_family] [-i] [-I Interface]\n", progname); 835 exit(1); 836 } 837