1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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. 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. 18 * 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. 30 */ 31 32 #ifndef lint 33 static char const copyright[] = 34 "@(#) Copyright (c) 1983, 1988, 1993\n\ 35 Regents of the University of California. All rights reserved.\n"; 36 #endif /* not lint */ 37 38 #if 0 39 #ifndef lint 40 static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; 41 #endif /* not lint */ 42 #endif 43 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 #include <sys/param.h> 48 #include <sys/file.h> 49 #include <sys/protosw.h> 50 #include <sys/socket.h> 51 #include <sys/socketvar.h> 52 #include <sys/sysctl.h> 53 54 #include <netinet/in.h> 55 56 #ifdef NETGRAPH 57 #include <netgraph/ng_socket.h> 58 #endif 59 60 #include <ctype.h> 61 #include <err.h> 62 #include <errno.h> 63 #ifndef FSTACK 64 #include <kvm.h> 65 #endif 66 #include <limits.h> 67 #include <netdb.h> 68 #include <nlist.h> 69 #include <paths.h> 70 #include <stdint.h> 71 #include <stdio.h> 72 #include <stdlib.h> 73 #include <stdbool.h> 74 #include <string.h> 75 #include <unistd.h> 76 #include "netstat.h" 77 #include "nl_defs.h" 78 #include <libxo/xo.h> 79 80 #ifdef FSTACK 81 #include "ff_ipc.h" 82 #endif 83 84 static struct protox { 85 int pr_index; /* index into nlist of cb head */ 86 int pr_sindex; /* index into nlist of stat block */ 87 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 88 void (*pr_cblocks)(u_long, const char *, int, int); 89 /* control blocks printing routine */ 90 void (*pr_stats)(u_long, const char *, int, int); 91 /* statistics printing routine */ 92 void (*pr_istats)(char *); /* per/if statistics printing routine */ 93 const char *pr_name; /* well-known name */ 94 int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ 95 int pr_protocol; 96 } protox[] = { 97 { N_TCBINFO, N_TCPSTAT, 1, protopr, 98 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 99 { N_UDBINFO, N_UDPSTAT, 1, protopr, 100 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 101 #ifdef SCTP 102 { -1, N_SCTPSTAT, 1, sctp_protopr, 103 sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, 104 #endif 105 #ifdef SDP 106 { -1, -1, 1, protopr, 107 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 108 #endif 109 { N_DIVCBINFO, -1, 1, protopr, 110 NULL, NULL, "divert", 1, IPPROTO_DIVERT }, 111 { N_RIPCBINFO, N_IPSTAT, 1, protopr, 112 ip_stats, NULL, "ip", 1, IPPROTO_RAW }, 113 { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, 114 icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, 115 { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, 116 igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, 117 #ifdef IPSEC 118 { -1, N_IPSEC4STAT, 1, NULL, /* keep as compat */ 119 ipsec_stats, NULL, "ipsec", 1, 0}, 120 { -1, N_AHSTAT, 1, NULL, 121 ah_stats, NULL, "ah", 1, 0}, 122 { -1, N_ESPSTAT, 1, NULL, 123 esp_stats, NULL, "esp", 1, 0}, 124 { -1, N_IPCOMPSTAT, 1, NULL, 125 ipcomp_stats, NULL, "ipcomp", 1, 0}, 126 #endif 127 { N_RIPCBINFO, N_PIMSTAT, 1, protopr, 128 pim_stats, NULL, "pim", 1, IPPROTO_PIM }, 129 { -1, N_CARPSTATS, 1, NULL, 130 carp_stats, NULL, "carp", 1, 0 }, 131 #ifdef PF 132 { -1, N_PFSYNCSTATS, 1, NULL, 133 pfsync_stats, NULL, "pfsync", 1, 0 }, 134 #endif 135 { -1, N_ARPSTAT, 1, NULL, 136 arp_stats, NULL, "arp", 1, 0 }, 137 { -1, -1, 0, NULL, 138 NULL, NULL, NULL, 0, 0 } 139 }; 140 141 #ifdef INET6 142 static struct protox ip6protox[] = { 143 { N_TCBINFO, N_TCPSTAT, 1, protopr, 144 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 145 { N_UDBINFO, N_UDPSTAT, 1, protopr, 146 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 147 { N_RIPCBINFO, N_IP6STAT, 1, protopr, 148 ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, 149 { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, 150 icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, 151 #ifdef SDP 152 { -1, -1, 1, protopr, 153 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 154 #endif 155 #ifdef IPSEC 156 { -1, N_IPSEC6STAT, 1, NULL, 157 ipsec_stats, NULL, "ipsec6", 1, 0 }, 158 #endif 159 #ifdef notyet 160 { -1, N_PIM6STAT, 1, NULL, 161 pim6_stats, NULL, "pim6", 1, 0 }, 162 #endif 163 { -1, N_RIP6STAT, 1, NULL, 164 rip6_stats, NULL, "rip6", 1, 0 }, 165 { -1, -1, 0, NULL, 166 NULL, NULL, NULL, 0, 0 } 167 }; 168 #endif /*INET6*/ 169 170 #ifdef IPSEC 171 static struct protox pfkeyprotox[] = { 172 { -1, N_PFKEYSTAT, 1, NULL, 173 pfkey_stats, NULL, "pfkey", 0, 0 }, 174 { -1, -1, 0, NULL, 175 NULL, NULL, NULL, 0, 0 } 176 }; 177 #endif 178 179 #ifdef NETGRAPH 180 static struct protox netgraphprotox[] = { 181 { N_NGSOCKLIST, -1, 1, netgraphprotopr, 182 NULL, NULL, "ctrl", 0, 0 }, 183 { N_NGSOCKLIST, -1, 1, netgraphprotopr, 184 NULL, NULL, "data", 0, 0 }, 185 { -1, -1, 0, NULL, 186 NULL, NULL, NULL, 0, 0 } 187 }; 188 #endif 189 190 static struct protox *protoprotox[] = { 191 protox, 192 #ifdef INET6 193 ip6protox, 194 #endif 195 #ifdef IPSEC 196 pfkeyprotox, 197 #endif 198 NULL }; 199 200 static void printproto(struct protox *, const char *, bool *); 201 static void usage(void); 202 static struct protox *name2protox(const char *); 203 static struct protox *knownname(const char *); 204 205 #ifndef FSTACK 206 static int kresolve_list(struct nlist *_nl); 207 208 static kvm_t *kvmd; 209 #endif 210 static char *nlistf = NULL, *memf = NULL; 211 212 int Aflag; /* show addresses of protocol control block */ 213 int aflag; /* show all sockets (including servers) */ 214 static int Bflag; /* show information about bpf consumers */ 215 int bflag; /* show i/f total bytes in/out */ 216 int cflag; /* show TCP congestion control stack */ 217 int Cflag; /* show congestion control algo and vars */ 218 int dflag; /* show i/f dropped packets */ 219 int gflag; /* show group (multicast) routing or stats */ 220 int hflag; /* show counters in human readable format */ 221 int iflag; /* show interfaces */ 222 int Lflag; /* show size of listen queues */ 223 int mflag; /* show memory stats */ 224 int noutputs = 0; /* how much outputs before we exit */ 225 int numeric_addr; /* show addresses numerically */ 226 int numeric_port; /* show ports numerically */ 227 int Oflag; /* show nhgrp objects*/ 228 int oflag; /* show nexthop objects*/ 229 int Pflag; /* show TCP log ID */ 230 static int pflag; /* show given protocol */ 231 static int Qflag; /* show netisr information */ 232 int rflag; /* show routing tables (or routing stats) */ 233 int Rflag; /* show flow / RSS statistics */ 234 int sflag; /* show protocol statistics */ 235 int Wflag; /* wide display */ 236 int Tflag; /* TCP Information */ 237 int xflag; /* extra information, includes all socket buffer info */ 238 int zflag; /* zero stats */ 239 240 int interval; /* repeat interval for i/f stats */ 241 242 char *interface; /* desired i/f for stats, or NULL for all i/fs */ 243 int unit; /* unit number for above */ 244 245 static int af; /* address family */ 246 int live; /* true if we are examining a live system */ 247 248 int 249 main(int argc, char *argv[]) 250 { 251 struct protox *tp = NULL; /* for printing cblocks & stats */ 252 int ch; 253 int fib = -1; 254 char *endptr; 255 bool first = true; 256 257 #ifdef FSTACK 258 ff_ipc_init(); 259 #endif 260 261 af = AF_UNSPEC; 262 263 argc = xo_parse_args(argc, argv); 264 if (argc < 0) 265 #ifndef FSTACK 266 exit(EXIT_FAILURE); 267 268 while ((ch = getopt(argc, argv, "46AaBbCcdF:f:ghI:iLlM:mN:nOoPp:Qq:RrSTsuWw:xz")) 269 #else 270 { 271 ff_ipc_exit(); 272 exit(EXIT_FAILURE); 273 } 274 275 while ((ch = getopt(argc, argv, "46AaBbCcdF:f:ghI:iLlnOoPp:Qq:RrSTsuWw:xzt:")) 276 #endif 277 != -1) 278 switch(ch) { 279 case '4': 280 #ifdef INET 281 af = AF_INET; 282 #else 283 errx(1, "IPv4 support is not compiled in"); 284 #endif 285 break; 286 case '6': 287 #ifdef INET6 288 af = AF_INET6; 289 #else 290 errx(1, "IPv6 support is not compiled in"); 291 #endif 292 break; 293 case 'A': 294 Aflag = 1; 295 break; 296 case 'a': 297 aflag = 1; 298 break; 299 case 'B': 300 Bflag = 1; 301 break; 302 case 'b': 303 bflag = 1; 304 break; 305 case 'c': 306 cflag = 1; 307 break; 308 case 'C': 309 Cflag = 1; 310 break; 311 case 'd': 312 dflag = 1; 313 break; 314 case 'F': 315 fib = strtol(optarg, &endptr, 0); 316 if (*endptr != '\0' || 317 (fib == 0 && (errno == EINVAL || errno == ERANGE))) 318 xo_errx(1, "%s: invalid fib", optarg); 319 break; 320 case 'f': 321 if (strcmp(optarg, "inet") == 0) 322 af = AF_INET; 323 #ifdef INET6 324 else if (strcmp(optarg, "inet6") == 0) 325 af = AF_INET6; 326 #endif 327 #ifdef IPSEC 328 else if (strcmp(optarg, "pfkey") == 0) 329 af = PF_KEY; 330 #endif 331 else if (strcmp(optarg, "unix") == 0 || 332 strcmp(optarg, "local") == 0) 333 af = AF_UNIX; 334 #ifdef NETGRAPH 335 else if (strcmp(optarg, "ng") == 0 336 || strcmp(optarg, "netgraph") == 0) 337 af = AF_NETGRAPH; 338 #endif 339 else if (strcmp(optarg, "link") == 0) 340 af = AF_LINK; 341 else { 342 xo_errx(1, "%s: unknown address family", 343 optarg); 344 } 345 break; 346 case 'g': 347 gflag = 1; 348 break; 349 case 'h': 350 hflag = 1; 351 break; 352 case 'I': { 353 char *cp; 354 355 iflag = 1; 356 for (cp = interface = optarg; isalpha(*cp); cp++) 357 continue; 358 unit = atoi(cp); 359 break; 360 } 361 case 'i': 362 iflag = 1; 363 break; 364 case 'L': 365 Lflag = 1; 366 break; 367 #ifndef FSTACK 368 case 'M': 369 memf = optarg; 370 break; 371 case 'm': 372 mflag = 1; 373 break; 374 case 'N': 375 nlistf = optarg; 376 break; 377 #endif 378 case 'n': 379 numeric_addr = numeric_port = 1; 380 break; 381 case 'o': 382 oflag = 1; 383 break; 384 case 'O': 385 Oflag = 1; 386 break; 387 case 'P': 388 Pflag = 1; 389 break; 390 case 'p': 391 if ((tp = name2protox(optarg)) == NULL) { 392 xo_errx(1, "%s: unknown or uninstrumented " 393 "protocol", optarg); 394 } 395 pflag = 1; 396 break; 397 case 'Q': 398 Qflag = 1; 399 break; 400 case 'q': 401 noutputs = atoi(optarg); 402 if (noutputs != 0) 403 noutputs++; 404 break; 405 case 'r': 406 rflag = 1; 407 break; 408 case 'R': 409 Rflag = 1; 410 break; 411 case 's': 412 ++sflag; 413 break; 414 case 'S': 415 numeric_addr = 1; 416 break; 417 case 'u': 418 af = AF_UNIX; 419 break; 420 case 'W': 421 case 'l': 422 Wflag = 1; 423 break; 424 case 'w': 425 interval = atoi(optarg); 426 iflag = 1; 427 break; 428 case 'T': 429 Tflag = 1; 430 break; 431 case 'x': 432 xflag = 1; 433 break; 434 case 'z': 435 zflag = 1; 436 break; 437 #ifdef FSTACK 438 case 't': 439 ff_set_proc_id(atoi(optarg)); 440 break; 441 #endif 442 case '?': 443 default: 444 usage(); 445 } 446 argv += optind; 447 argc -= optind; 448 449 #define BACKWARD_COMPATIBILITY 450 #ifdef BACKWARD_COMPATIBILITY 451 if (*argv) { 452 if (isdigit(**argv)) { 453 interval = atoi(*argv); 454 if (interval <= 0) 455 usage(); 456 ++argv; 457 iflag = 1; 458 } 459 if (*argv) { 460 nlistf = *argv; 461 if (*++argv) 462 memf = *argv; 463 } 464 } 465 #endif 466 467 /* 468 * Discard setgid privileges if not the running kernel so that bad 469 * guys can't print interesting stuff from kernel memory. 470 */ 471 #ifndef FSTACK 472 live = (nlistf == NULL && memf == NULL); 473 #else 474 live = 1; 475 #endif 476 if (!live) { 477 if (setgid(getgid()) != 0) 478 xo_err(-1, "setgid"); 479 #ifndef FSTACK 480 /* Load all necessary kvm symbols */ 481 kresolve_list(nl); 482 #endif 483 } 484 485 if (xflag && Tflag) 486 xo_errx(1, "-x and -T are incompatible, pick one."); 487 488 if (Bflag) { 489 if (!live) 490 usage(); 491 bpf_stats(interface); 492 xo_finish(); 493 #ifdef FSTACK 494 ff_ipc_exit(); 495 #endif 496 exit(0); 497 } 498 if (mflag) { 499 if (!live) { 500 #ifndef FSTACK 501 if (kread(0, NULL, 0) == 0) 502 mbpr(kvmd, nl[N_SFSTAT].n_value); 503 #endif 504 } else 505 mbpr(NULL, 0); 506 xo_finish(); 507 #ifdef FSTACK 508 ff_ipc_exit(); 509 #endif 510 exit(0); 511 } 512 if (Qflag) { 513 if (!live) { 514 #ifndef FSTACK 515 if (kread(0, NULL, 0) == 0) 516 netisr_stats(); 517 #endif 518 } else 519 netisr_stats(); 520 xo_finish(); 521 #ifdef FSTACK 522 ff_ipc_exit(); 523 #endif 524 exit(0); 525 } 526 #if 0 527 /* 528 * Keep file descriptors open to avoid overhead 529 * of open/close on each call to get* routines. 530 */ 531 sethostent(1); 532 setnetent(1); 533 #else 534 /* 535 * This does not make sense any more with DNS being default over 536 * the files. Doing a setXXXXent(1) causes a tcp connection to be 537 * used for the queries, which is slower. 538 */ 539 #endif 540 if (iflag && !sflag) { 541 xo_open_container("statistics"); 542 intpr(NULL, af); 543 xo_close_container("statistics"); 544 xo_finish(); 545 #ifdef FSTACK 546 ff_ipc_exit(); 547 #endif 548 exit(0); 549 } 550 if (rflag) { 551 xo_open_container("statistics"); 552 if (sflag) { 553 if (live) { 554 #ifndef FSTACK 555 kresolve_list(nl); 556 #endif 557 } 558 rt_stats(); 559 } else 560 routepr(fib, af); 561 xo_close_container("statistics"); 562 xo_finish(); 563 #ifdef FSTACK 564 ff_ipc_exit(); 565 #endif 566 exit(0); 567 } 568 if (oflag) { 569 xo_open_container("statistics"); 570 nhops_print(fib, af); 571 xo_close_container("statistics"); 572 xo_finish(); 573 #ifdef FSTACK 574 ff_ipc_exit(); 575 #endif 576 exit(0); 577 } 578 if (Oflag) { 579 xo_open_container("statistics"); 580 nhgrp_print(fib, af); 581 xo_close_container("statistics"); 582 xo_finish(); 583 #ifdef FSTACK 584 ff_ipc_exit(); 585 #endif 586 exit(0); 587 } 588 589 590 591 if (gflag) { 592 xo_open_container("statistics"); 593 if (sflag) { 594 if (af == AF_INET || af == AF_UNSPEC) 595 mrt_stats(); 596 #ifdef INET6 597 if (af == AF_INET6 || af == AF_UNSPEC) 598 mrt6_stats(); 599 #endif 600 } else { 601 if (af == AF_INET || af == AF_UNSPEC) 602 mroutepr(); 603 #ifdef INET6 604 if (af == AF_INET6 || af == AF_UNSPEC) 605 mroute6pr(); 606 #endif 607 } 608 xo_close_container("statistics"); 609 xo_finish(); 610 #ifdef FSTACK 611 ff_ipc_exit(); 612 #endif 613 exit(0); 614 } 615 616 if (tp) { 617 xo_open_container("statistics"); 618 printproto(tp, tp->pr_name, &first); 619 if (!first) 620 xo_close_list("socket"); 621 xo_close_container("statistics"); 622 xo_finish(); 623 #ifdef FSTACK 624 ff_ipc_exit(); 625 #endif 626 exit(0); 627 } 628 629 xo_open_container("statistics"); 630 if (af == AF_INET || af == AF_UNSPEC) 631 for (tp = protox; tp->pr_name; tp++) 632 printproto(tp, tp->pr_name, &first); 633 #ifdef INET6 634 if (af == AF_INET6 || af == AF_UNSPEC) 635 for (tp = ip6protox; tp->pr_name; tp++) 636 printproto(tp, tp->pr_name, &first); 637 #endif /*INET6*/ 638 #ifdef IPSEC 639 if (af == PF_KEY || af == AF_UNSPEC) 640 for (tp = pfkeyprotox; tp->pr_name; tp++) 641 printproto(tp, tp->pr_name, &first); 642 #endif /*IPSEC*/ 643 #ifdef NETGRAPH 644 if (af == AF_NETGRAPH || af == AF_UNSPEC) 645 for (tp = netgraphprotox; tp->pr_name; tp++) 646 printproto(tp, tp->pr_name, &first); 647 #endif /* NETGRAPH */ 648 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) 649 unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, 650 nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, 651 nl[N_UNP_SPHEAD].n_value, &first); 652 653 if (!first) 654 xo_close_list("socket"); 655 xo_close_container("statistics"); 656 xo_finish(); 657 658 #ifdef FSTACK 659 ff_ipc_exit(); 660 #endif 661 662 exit(0); 663 } 664 665 static int 666 fetch_stats_internal(const char *sysctlname, u_long off, void *stats, 667 size_t len, kreadfn_t kreadfn, int zero) 668 { 669 int error; 670 671 if (live) { 672 memset(stats, 0, len); 673 if (zero) 674 error = sysctlbyname(sysctlname, NULL, NULL, stats, 675 len); 676 else 677 error = sysctlbyname(sysctlname, stats, &len, NULL, 0); 678 if (error == -1 && errno != ENOENT) 679 xo_warn("sysctl %s", sysctlname); 680 } else { 681 if (off == 0) 682 return (1); 683 error = kreadfn(off, stats, len); 684 } 685 return (error); 686 } 687 688 int 689 fetch_stats(const char *sysctlname, u_long off, void *stats, 690 size_t len, kreadfn_t kreadfn) 691 { 692 693 return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 694 zflag)); 695 } 696 697 int 698 fetch_stats_ro(const char *sysctlname, u_long off, void *stats, 699 size_t len, kreadfn_t kreadfn) 700 { 701 702 return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0)); 703 } 704 705 /* 706 * Print out protocol statistics or control blocks (per sflag). 707 * If the interface was not specifically requested, and the symbol 708 * is not in the namelist, ignore this one. 709 */ 710 static void 711 printproto(struct protox *tp, const char *name, bool *first) 712 { 713 void (*pr)(u_long, const char *, int, int); 714 u_long off; 715 bool doingdblocks = false; 716 717 if (sflag) { 718 if (iflag) { 719 if (tp->pr_istats) 720 intpr(tp->pr_istats, af); 721 else if (pflag) 722 xo_message("%s: no per-interface stats routine", 723 tp->pr_name); 724 return; 725 } else { 726 pr = tp->pr_stats; 727 if (!pr) { 728 if (pflag) 729 xo_message("%s: no stats routine", 730 tp->pr_name); 731 return; 732 } 733 if (tp->pr_usesysctl && live) 734 off = 0; 735 else if (tp->pr_sindex < 0) { 736 if (pflag) 737 xo_message("%s: stats routine doesn't " 738 "work on cores", tp->pr_name); 739 return; 740 } else 741 off = nl[tp->pr_sindex].n_value; 742 } 743 } else { 744 doingdblocks = true; 745 pr = tp->pr_cblocks; 746 if (!pr) { 747 if (pflag) 748 xo_message("%s: no PCB routine", tp->pr_name); 749 return; 750 } 751 if (tp->pr_usesysctl && live) 752 off = 0; 753 else if (tp->pr_index < 0) { 754 if (pflag) 755 xo_message("%s: PCB routine doesn't work on " 756 "cores", tp->pr_name); 757 return; 758 } else 759 off = nl[tp->pr_index].n_value; 760 } 761 if (pr != NULL && (off || (live && tp->pr_usesysctl) || 762 af != AF_UNSPEC)) { 763 if (doingdblocks && *first) { 764 xo_open_list("socket"); 765 *first = false; 766 } 767 768 (*pr)(off, name, af, tp->pr_protocol); 769 } 770 } 771 772 #ifndef FSTACK 773 static int 774 kvmd_init(void) 775 { 776 char errbuf[_POSIX2_LINE_MAX]; 777 778 if (kvmd != NULL) 779 return (0); 780 781 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 782 if (setgid(getgid()) != 0) 783 xo_err(-1, "setgid"); 784 785 if (kvmd == NULL) { 786 xo_warnx("kvm not available: %s", errbuf); 787 return (-1); 788 } 789 790 return (0); 791 } 792 793 /* 794 * Resolve symbol list, return 0 on success. 795 */ 796 static int 797 kresolve_list(struct nlist *_nl) 798 { 799 800 if ((kvmd == NULL) && (kvmd_init() != 0)) 801 return (-1); 802 803 if (_nl[0].n_type != 0) 804 return (0); 805 806 if (kvm_nlist(kvmd, _nl) < 0) { 807 if (nlistf) 808 xo_errx(1, "%s: kvm_nlist: %s", nlistf, 809 kvm_geterr(kvmd)); 810 else 811 xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 812 } 813 814 return (0); 815 } 816 817 /* 818 * Wrapper of kvm_dpcpu_setcpu(). 819 */ 820 void 821 kset_dpcpu(u_int cpuid) 822 { 823 824 if ((kvmd == NULL) && (kvmd_init() != 0)) 825 xo_errx(-1, "%s: kvm is not available", __func__); 826 827 if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0) 828 xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__, 829 cpuid, kvm_geterr(kvmd)); 830 return; 831 } 832 833 /* 834 * Read kernel memory, return 0 on success. 835 */ 836 int 837 kread(u_long addr, void *buf, size_t size) 838 { 839 840 if (kvmd_init() < 0) 841 return (-1); 842 843 if (!buf) 844 return (0); 845 if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { 846 xo_warnx("%s", kvm_geterr(kvmd)); 847 return (-1); 848 } 849 return (0); 850 } 851 852 /* 853 * Read single counter(9). 854 */ 855 uint64_t 856 kread_counter(u_long addr) 857 { 858 859 if (kvmd_init() < 0) 860 return (-1); 861 862 return (kvm_counter_u64_fetch(kvmd, addr)); 863 } 864 865 /* 866 * Read an array of N counters in kernel memory into array of N uint64_t's. 867 */ 868 int 869 kread_counters(u_long addr, void *buf, size_t size) 870 { 871 uint64_t *c; 872 u_long *counters; 873 size_t i, n; 874 875 if (kvmd_init() < 0) 876 return (-1); 877 878 if (size % sizeof(uint64_t) != 0) { 879 xo_warnx("kread_counters: invalid counter set size"); 880 return (-1); 881 } 882 883 n = size / sizeof(uint64_t); 884 if ((counters = malloc(n * sizeof(u_long))) == NULL) 885 xo_err(-1, "malloc"); 886 if (kread(addr, counters, n * sizeof(u_long)) < 0) { 887 free(counters); 888 return (-1); 889 } 890 891 c = buf; 892 for (i = 0; i < n; i++) 893 c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); 894 895 free(counters); 896 return (0); 897 } 898 899 #else 900 int 901 kread(u_long addr, void *buf, size_t size) 902 { 903 return 0; 904 } 905 906 uint64_t 907 kread_counter(u_long addr) 908 { 909 return 0; 910 } 911 912 int 913 kread_counters(u_long addr, void *buf, size_t size) 914 { 915 return 0; 916 } 917 void 918 kset_dpcpu(u_int cpuid) 919 { 920 921 } 922 923 #endif 924 925 const char * 926 plural(uintmax_t n) 927 { 928 return (n != 1 ? "s" : ""); 929 } 930 931 const char * 932 plurales(uintmax_t n) 933 { 934 return (n != 1 ? "es" : ""); 935 } 936 937 const char * 938 pluralies(uintmax_t n) 939 { 940 return (n != 1 ? "ies" : "y"); 941 } 942 943 /* 944 * Find the protox for the given "well-known" name. 945 */ 946 static struct protox * 947 knownname(const char *name) 948 { 949 struct protox **tpp, *tp; 950 951 for (tpp = protoprotox; *tpp; tpp++) 952 for (tp = *tpp; tp->pr_name; tp++) 953 if (strcmp(tp->pr_name, name) == 0) 954 return (tp); 955 return (NULL); 956 } 957 958 /* 959 * Find the protox corresponding to name. 960 */ 961 static struct protox * 962 name2protox(const char *name) 963 { 964 struct protox *tp; 965 char **alias; /* alias from p->aliases */ 966 struct protoent *p; 967 968 /* 969 * Try to find the name in the list of "well-known" names. If that 970 * fails, check if name is an alias for an Internet protocol. 971 */ 972 if ((tp = knownname(name)) != NULL) 973 return (tp); 974 975 setprotoent(1); /* make protocol lookup cheaper */ 976 while ((p = getprotoent()) != NULL) { 977 /* assert: name not same as p->name */ 978 for (alias = p->p_aliases; *alias; alias++) 979 if (strcmp(name, *alias) == 0) { 980 endprotoent(); 981 return (knownname(p->p_name)); 982 } 983 } 984 endprotoent(); 985 return (NULL); 986 } 987 988 static void 989 usage(void) 990 { 991 (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", 992 #ifndef FSTACK 993 "usage: netstat [-46AaCcLnRSTWx] [-f protocol_family | -p protocol]\n" 994 " [-M core] [-N system]", 995 " netstat -i | -I interface [-46abdhnW] [-f address_family]\n" 996 " [-M core] [-N system]", 997 " netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n" 998 " [-q howmany]", 999 " netstat -s [-46sz] [-f protocol_family | -p protocol]\n" 1000 " [-M core] [-N system]", 1001 " netstat -i | -I interface -s [-46s]\n" 1002 " [-f protocol_family | -p protocol] [-M core] [-N system]", 1003 " netstat -m [-M core] [-N system]", 1004 " netstat -B [-z] [-I interface]", 1005 " netstat -r [-46AnW] [-F fibnum] [-f address_family]\n" 1006 " [-M core] [-N system]", 1007 " netstat -rs [-s] [-M core] [-N system]", 1008 " netstat -g [-46W] [-f address_family] [-M core] [-N system]", 1009 " netstat -gs [-46s] [-f address_family] [-M core] [-N system]", 1010 " netstat -Q"); 1011 #else 1012 "usage: netstat -t <f-stack proc_id> [-46AaLnRSTWx] [-f protocol_family | -p protocol]", 1013 " netstat -t <f-stack proc_id> -i | -I interface [-46abdhnW] [-f address_family]", 1014 " netstat -t <f-stack proc_id> -w wait [-I interface] [-46d] [-q howmany]", 1015 " netstat -t <f-stack proc_id> -s [-46sz] [-f protocol_family | -p protocol]", 1016 " netstat -t <f-stack proc_id> -i | -I interface -s [-46s]\n" 1017 " [-f protocol_family | -p protocol]", 1018 " netstat -t <f-stack proc_id> -B [-z] [-I interface]", 1019 " netstat -t <f-stack proc_id> -r [-46AnW] [-F fibnum] [-f address_family]", 1020 " netstat -t <f-stack proc_id> -rs [-s]", 1021 " netstat -t <f-stack proc_id> -g [-46W] [-f address_family]", 1022 " netstat -t <f-stack proc_id> -gs [-46s] [-f address_family]", 1023 " netstat -t <f-stack proc_id> -Q"); 1024 1025 #endif 1026 xo_finish(); 1027 #ifdef FSTACK 1028 ff_ipc_exit(); 1029 #endif 1030 exit(1); 1031 } 1032