1 /*- 2 * Copyright (c) 1983, 1988, 1993 3 * Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef lint 31 static char const copyright[] = 32 "@(#) Copyright (c) 1983, 1988, 1993\n\ 33 Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #if 0 37 #ifndef lint 38 static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; 39 #endif /* not lint */ 40 #endif 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include <sys/param.h> 46 #include <sys/file.h> 47 #include <sys/protosw.h> 48 #include <sys/socket.h> 49 #include <sys/socketvar.h> 50 51 #include <netinet/in.h> 52 53 #ifdef NETGRAPH 54 #include <netgraph/ng_socket.h> 55 #endif 56 57 #include <ctype.h> 58 #include <err.h> 59 #include <errno.h> 60 #include <kvm.h> 61 #include <limits.h> 62 #include <netdb.h> 63 #include <nlist.h> 64 #include <paths.h> 65 #include <stdint.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <stdbool.h> 69 #include <string.h> 70 #include <unistd.h> 71 #include "netstat.h" 72 #include "nl_defs.h" 73 #include <libxo/xo.h> 74 75 static struct protox { 76 int pr_index; /* index into nlist of cb head */ 77 int pr_sindex; /* index into nlist of stat block */ 78 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 79 void (*pr_cblocks)(u_long, const char *, int, int); 80 /* control blocks printing routine */ 81 void (*pr_stats)(u_long, const char *, int, int); 82 /* statistics printing routine */ 83 void (*pr_istats)(char *); /* per/if statistics printing routine */ 84 const char *pr_name; /* well-known name */ 85 int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ 86 int pr_protocol; 87 } protox[] = { 88 { N_TCBINFO, N_TCPSTAT, 1, protopr, 89 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 90 { N_UDBINFO, N_UDPSTAT, 1, protopr, 91 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 92 #ifdef SCTP 93 { -1, N_SCTPSTAT, 1, sctp_protopr, 94 sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, 95 #endif 96 #ifdef SDP 97 { -1, -1, 1, protopr, 98 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 99 #endif 100 { N_DIVCBINFO, -1, 1, protopr, 101 NULL, NULL, "divert", 1, IPPROTO_DIVERT }, 102 { N_RIPCBINFO, N_IPSTAT, 1, protopr, 103 ip_stats, NULL, "ip", 1, IPPROTO_RAW }, 104 { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, 105 icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, 106 { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, 107 igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, 108 #ifdef IPSEC 109 { -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */ 110 ipsec_stats, NULL, "ipsec", 0, 0}, 111 { -1, N_AHSTAT, 1, NULL, 112 ah_stats, NULL, "ah", 0, 0}, 113 { -1, N_ESPSTAT, 1, NULL, 114 esp_stats, NULL, "esp", 0, 0}, 115 { -1, N_IPCOMPSTAT, 1, NULL, 116 ipcomp_stats, NULL, "ipcomp", 0, 0}, 117 #endif 118 { N_RIPCBINFO, N_PIMSTAT, 1, protopr, 119 pim_stats, NULL, "pim", 1, IPPROTO_PIM }, 120 { -1, N_CARPSTATS, 1, NULL, 121 carp_stats, NULL, "carp", 1, 0 }, 122 #ifdef PF 123 { -1, N_PFSYNCSTATS, 1, NULL, 124 pfsync_stats, NULL, "pfsync", 1, 0 }, 125 #endif 126 { -1, N_ARPSTAT, 1, NULL, 127 arp_stats, NULL, "arp", 1, 0 }, 128 { -1, -1, 0, NULL, 129 NULL, NULL, NULL, 0, 0 } 130 }; 131 132 #ifdef INET6 133 static struct protox ip6protox[] = { 134 { N_TCBINFO, N_TCPSTAT, 1, protopr, 135 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 136 { N_UDBINFO, N_UDPSTAT, 1, protopr, 137 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 138 { N_RIPCBINFO, N_IP6STAT, 1, protopr, 139 ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, 140 { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, 141 icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, 142 #ifdef SDP 143 { -1, -1, 1, protopr, 144 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 145 #endif 146 #ifdef IPSEC 147 { -1, N_IPSEC6STAT, 1, NULL, 148 ipsec_stats, NULL, "ipsec6", 0, 0 }, 149 #endif 150 #ifdef notyet 151 { -1, N_PIM6STAT, 1, NULL, 152 pim6_stats, NULL, "pim6", 1, 0 }, 153 #endif 154 { -1, N_RIP6STAT, 1, NULL, 155 rip6_stats, NULL, "rip6", 1, 0 }, 156 { -1, -1, 0, NULL, 157 NULL, NULL, NULL, 0, 0 } 158 }; 159 #endif /*INET6*/ 160 161 #ifdef IPSEC 162 static struct protox pfkeyprotox[] = { 163 { -1, N_PFKEYSTAT, 1, NULL, 164 pfkey_stats, NULL, "pfkey", 0, 0 }, 165 { -1, -1, 0, NULL, 166 NULL, NULL, NULL, 0, 0 } 167 }; 168 #endif 169 170 #ifdef NETGRAPH 171 static struct protox netgraphprotox[] = { 172 { N_NGSOCKLIST, -1, 1, netgraphprotopr, 173 NULL, NULL, "ctrl", 0, 0 }, 174 { N_NGSOCKLIST, -1, 1, netgraphprotopr, 175 NULL, NULL, "data", 0, 0 }, 176 { -1, -1, 0, NULL, 177 NULL, NULL, NULL, 0, 0 } 178 }; 179 #endif 180 181 static struct protox *protoprotox[] = { 182 protox, 183 #ifdef INET6 184 ip6protox, 185 #endif 186 #ifdef IPSEC 187 pfkeyprotox, 188 #endif 189 NULL }; 190 191 static void printproto(struct protox *, const char *, bool *); 192 static void usage(void); 193 static struct protox *name2protox(const char *); 194 static struct protox *knownname(const char *); 195 196 static int kresolve_list(struct nlist *_nl); 197 198 static kvm_t *kvmd; 199 static char *nlistf = NULL, *memf = NULL; 200 201 int Aflag; /* show addresses of protocol control block */ 202 int aflag; /* show all sockets (including servers) */ 203 static int Bflag; /* show information about bpf consumers */ 204 int bflag; /* show i/f total bytes in/out */ 205 int dflag; /* show i/f dropped packets */ 206 int gflag; /* show group (multicast) routing or stats */ 207 int hflag; /* show counters in human readable format */ 208 int iflag; /* show interfaces */ 209 int Lflag; /* show size of listen queues */ 210 int mflag; /* show memory stats */ 211 int noutputs = 0; /* how much outputs before we exit */ 212 int numeric_addr; /* show addresses numerically */ 213 int numeric_port; /* show ports numerically */ 214 static int pflag; /* show given protocol */ 215 static int Qflag; /* show netisr information */ 216 int rflag; /* show routing tables (or routing stats) */ 217 int Rflag; /* show flow / RSS statistics */ 218 int sflag; /* show protocol statistics */ 219 int Wflag; /* wide display */ 220 int Tflag; /* TCP Information */ 221 int xflag; /* extra information, includes all socket buffer info */ 222 int zflag; /* zero stats */ 223 224 int interval; /* repeat interval for i/f stats */ 225 226 char *interface; /* desired i/f for stats, or NULL for all i/fs */ 227 int unit; /* unit number for above */ 228 229 static int af; /* address family */ 230 int live; /* true if we are examining a live system */ 231 232 int 233 main(int argc, char *argv[]) 234 { 235 struct protox *tp = NULL; /* for printing cblocks & stats */ 236 int ch; 237 int fib = -1; 238 char *endptr; 239 bool first = true; 240 241 af = AF_UNSPEC; 242 243 argc = xo_parse_args(argc, argv); 244 245 while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz")) 246 != -1) 247 switch(ch) { 248 case '4': 249 #ifdef INET 250 af = AF_INET; 251 #else 252 errx(1, "IPv4 support is not compiled in"); 253 #endif 254 break; 255 case '6': 256 #ifdef INET6 257 af = AF_INET6; 258 #else 259 errx(1, "IPv6 support is not compiled in"); 260 #endif 261 break; 262 case 'A': 263 Aflag = 1; 264 break; 265 case 'a': 266 aflag = 1; 267 break; 268 case 'B': 269 Bflag = 1; 270 break; 271 case 'b': 272 bflag = 1; 273 break; 274 case 'd': 275 dflag = 1; 276 break; 277 case 'F': 278 fib = strtol(optarg, &endptr, 0); 279 if (*endptr != '\0' || 280 (fib == 0 && (errno == EINVAL || errno == ERANGE))) 281 xo_errx(1, "%s: invalid fib", optarg); 282 break; 283 case 'f': 284 if (strcmp(optarg, "inet") == 0) 285 af = AF_INET; 286 #ifdef INET6 287 else if (strcmp(optarg, "inet6") == 0) 288 af = AF_INET6; 289 #endif 290 #ifdef IPSEC 291 else if (strcmp(optarg, "pfkey") == 0) 292 af = PF_KEY; 293 #endif 294 else if (strcmp(optarg, "unix") == 0 || 295 strcmp(optarg, "local") == 0) 296 af = AF_UNIX; 297 #ifdef NETGRAPH 298 else if (strcmp(optarg, "ng") == 0 299 || strcmp(optarg, "netgraph") == 0) 300 af = AF_NETGRAPH; 301 #endif 302 else if (strcmp(optarg, "link") == 0) 303 af = AF_LINK; 304 else { 305 xo_errx(1, "%s: unknown address family", 306 optarg); 307 } 308 break; 309 case 'g': 310 gflag = 1; 311 break; 312 case 'h': 313 hflag = 1; 314 break; 315 case 'I': { 316 char *cp; 317 318 iflag = 1; 319 for (cp = interface = optarg; isalpha(*cp); cp++) 320 continue; 321 unit = atoi(cp); 322 break; 323 } 324 case 'i': 325 iflag = 1; 326 break; 327 case 'L': 328 Lflag = 1; 329 break; 330 case 'M': 331 memf = optarg; 332 break; 333 case 'm': 334 mflag = 1; 335 break; 336 case 'N': 337 nlistf = optarg; 338 break; 339 case 'n': 340 numeric_addr = numeric_port = 1; 341 break; 342 case 'p': 343 if ((tp = name2protox(optarg)) == NULL) { 344 xo_errx(1, "%s: unknown or uninstrumented " 345 "protocol", optarg); 346 } 347 pflag = 1; 348 break; 349 case 'Q': 350 Qflag = 1; 351 break; 352 case 'q': 353 noutputs = atoi(optarg); 354 if (noutputs != 0) 355 noutputs++; 356 break; 357 case 'r': 358 rflag = 1; 359 break; 360 case 'R': 361 Rflag = 1; 362 break; 363 case 's': 364 ++sflag; 365 break; 366 case 'S': 367 numeric_addr = 1; 368 break; 369 case 'u': 370 af = AF_UNIX; 371 break; 372 case 'W': 373 case 'l': 374 Wflag = 1; 375 break; 376 case 'w': 377 interval = atoi(optarg); 378 iflag = 1; 379 break; 380 case 'T': 381 Tflag = 1; 382 break; 383 case 'x': 384 xflag = 1; 385 break; 386 case 'z': 387 zflag = 1; 388 break; 389 case '?': 390 default: 391 usage(); 392 } 393 argv += optind; 394 argc -= optind; 395 396 #define BACKWARD_COMPATIBILITY 397 #ifdef BACKWARD_COMPATIBILITY 398 if (*argv) { 399 if (isdigit(**argv)) { 400 interval = atoi(*argv); 401 if (interval <= 0) 402 usage(); 403 ++argv; 404 iflag = 1; 405 } 406 if (*argv) { 407 nlistf = *argv; 408 if (*++argv) 409 memf = *argv; 410 } 411 } 412 #endif 413 414 /* 415 * Discard setgid privileges if not the running kernel so that bad 416 * guys can't print interesting stuff from kernel memory. 417 */ 418 live = (nlistf == NULL && memf == NULL); 419 if (!live) { 420 if (setgid(getgid()) != 0) 421 xo_err(-1, "setgid"); 422 } 423 424 if (xflag && Tflag) 425 xo_errx(1, "-x and -T are incompatible, pick one."); 426 427 if (Bflag) { 428 if (!live) 429 usage(); 430 bpf_stats(interface); 431 xo_finish(); 432 exit(0); 433 } 434 if (mflag) { 435 if (!live) { 436 if (kread(0, NULL, 0) == 0) 437 mbpr(kvmd, nl[N_SFSTAT].n_value); 438 } else 439 mbpr(NULL, 0); 440 xo_finish(); 441 exit(0); 442 } 443 if (Qflag) { 444 if (!live) { 445 if (kread(0, NULL, 0) == 0) 446 netisr_stats(); 447 } else 448 netisr_stats(); 449 xo_finish(); 450 exit(0); 451 } 452 #if 0 453 /* 454 * Keep file descriptors open to avoid overhead 455 * of open/close on each call to get* routines. 456 */ 457 sethostent(1); 458 setnetent(1); 459 #else 460 /* 461 * This does not make sense any more with DNS being default over 462 * the files. Doing a setXXXXent(1) causes a tcp connection to be 463 * used for the queries, which is slower. 464 */ 465 #endif 466 if (iflag && !sflag) { 467 xo_open_container("statistics"); 468 intpr(NULL, af); 469 xo_close_container("statistics"); 470 xo_finish(); 471 exit(0); 472 } 473 if (rflag) { 474 xo_open_container("statistics"); 475 if (sflag) { 476 rt_stats(); 477 flowtable_stats(); 478 } else 479 routepr(fib, af); 480 xo_close_container("statistics"); 481 xo_finish(); 482 exit(0); 483 } 484 485 if (gflag) { 486 xo_open_container("statistics"); 487 if (sflag) { 488 if (af == AF_INET || af == AF_UNSPEC) 489 mrt_stats(); 490 #ifdef INET6 491 if (af == AF_INET6 || af == AF_UNSPEC) 492 mrt6_stats(); 493 #endif 494 } else { 495 if (af == AF_INET || af == AF_UNSPEC) 496 mroutepr(); 497 #ifdef INET6 498 if (af == AF_INET6 || af == AF_UNSPEC) 499 mroute6pr(); 500 #endif 501 } 502 xo_close_container("statistics"); 503 xo_finish(); 504 exit(0); 505 } 506 507 /* Load all necessary kvm symbols */ 508 kresolve_list(nl); 509 510 if (tp) { 511 xo_open_container("statistics"); 512 printproto(tp, tp->pr_name, &first); 513 if (!first) 514 xo_close_list("socket"); 515 xo_close_container("statistics"); 516 xo_finish(); 517 exit(0); 518 } 519 520 xo_open_container("statistics"); 521 if (af == AF_INET || af == AF_UNSPEC) 522 for (tp = protox; tp->pr_name; tp++) 523 printproto(tp, tp->pr_name, &first); 524 #ifdef INET6 525 if (af == AF_INET6 || af == AF_UNSPEC) 526 for (tp = ip6protox; tp->pr_name; tp++) 527 printproto(tp, tp->pr_name, &first); 528 #endif /*INET6*/ 529 #ifdef IPSEC 530 if (af == PF_KEY || af == AF_UNSPEC) 531 for (tp = pfkeyprotox; tp->pr_name; tp++) 532 printproto(tp, tp->pr_name, &first); 533 #endif /*IPSEC*/ 534 #ifdef NETGRAPH 535 if (af == AF_NETGRAPH || af == AF_UNSPEC) 536 for (tp = netgraphprotox; tp->pr_name; tp++) 537 printproto(tp, tp->pr_name, &first); 538 #endif /* NETGRAPH */ 539 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) 540 unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, 541 nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, 542 nl[N_UNP_SPHEAD].n_value, &first); 543 544 if (!first) 545 xo_close_list("socket"); 546 xo_close_container("statistics"); 547 xo_finish(); 548 exit(0); 549 } 550 551 /* 552 * Print out protocol statistics or control blocks (per sflag). 553 * If the interface was not specifically requested, and the symbol 554 * is not in the namelist, ignore this one. 555 */ 556 static void 557 printproto(struct protox *tp, const char *name, bool *first) 558 { 559 void (*pr)(u_long, const char *, int, int); 560 u_long off; 561 bool doingdblocks = false; 562 563 if (sflag) { 564 if (iflag) { 565 if (tp->pr_istats) 566 intpr(tp->pr_istats, af); 567 else if (pflag) 568 xo_message("%s: no per-interface stats routine", 569 tp->pr_name); 570 return; 571 } else { 572 pr = tp->pr_stats; 573 if (!pr) { 574 if (pflag) 575 xo_message("%s: no stats routine", 576 tp->pr_name); 577 return; 578 } 579 if (tp->pr_usesysctl && live) 580 off = 0; 581 else if (tp->pr_sindex < 0) { 582 if (pflag) 583 xo_message("%s: stats routine doesn't " 584 "work on cores", tp->pr_name); 585 return; 586 } else 587 off = nl[tp->pr_sindex].n_value; 588 } 589 } else { 590 doingdblocks = true; 591 pr = tp->pr_cblocks; 592 if (!pr) { 593 if (pflag) 594 xo_message("%s: no PCB routine", tp->pr_name); 595 return; 596 } 597 if (tp->pr_usesysctl && live) 598 off = 0; 599 else if (tp->pr_index < 0) { 600 if (pflag) 601 xo_message("%s: PCB routine doesn't work on " 602 "cores", tp->pr_name); 603 return; 604 } else 605 off = nl[tp->pr_index].n_value; 606 } 607 if (pr != NULL && (off || (live && tp->pr_usesysctl) || 608 af != AF_UNSPEC)) { 609 if (doingdblocks && *first) { 610 xo_open_list("socket"); 611 *first = false; 612 } 613 614 (*pr)(off, name, af, tp->pr_protocol); 615 } 616 } 617 618 static int 619 kvmd_init(void) 620 { 621 char errbuf[_POSIX2_LINE_MAX]; 622 623 if (kvmd != NULL) 624 return (0); 625 626 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 627 if (setgid(getgid()) != 0) 628 xo_err(-1, "setgid"); 629 630 if (kvmd == NULL) { 631 xo_warnx("kvm not available: %s", errbuf); 632 return (-1); 633 } 634 635 return (0); 636 } 637 638 /* 639 * Resolve symbol list, return 0 on success. 640 */ 641 static int 642 kresolve_list(struct nlist *_nl) 643 { 644 645 if ((kvmd == NULL) && (kvmd_init() != 0)) 646 return (-1); 647 648 if (_nl[0].n_type != 0) 649 return (0); 650 651 if (kvm_nlist(kvmd, _nl) < 0) { 652 if (nlistf) 653 xo_errx(1, "%s: kvm_nlist: %s", nlistf, 654 kvm_geterr(kvmd)); 655 else 656 xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 657 } 658 659 return (0); 660 } 661 662 /* 663 * Wrapper of kvm_dpcpu_setcpu(). 664 */ 665 void 666 kset_dpcpu(u_int cpuid) 667 { 668 669 if ((kvmd == NULL) && (kvmd_init() != 0)) 670 xo_errx(-1, "%s: kvm is not available", __func__); 671 672 if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) 673 xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, 674 cpuid, kvm_geterr(kvmd)); 675 return; 676 } 677 678 /* 679 * Read kernel memory, return 0 on success. 680 */ 681 int 682 kread(u_long addr, void *buf, size_t size) 683 { 684 685 if (kvmd_init() < 0) 686 return (-1); 687 688 if (!buf) 689 return (0); 690 if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { 691 xo_warnx("%s", kvm_geterr(kvmd)); 692 return (-1); 693 } 694 return (0); 695 } 696 697 /* 698 * Read single counter(9). 699 */ 700 uint64_t 701 kread_counter(u_long addr) 702 { 703 704 if (kvmd_init() < 0) 705 return (-1); 706 707 return (kvm_counter_u64_fetch(kvmd, addr)); 708 } 709 710 /* 711 * Read an array of N counters in kernel memory into array of N uint64_t's. 712 */ 713 int 714 kread_counters(u_long addr, void *buf, size_t size) 715 { 716 uint64_t *c; 717 u_long *counters; 718 size_t i, n; 719 720 if (kvmd_init() < 0) 721 return (-1); 722 723 if (size % sizeof(uint64_t) != 0) { 724 xo_warnx("kread_counters: invalid counter set size"); 725 return (-1); 726 } 727 728 n = size / sizeof(uint64_t); 729 if ((counters = malloc(n * sizeof(u_long))) == NULL) 730 xo_err(-1, "malloc"); 731 if (kread(addr, counters, n * sizeof(u_long)) < 0) { 732 free(counters); 733 return (-1); 734 } 735 736 c = buf; 737 for (i = 0; i < n; i++) 738 c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); 739 740 free(counters); 741 return (0); 742 } 743 744 const char * 745 plural(uintmax_t n) 746 { 747 return (n != 1 ? "s" : ""); 748 } 749 750 const char * 751 plurales(uintmax_t n) 752 { 753 return (n != 1 ? "es" : ""); 754 } 755 756 const char * 757 pluralies(uintmax_t n) 758 { 759 return (n != 1 ? "ies" : "y"); 760 } 761 762 /* 763 * Find the protox for the given "well-known" name. 764 */ 765 static struct protox * 766 knownname(const char *name) 767 { 768 struct protox **tpp, *tp; 769 770 for (tpp = protoprotox; *tpp; tpp++) 771 for (tp = *tpp; tp->pr_name; tp++) 772 if (strcmp(tp->pr_name, name) == 0) 773 return (tp); 774 return (NULL); 775 } 776 777 /* 778 * Find the protox corresponding to name. 779 */ 780 static struct protox * 781 name2protox(const char *name) 782 { 783 struct protox *tp; 784 char **alias; /* alias from p->aliases */ 785 struct protoent *p; 786 787 /* 788 * Try to find the name in the list of "well-known" names. If that 789 * fails, check if name is an alias for an Internet protocol. 790 */ 791 if ((tp = knownname(name)) != NULL) 792 return (tp); 793 794 setprotoent(1); /* make protocol lookup cheaper */ 795 while ((p = getprotoent()) != NULL) { 796 /* assert: name not same as p->name */ 797 for (alias = p->p_aliases; *alias; alias++) 798 if (strcmp(name, *alias) == 0) { 799 endprotoent(); 800 return (knownname(p->p_name)); 801 } 802 } 803 endprotoent(); 804 return (NULL); 805 } 806 807 static void 808 usage(void) 809 { 810 (void)xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 811 "usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n" 812 " [-M core] [-N system]", 813 " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" 814 " [-M core] [-N system]", 815 " netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" 816 " [-q howmany]", 817 " netstat -s [-46sz] [-f protocol_family | -p protocol]\n" 818 " [-M core] [-N system]", 819 " netstat -i | -I interface -s [-46s]\n" 820 " [-f protocol_family | -p protocol] [-M core] [-N system]", 821 " netstat -m [-M core] [-N system]", 822 " netstat -B [-z] [-I interface]", 823 " netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" 824 " [-M core] [-N system]", 825 " netstat -rs [-s] [-M core] [-N system]", 826 " netstat -g [-46W] [-f address_family] [-M core] [-N system]", 827 " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", 828 " netstat -Q"); 829 xo_finish(); 830 exit(1); 831 } 832