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 31char 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 38static 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: stable/10/usr.bin/netstat/main.c 312278 2017-01-16 09:12:40Z smh $"); 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#include <sys/sysctl.h> 51 52#include <netinet/in.h> 53 54#ifdef NETGRAPH 55#include <netgraph/ng_socket.h> 56#endif 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 <stdint.h> 67#include <stdio.h> 68#include <stdlib.h> 69#include <string.h> 70#include <unistd.h> 71#include "netstat.h" 72 73static struct nlist nl[] = { 74#define N_IFNET 0 75 { .n_name = "_ifnet" }, /* XXXGL: can be deleted */ 76#define N_RTSTAT 1 77 { .n_name = "_rtstat" }, 78#define N_RTREE 2 79 { .n_name = "_rt_tables"}, 80#define N_MRTSTAT 3 81 { .n_name = "_mrtstat" }, 82#define N_MFCHASHTBL 4 83 { .n_name = "_mfchashtbl" }, 84#define N_VIFTABLE 5 85 { .n_name = "_viftable" }, 86#define N_IPX 6 87 { .n_name = "_ipxpcb_list"}, 88#define N_IPXSTAT 7 89 { .n_name = "_ipxstat"}, 90#define N_SPXSTAT 8 91 { .n_name = "_spx_istat"}, 92#define N_DDPSTAT 9 93 { .n_name = "_ddpstat"}, 94#define N_DDPCB 10 95 { .n_name = "_ddpcb"}, 96#define N_NGSOCKS 11 97 { .n_name = "_ngsocklist"}, 98#define N_IP6STAT 12 99 { .n_name = "_ip6stat" }, 100#define N_ICMP6STAT 13 101 { .n_name = "_icmp6stat" }, 102#define N_IPSECSTAT 14 103 { .n_name = "_ipsec4stat" }, 104#define N_IPSEC6STAT 15 105 { .n_name = "_ipsec6stat" }, 106#define N_PIM6STAT 16 107 { .n_name = "_pim6stat" }, 108#define N_MRT6STAT 17 109 { .n_name = "_mrt6stat" }, 110#define N_MF6CTABLE 18 111 { .n_name = "_mf6ctable" }, 112#define N_MIF6TABLE 19 113 { .n_name = "_mif6table" }, 114#define N_PFKEYSTAT 20 115 { .n_name = "_pfkeystat" }, 116#define N_RTTRASH 21 117 { .n_name = "_rttrash" }, 118#define N_CARPSTAT 22 119 { .n_name = "_carpstats" }, 120#define N_PFSYNCSTAT 23 121 { .n_name = "_pfsyncstats" }, 122#define N_AHSTAT 24 123 { .n_name = "_ahstat" }, 124#define N_ESPSTAT 25 125 { .n_name = "_espstat" }, 126#define N_IPCOMPSTAT 26 127 { .n_name = "_ipcompstat" }, 128#define N_TCPSTAT 27 129 { .n_name = "_tcpstat" }, 130#define N_UDPSTAT 28 131 { .n_name = "_udpstat" }, 132#define N_IPSTAT 29 133 { .n_name = "_ipstat" }, 134#define N_ICMPSTAT 30 135 { .n_name = "_icmpstat" }, 136#define N_IGMPSTAT 31 137 { .n_name = "_igmpstat" }, 138#define N_PIMSTAT 32 139 { .n_name = "_pimstat" }, 140#define N_TCBINFO 33 141 { .n_name = "_tcbinfo" }, 142#define N_UDBINFO 34 143 { .n_name = "_udbinfo" }, 144#define N_DIVCBINFO 35 145 { .n_name = "_divcbinfo" }, 146#define N_RIPCBINFO 36 147 { .n_name = "_ripcbinfo" }, 148#define N_UNP_COUNT 37 149 { .n_name = "_unp_count" }, 150#define N_UNP_GENCNT 38 151 { .n_name = "_unp_gencnt" }, 152#define N_UNP_DHEAD 39 153 { .n_name = "_unp_dhead" }, 154#define N_UNP_SHEAD 40 155 { .n_name = "_unp_shead" }, 156#define N_RIP6STAT 41 157 { .n_name = "_rip6stat" }, 158#define N_SCTPSTAT 42 159 { .n_name = "_sctpstat" }, 160#define N_MFCTABLESIZE 43 161 { .n_name = "_mfctablesize" }, 162#define N_ARPSTAT 44 163 { .n_name = "_arpstat" }, 164#define N_UNP_SPHEAD 45 165 { .n_name = "unp_sphead" }, 166#define N_SFSTAT 46 167 { .n_name = "_sfstat"}, 168 { .n_name = NULL }, 169}; 170 171struct protox { 172 int pr_index; /* index into nlist of cb head */ 173 int pr_sindex; /* index into nlist of stat block */ 174 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 175 void (*pr_cblocks)(u_long, const char *, int, int); 176 /* control blocks printing routine */ 177 void (*pr_stats)(u_long, const char *, int, int); 178 /* statistics printing routine */ 179 void (*pr_istats)(char *); /* per/if statistics printing routine */ 180 const char *pr_name; /* well-known name */ 181 int pr_usesysctl; /* non-zero if we use sysctl, not kvm */ 182 int pr_protocol; 183} protox[] = { 184 { N_TCBINFO, N_TCPSTAT, 1, protopr, 185 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 186 { N_UDBINFO, N_UDPSTAT, 1, protopr, 187 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 188#ifdef SCTP 189 { -1, N_SCTPSTAT, 1, sctp_protopr, 190 sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP }, 191#endif 192#ifdef SDP 193 { -1, -1, 1, protopr, 194 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 195#endif 196 { N_DIVCBINFO, -1, 1, protopr, 197 NULL, NULL, "divert", 1, IPPROTO_DIVERT }, 198 { N_RIPCBINFO, N_IPSTAT, 1, protopr, 199 ip_stats, NULL, "ip", 1, IPPROTO_RAW }, 200 { N_RIPCBINFO, N_ICMPSTAT, 1, protopr, 201 icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP }, 202 { N_RIPCBINFO, N_IGMPSTAT, 1, protopr, 203 igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP }, 204#ifdef IPSEC 205 { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */ 206 ipsec_stats, NULL, "ipsec", 1, 0}, 207 { -1, N_AHSTAT, 1, NULL, 208 ah_stats, NULL, "ah", 1, 0}, 209 { -1, N_ESPSTAT, 1, NULL, 210 esp_stats, NULL, "esp", 1, 0}, 211 { -1, N_IPCOMPSTAT, 1, NULL, 212 ipcomp_stats, NULL, "ipcomp", 1, 0}, 213#endif 214 { N_RIPCBINFO, N_PIMSTAT, 1, protopr, 215 pim_stats, NULL, "pim", 1, IPPROTO_PIM }, 216 { -1, N_CARPSTAT, 1, NULL, 217 carp_stats, NULL, "carp", 1, 0 }, 218#ifdef PF 219 { -1, N_PFSYNCSTAT, 1, NULL, 220 pfsync_stats, NULL, "pfsync", 1, 0 }, 221#endif 222 { -1, N_ARPSTAT, 1, NULL, 223 arp_stats, NULL, "arp", 1, 0 }, 224 { -1, -1, 0, NULL, 225 NULL, NULL, NULL, 0, 0 } 226}; 227 228#ifdef INET6 229struct protox ip6protox[] = { 230 { N_TCBINFO, N_TCPSTAT, 1, protopr, 231 tcp_stats, NULL, "tcp", 1, IPPROTO_TCP }, 232 { N_UDBINFO, N_UDPSTAT, 1, protopr, 233 udp_stats, NULL, "udp", 1, IPPROTO_UDP }, 234 { N_RIPCBINFO, N_IP6STAT, 1, protopr, 235 ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW }, 236 { N_RIPCBINFO, N_ICMP6STAT, 1, protopr, 237 icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 }, 238#ifdef SDP 239 { -1, -1, 1, protopr, 240 NULL, NULL, "sdp", 1, IPPROTO_TCP }, 241#endif 242#ifdef IPSEC 243 { -1, N_IPSEC6STAT, 1, NULL, 244 ipsec_stats, NULL, "ipsec6", 1, 0 }, 245#endif 246#ifdef notyet 247 { -1, N_PIM6STAT, 1, NULL, 248 pim6_stats, NULL, "pim6", 1, 0 }, 249#endif 250 { -1, N_RIP6STAT, 1, NULL, 251 rip6_stats, NULL, "rip6", 1, 0 }, 252 { -1, -1, 0, NULL, 253 NULL, NULL, NULL, 0, 0 } 254}; 255#endif /*INET6*/ 256 257#ifdef IPSEC 258struct protox pfkeyprotox[] = { 259 { -1, N_PFKEYSTAT, 1, NULL, 260 pfkey_stats, NULL, "pfkey", 0, 0 }, 261 { -1, -1, 0, NULL, 262 NULL, NULL, NULL, 0, 0 } 263}; 264#endif 265 266struct protox atalkprotox[] = { 267 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, 268 ddp_stats, NULL, "ddp", 0, 0 }, 269 { -1, -1, 0, NULL, 270 NULL, NULL, NULL, 0, 0 } 271}; 272#ifdef NETGRAPH 273struct protox netgraphprotox[] = { 274 { N_NGSOCKS, -1, 1, netgraphprotopr, 275 NULL, NULL, "ctrl", 0, 0 }, 276 { N_NGSOCKS, -1, 1, netgraphprotopr, 277 NULL, NULL, "data", 0, 0 }, 278 { -1, -1, 0, NULL, 279 NULL, NULL, NULL, 0, 0 } 280}; 281#endif 282#ifdef IPX 283struct protox ipxprotox[] = { 284 { N_IPX, N_IPXSTAT, 1, ipxprotopr, 285 ipx_stats, NULL, "ipx", 0, 0 }, 286 { N_IPX, N_SPXSTAT, 1, ipxprotopr, 287 spx_stats, NULL, "spx", 0, 0 }, 288 { -1, -1, 0, NULL, 289 NULL, NULL, 0, 0, 0 } 290}; 291#endif 292 293struct protox *protoprotox[] = { 294 protox, 295#ifdef INET6 296 ip6protox, 297#endif 298#ifdef IPSEC 299 pfkeyprotox, 300#endif 301#ifdef IPX 302 ipxprotox, 303#endif 304 atalkprotox, NULL }; 305 306static void printproto(struct protox *, const char *); 307static void usage(void); 308static struct protox *name2protox(const char *); 309static struct protox *knownname(const char *); 310 311static kvm_t *kvmd; 312static char *nlistf = NULL, *memf = NULL; 313 314int Aflag; /* show addresses of protocol control block */ 315int aflag; /* show all sockets (including servers) */ 316int Bflag; /* show information about bpf consumers */ 317int bflag; /* show i/f total bytes in/out */ 318int dflag; /* show i/f dropped packets */ 319int gflag; /* show group (multicast) routing or stats */ 320int hflag; /* show counters in human readable format */ 321int iflag; /* show interfaces */ 322int Lflag; /* show size of listen queues */ 323int mflag; /* show memory stats */ 324int noutputs = 0; /* how much outputs before we exit */ 325int numeric_addr; /* show addresses numerically */ 326int numeric_port; /* show ports numerically */ 327static int pflag; /* show given protocol */ 328int Qflag; /* show netisr information */ 329int rflag; /* show routing tables (or routing stats) */ 330int Rflag; /* show flow / RSS statistics */ 331int sflag; /* show protocol statistics */ 332int Wflag; /* wide display */ 333int Tflag; /* TCP Information */ 334int xflag; /* extra information, includes all socket buffer info */ 335int zflag; /* zero stats */ 336 337int interval; /* repeat interval for i/f stats */ 338 339char *interface; /* desired i/f for stats, or NULL for all i/fs */ 340int unit; /* unit number for above */ 341 342int af; /* address family */ 343int live; /* true if we are examining a live system */ 344 345int 346main(int argc, char *argv[]) 347{ 348 struct protox *tp = NULL; /* for printing cblocks & stats */ 349 int ch; 350 int fib = -1; 351 char *endptr; 352 353 af = AF_UNSPEC; 354 355 while ((ch = getopt(argc, argv, "46AaBbdF:f:ghI:iLlM:mN:np:Qq:RrSTsuWw:xz")) 356 != -1) 357 switch(ch) { 358 case '4': 359#ifdef INET 360 af = AF_INET; 361#else 362 errx(1, "IPv4 support is not compiled in"); 363#endif 364 break; 365 case '6': 366#ifdef INET6 367 af = AF_INET6; 368#else 369 errx(1, "IPv6 support is not compiled in"); 370#endif 371 break; 372 case 'A': 373 Aflag = 1; 374 break; 375 case 'a': 376 aflag = 1; 377 break; 378 case 'B': 379 Bflag = 1; 380 break; 381 case 'b': 382 bflag = 1; 383 break; 384 case 'd': 385 dflag = 1; 386 break; 387 case 'F': 388 fib = strtol(optarg, &endptr, 0); 389 if (*endptr != '\0' || 390 (fib == 0 && (errno == EINVAL || errno == ERANGE))) 391 errx(1, "%s: invalid fib", optarg); 392 break; 393 case 'f': 394 if (strcmp(optarg, "ipx") == 0) 395 af = AF_IPX; 396 else if (strcmp(optarg, "inet") == 0) 397 af = AF_INET; 398#ifdef INET6 399 else if (strcmp(optarg, "inet6") == 0) 400 af = AF_INET6; 401#endif 402#ifdef IPSEC 403 else if (strcmp(optarg, "pfkey") == 0) 404 af = PF_KEY; 405#endif 406 else if (strcmp(optarg, "unix") == 0) 407 af = AF_UNIX; 408 else if (strcmp(optarg, "atalk") == 0) 409 af = AF_APPLETALK; 410#ifdef NETGRAPH 411 else if (strcmp(optarg, "ng") == 0 412 || strcmp(optarg, "netgraph") == 0) 413 af = AF_NETGRAPH; 414#endif 415 else if (strcmp(optarg, "link") == 0) 416 af = AF_LINK; 417 else { 418 errx(1, "%s: unknown address family", optarg); 419 } 420 break; 421 case 'g': 422 gflag = 1; 423 break; 424 case 'h': 425 hflag = 1; 426 break; 427 case 'I': { 428 char *cp; 429 430 iflag = 1; 431 for (cp = interface = optarg; isalpha(*cp); cp++) 432 continue; 433 unit = atoi(cp); 434 break; 435 } 436 case 'i': 437 iflag = 1; 438 break; 439 case 'L': 440 Lflag = 1; 441 break; 442 case 'M': 443 memf = optarg; 444 break; 445 case 'm': 446 mflag = 1; 447 break; 448 case 'N': 449 nlistf = optarg; 450 break; 451 case 'n': 452 numeric_addr = numeric_port = 1; 453 break; 454 case 'p': 455 if ((tp = name2protox(optarg)) == NULL) { 456 errx(1, 457 "%s: unknown or uninstrumented protocol", 458 optarg); 459 } 460 pflag = 1; 461 break; 462 case 'Q': 463 Qflag = 1; 464 break; 465 case 'q': 466 noutputs = atoi(optarg); 467 if (noutputs != 0) 468 noutputs++; 469 break; 470 case 'r': 471 rflag = 1; 472 break; 473 case 'R': 474 Rflag = 1; 475 break; 476 case 's': 477 ++sflag; 478 break; 479 case 'S': 480 numeric_addr = 1; 481 break; 482 case 'u': 483 af = AF_UNIX; 484 break; 485 case 'W': 486 case 'l': 487 Wflag = 1; 488 break; 489 case 'w': 490 interval = atoi(optarg); 491 iflag = 1; 492 break; 493 case 'T': 494 Tflag = 1; 495 break; 496 case 'x': 497 xflag = 1; 498 break; 499 case 'z': 500 zflag = 1; 501 break; 502 case '?': 503 default: 504 usage(); 505 } 506 argv += optind; 507 argc -= optind; 508 509#define BACKWARD_COMPATIBILITY 510#ifdef BACKWARD_COMPATIBILITY 511 if (*argv) { 512 if (isdigit(**argv)) { 513 interval = atoi(*argv); 514 if (interval <= 0) 515 usage(); 516 ++argv; 517 iflag = 1; 518 } 519 if (*argv) { 520 nlistf = *argv; 521 if (*++argv) 522 memf = *argv; 523 } 524 } 525#endif 526 527 /* 528 * Discard setgid privileges if not the running kernel so that bad 529 * guys can't print interesting stuff from kernel memory. 530 */ 531 live = (nlistf == NULL && memf == NULL); 532 if (!live) 533 setgid(getgid()); 534 535 if (xflag && Tflag) 536 errx(1, "-x and -T are incompatible, pick one."); 537 538 /* Load all necessary kvm symbols */ 539 kresolve_list(nl); 540 541 if (Bflag) { 542 if (!live) 543 usage(); 544 bpf_stats(interface); 545 exit(0); 546 } 547 if (mflag) { 548 if (!live) { 549 if (kread(0, NULL, 0) == 0) 550 mbpr(kvmd, nl[N_SFSTAT].n_value); 551 } else 552 mbpr(NULL, 0); 553 exit(0); 554 } 555 if (Qflag) { 556 if (!live) { 557 if (kread(0, NULL, 0) == 0) 558 netisr_stats(kvmd); 559 } else 560 netisr_stats(NULL); 561 exit(0); 562 } 563#if 0 564 /* 565 * Keep file descriptors open to avoid overhead 566 * of open/close on each call to get* routines. 567 */ 568 sethostent(1); 569 setnetent(1); 570#else 571 /* 572 * This does not make sense any more with DNS being default over 573 * the files. Doing a setXXXXent(1) causes a tcp connection to be 574 * used for the queries, which is slower. 575 */ 576#endif 577 if (iflag && !sflag) { 578 intpr(interval, NULL, af); 579 exit(0); 580 } 581 if (rflag) { 582 if (sflag) { 583 rt_stats(); 584 flowtable_stats(); 585 } else 586 routepr(fib, af); 587 exit(0); 588 } 589 590 if (gflag) { 591 if (sflag) { 592 if (af == AF_INET || af == AF_UNSPEC) 593 mrt_stats(); 594#ifdef INET6 595 if (af == AF_INET6 || af == AF_UNSPEC) 596 mrt6_stats(); 597#endif 598 } else { 599 if (af == AF_INET || af == AF_UNSPEC) 600 mroutepr(); 601#ifdef INET6 602 if (af == AF_INET6 || af == AF_UNSPEC) 603 mroute6pr(); 604#endif 605 } 606 exit(0); 607 } 608 609 if (tp) { 610 printproto(tp, tp->pr_name); 611 exit(0); 612 } 613 if (af == AF_INET || af == AF_UNSPEC) 614 for (tp = protox; tp->pr_name; tp++) 615 printproto(tp, tp->pr_name); 616#ifdef INET6 617 if (af == AF_INET6 || af == AF_UNSPEC) 618 for (tp = ip6protox; tp->pr_name; tp++) 619 printproto(tp, tp->pr_name); 620#endif /*INET6*/ 621#ifdef IPSEC 622 if (af == PF_KEY || af == AF_UNSPEC) 623 for (tp = pfkeyprotox; tp->pr_name; tp++) 624 printproto(tp, tp->pr_name); 625#endif /*IPSEC*/ 626#ifdef IPX 627 if (af == AF_IPX || af == AF_UNSPEC) { 628 for (tp = ipxprotox; tp->pr_name; tp++) 629 printproto(tp, tp->pr_name); 630 } 631#endif /* IPX */ 632 if (af == AF_APPLETALK || af == AF_UNSPEC) 633 for (tp = atalkprotox; tp->pr_name; tp++) 634 printproto(tp, tp->pr_name); 635#ifdef NETGRAPH 636 if (af == AF_NETGRAPH || af == AF_UNSPEC) 637 for (tp = netgraphprotox; tp->pr_name; tp++) 638 printproto(tp, tp->pr_name); 639#endif /* NETGRAPH */ 640 if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) 641 unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value, 642 nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value, 643 nl[N_UNP_SPHEAD].n_value); 644 exit(0); 645} 646 647int 648fetch_stats(const char *sysctlname, u_long off, void *stats, size_t len, 649 int (*kreadfn)(u_long, void *, size_t)) 650{ 651 int error; 652 653 if (live) { 654 memset(stats, 0, len); 655 if (zflag) 656 error = sysctlbyname(sysctlname, NULL, NULL, stats, 657 len); 658 else 659 error = sysctlbyname(sysctlname, stats, &len, NULL, 0); 660 if (error == -1 && errno != ENOENT) 661 warn("sysctl %s", sysctlname); 662 } else { 663 if (off == 0) 664 return (1); 665 error = kreadfn(off, stats, len); 666 } 667 return (error); 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 */ 675static void 676printproto(struct protox *tp, const char *name) 677{ 678 void (*pr)(u_long, const char *, int, int); 679 u_long off; 680 681 if (sflag) { 682 if (iflag) { 683 if (tp->pr_istats) 684 intpr(interval, tp->pr_istats, af); 685 else if (pflag) 686 printf("%s: no per-interface stats routine\n", 687 tp->pr_name); 688 return; 689 } else { 690 pr = tp->pr_stats; 691 if (!pr) { 692 if (pflag) 693 printf("%s: no stats routine\n", 694 tp->pr_name); 695 return; 696 } 697 if (tp->pr_usesysctl && live) 698 off = 0; 699 else if (tp->pr_sindex < 0) { 700 if (pflag) 701 printf( 702 "%s: stats routine doesn't work on cores\n", 703 tp->pr_name); 704 return; 705 } else 706 off = nl[tp->pr_sindex].n_value; 707 } 708 } else { 709 pr = tp->pr_cblocks; 710 if (!pr) { 711 if (pflag) 712 printf("%s: no PCB routine\n", tp->pr_name); 713 return; 714 } 715 if (tp->pr_usesysctl && live) 716 off = 0; 717 else if (tp->pr_index < 0) { 718 if (pflag) 719 printf( 720 "%s: PCB routine doesn't work on cores\n", 721 tp->pr_name); 722 return; 723 } else 724 off = nl[tp->pr_index].n_value; 725 } 726 if (pr != NULL && (off || (live && tp->pr_usesysctl) || 727 af != AF_UNSPEC)) 728 (*pr)(off, name, af, tp->pr_protocol); 729} 730 731static int 732kvmd_init(void) 733{ 734 char errbuf[_POSIX2_LINE_MAX]; 735 736 if (kvmd != NULL) 737 return (0); 738 739 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 740 setgid(getgid()); 741 742 if (kvmd == NULL) { 743 warnx("kvm not available: %s", errbuf); 744 return (-1); 745 } 746 747 return (0); 748} 749 750/* 751 * Resolve symbol list, return 0 on success. 752 */ 753int 754kresolve_list(struct nlist *_nl) 755{ 756 757 if ((kvmd == NULL) && (kvmd_init() != 0)) 758 return (-1); 759 760 if (_nl[0].n_type != 0) 761 return (0); 762 763 if (kvm_nlist(kvmd, _nl) < 0) { 764 if (nlistf) 765 errx(1, "%s: kvm_nlist: %s", nlistf, 766 kvm_geterr(kvmd)); 767 else 768 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 769 } 770 771 return (0); 772} 773 774/* 775 * Read kernel memory, return 0 on success. 776 */ 777int 778kread(u_long addr, void *buf, size_t size) 779{ 780 781 if (kvmd_init() < 0) 782 return (-1); 783 784 if (!buf) 785 return (0); 786 if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) { 787 warnx("%s", kvm_geterr(kvmd)); 788 return (-1); 789 } 790 return (0); 791} 792 793/* 794 * Read single counter(9). 795 */ 796uint64_t 797kread_counter(u_long addr) 798{ 799 800 if (kvmd_init() < 0) 801 return (-1); 802 803 return (kvm_counter_u64_fetch(kvmd, addr)); 804} 805 806/* 807 * Read an array of N counters in kernel memory into array of N uint64_t's. 808 */ 809int 810kread_counters(u_long addr, void *buf, size_t size) 811{ 812 uint64_t *c; 813 u_long *counters; 814 size_t i, n; 815 816 if (kvmd_init() < 0) 817 return (-1); 818 819 if (size % sizeof(uint64_t) != 0) { 820 warnx("kread_counters: invalid counter set size"); 821 return (-1); 822 } 823 824 n = size / sizeof(uint64_t); 825 if ((counters = malloc(n * sizeof(u_long))) == NULL) 826 err(-1, "malloc"); 827 if (kread(addr, counters, n * sizeof(u_long)) < 0) { 828 free(counters); 829 return (-1); 830 } 831 832 c = buf; 833 for (i = 0; i < n; i++) 834 c[i] = kvm_counter_u64_fetch(kvmd, counters[i]); 835 836 free(counters); 837 return (0); 838} 839 840const char * 841plural(uintmax_t n) 842{ 843 return (n != 1 ? "s" : ""); 844} 845 846const char * 847plurales(uintmax_t n) 848{ 849 return (n != 1 ? "es" : ""); 850} 851 852const char * 853pluralies(uintmax_t n) 854{ 855 return (n != 1 ? "ies" : "y"); 856} 857 858/* 859 * Find the protox for the given "well-known" name. 860 */ 861static struct protox * 862knownname(const char *name) 863{ 864 struct protox **tpp, *tp; 865 866 for (tpp = protoprotox; *tpp; tpp++) 867 for (tp = *tpp; tp->pr_name; tp++) 868 if (strcmp(tp->pr_name, name) == 0) 869 return (tp); 870 return (NULL); 871} 872 873/* 874 * Find the protox corresponding to name. 875 */ 876static struct protox * 877name2protox(const char *name) 878{ 879 struct protox *tp; 880 char **alias; /* alias from p->aliases */ 881 struct protoent *p; 882 883 /* 884 * Try to find the name in the list of "well-known" names. If that 885 * fails, check if name is an alias for an Internet protocol. 886 */ 887 if ((tp = knownname(name)) != NULL) 888 return (tp); 889 890 setprotoent(1); /* make protocol lookup cheaper */ 891 while ((p = getprotoent()) != NULL) { 892 /* assert: name not same as p->name */ 893 for (alias = p->p_aliases; *alias; alias++) 894 if (strcmp(name, *alias) == 0) { 895 endprotoent(); 896 return (knownname(p->p_name)); 897 } 898 } 899 endprotoent(); 900 return (NULL); 901} 902 903static void 904usage(void) 905{ 906 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 907"usage: netstat [-46AaLnRSTWx] [-f protocol_family | -p protocol]\n" 908" [-M core] [-N system]", 909" netstat -i | -I interface [-46abdhnW] [-f address_family]\n" 910" [-M core] [-N system]", 911" netstat -w wait [-I interface] [-46d] [-M core] [-N system] [-q howmany]", 912" netstat -s [-s] [-46z] [-f protocol_family | -p protocol]\n" 913" [-M core] [-N system]", 914" netstat -i | -I interface [-46s] [-f protocol_family | -p protocol]\n" 915" [-M core] [-N system]", 916" netstat -m [-M core] [-N system]", 917" netstat -B [-I interface]", 918" netstat -r [-46AanW] [-f address_family] [-M core] [-N system]", 919" netstat -rs [-s] [-M core] [-N system]", 920" netstat -g [-46W] [-f address_family] [-M core] [-N system]", 921" netstat -gs [-46s] [-f address_family] [-M core] [-N system]", 922" netstat -Q"); 923 exit(1); 924} 925