main.c revision 78592
197403Sobrien/* 297403Sobrien * Copyright (c) 1983, 1988, 1993 397403Sobrien * Regents of the University of California. All rights reserved. 497403Sobrien * 597403Sobrien * Redistribution and use in source and binary forms, with or without 697403Sobrien * modification, are permitted provided that the following conditions 797403Sobrien * are met: 897403Sobrien * 1. Redistributions of source code must retain the above copyright 997403Sobrien * notice, this list of conditions and the following disclaimer. 1097403Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1197403Sobrien * notice, this list of conditions and the following disclaimer in the 1297403Sobrien * documentation and/or other materials provided with the distribution. 1397403Sobrien * 3. All advertising materials mentioning features or use of this software 1497403Sobrien * must display the following acknowledgement: 1597403Sobrien * This product includes software developed by the University of 1697403Sobrien * California, Berkeley and its contributors. 1797403Sobrien * 4. Neither the name of the University nor the names of its contributors 1897403Sobrien * may be used to endorse or promote products derived from this software 1997403Sobrien * without specific prior written permission. 2097403Sobrien * 2197403Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2297403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2397403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2497403Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2597403Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2697403Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2797403Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2897403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2997403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3097403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3197403Sobrien * SUCH DAMAGE. 3297403Sobrien */ 3397403Sobrien 3497403Sobrien#ifndef lint 3597403Sobrienchar const copyright[] = 3697403Sobrien"@(#) Copyright (c) 1983, 1988, 1993\n\ 3797403Sobrien Regents of the University of California. All rights reserved.\n"; 3897403Sobrien#endif /* not lint */ 3997403Sobrien 4097403Sobrien#ifndef lint 4197403Sobrien#if 0 4297403Sobrienstatic char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; 4397403Sobrien#endif 4497403Sobrienstatic const char rcsid[] = 4597403Sobrien "$FreeBSD: head/usr.bin/netstat/main.c 78592 2001-06-22 06:35:32Z bmilekic $"; 4697403Sobrien#endif /* not lint */ 4797403Sobrien 4897403Sobrien#include <sys/param.h> 4997403Sobrien#include <sys/file.h> 5097403Sobrien#include <sys/protosw.h> 5197403Sobrien#include <sys/socket.h> 5297403Sobrien 5397403Sobrien#include <netinet/in.h> 5497403Sobrien 5597403Sobrien#include <netgraph/ng_socket.h> 5697403Sobrien 5797403Sobrien#include <ctype.h> 5897403Sobrien#include <err.h> 5997403Sobrien#include <errno.h> 6097403Sobrien#include <kvm.h> 6197403Sobrien#include <limits.h> 6297403Sobrien#include <netdb.h> 6397403Sobrien#include <nlist.h> 6497403Sobrien#include <paths.h> 6597403Sobrien#include <stdio.h> 6697403Sobrien#include <stdlib.h> 6797403Sobrien#include <string.h> 6897403Sobrien#include <unistd.h> 6997403Sobrien#include "netstat.h" 7097403Sobrien 7197403Sobrienstatic struct nlist nl[] = { 7297403Sobrien#define N_IFNET 0 7397403Sobrien { "_ifnet" }, 7497403Sobrien#define N_IMP 1 7597403Sobrien { "_imp_softc" }, 7697403Sobrien#define N_RTSTAT 2 7797403Sobrien { "_rtstat" }, 7897403Sobrien#define N_UNIXSW 3 7997403Sobrien { "_localsw" }, 8097403Sobrien#define N_IDP 4 8197403Sobrien { "_nspcb"}, 8297403Sobrien#define N_IDPSTAT 5 8397403Sobrien { "_idpstat"}, 8497403Sobrien#define N_SPPSTAT 6 8597403Sobrien { "_spp_istat"}, 8697403Sobrien#define N_NSERR 7 8797403Sobrien { "_ns_errstat"}, 8897403Sobrien#define N_CLNPSTAT 8 8997403Sobrien { "_clnp_stat"}, 9097403Sobrien#define IN_NOTUSED 9 9197403Sobrien { "_tp_inpcb" }, 9297403Sobrien#define ISO_TP 10 9397403Sobrien { "_tp_refinfo" }, 9497403Sobrien#define N_TPSTAT 11 9597403Sobrien { "_tp_stat" }, 9697403Sobrien#define N_ESISSTAT 12 9797403Sobrien { "_esis_stat"}, 9897403Sobrien#define N_NIMP 13 9997403Sobrien { "_nimp"}, 10097403Sobrien#define N_RTREE 14 10197403Sobrien { "_rt_tables"}, 10297403Sobrien#define N_CLTP 15 10397403Sobrien { "_cltb"}, 10497403Sobrien#define N_CLTPSTAT 16 10597403Sobrien { "_cltpstat"}, 10697403Sobrien#define N_NFILE 17 10797403Sobrien { "_nfile" }, 10897403Sobrien#define N_FILE 18 10997403Sobrien { "_file" }, 11097403Sobrien#define N_MRTSTAT 19 11197403Sobrien { "_mrtstat" }, 11297403Sobrien#define N_MFCTABLE 20 11397403Sobrien { "_mfctable" }, 11497403Sobrien#define N_VIFTABLE 21 11597403Sobrien { "_viftable" }, 11697403Sobrien#define N_IPX 22 11797403Sobrien { "_ipxpcb"}, 11897403Sobrien#define N_IPXSTAT 23 11997403Sobrien { "_ipxstat"}, 12097403Sobrien#define N_SPXSTAT 24 12197403Sobrien { "_spx_istat"}, 12297403Sobrien#define N_DDPSTAT 25 12397403Sobrien { "_ddpstat"}, 12497403Sobrien#define N_DDPCB 26 12597403Sobrien { "_ddpcb"}, 12697403Sobrien#define N_NGSOCKS 27 12797403Sobrien { "_ngsocklist"}, 12897403Sobrien#define N_IP6STAT 28 12997403Sobrien { "_ip6stat" }, 13097403Sobrien#define N_ICMP6STAT 29 13197403Sobrien { "_icmp6stat" }, 13297403Sobrien#define N_IPSECSTAT 30 13397403Sobrien { "_ipsecstat" }, 13497403Sobrien#define N_IPSEC6STAT 31 13597403Sobrien { "_ipsec6stat" }, 13697403Sobrien#define N_PIM6STAT 32 13797403Sobrien { "_pim6stat" }, 13897403Sobrien#define N_MRT6PROTO 33 13997403Sobrien { "_ip6_mrtproto" }, 14097403Sobrien#define N_MRT6STAT 34 14197403Sobrien { "_mrt6stat" }, 14297403Sobrien#define N_MF6CTABLE 35 14397403Sobrien { "_mf6ctable" }, 14497403Sobrien#define N_MIF6TABLE 36 14597403Sobrien { "_mif6table" }, 14697403Sobrien#define N_PFKEYSTAT 37 14797403Sobrien { "_pfkeystat" }, 14897403Sobrien#define N_MBSTAT 38 14997403Sobrien { "_mbstat" }, 15097403Sobrien#define N_MBTYPES 39 15197403Sobrien { "_mbtypes" }, 15297403Sobrien#define N_NMBCLUSTERS 40 15397403Sobrien { "_nmbclusters" }, 15497403Sobrien#define N_NMBUFS 41 15597403Sobrien { "_nmbufs" }, 15697403Sobrien#define N_MBLIM 42 15797403Sobrien { "_mbuf_limit" }, 15897403Sobrien#define N_CLLIM 43 15997403Sobrien { "_clust_limit" }, 16097403Sobrien#define N_NCPUS 44 16197403Sobrien { "_smp_cpus" }, 16297403Sobrien#define N_PAGESZ 45 16397403Sobrien { "_pagesize" }, 16497403Sobrien#define N_MBPSTAT 46 16597403Sobrien { "_mb_statpcpu" }, 16697403Sobrien { "" }, 16797403Sobrien}; 16897403Sobrien 16997403Sobrienstruct protox { 17097403Sobrien u_char pr_index; /* index into nlist of cb head */ 17197403Sobrien u_char pr_sindex; /* index into nlist of stat block */ 17297403Sobrien u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 17397403Sobrien void (*pr_cblocks)(u_long, char *, int); 17497403Sobrien /* control blocks printing routine */ 17597403Sobrien void (*pr_stats)(u_long, char *, int); 17697403Sobrien /* statistics printing routine */ 17797403Sobrien void (*pr_istats)(char *); /* per/if statistics printing routine */ 17897403Sobrien char *pr_name; /* well-known name */ 17997403Sobrien int pr_usesysctl; /* true if we use sysctl, not kvm */ 18097403Sobrien} protox[] = { 18197403Sobrien { -1, -1, 1, protopr, 18297403Sobrien tcp_stats, NULL, "tcp", IPPROTO_TCP }, 18397403Sobrien { -1, -1, 1, protopr, 18497403Sobrien udp_stats, NULL, "udp", IPPROTO_UDP }, 18597403Sobrien { -1, -1, 1, protopr, 18697403Sobrien NULL, NULL, "divert",IPPROTO_DIVERT }, 18797403Sobrien { -1, -1, 1, protopr, 18897403Sobrien ip_stats, NULL, "ip", IPPROTO_RAW }, 18997403Sobrien { -1, -1, 1, protopr, 190 icmp_stats, NULL, "icmp", IPPROTO_ICMP }, 191 { -1, -1, 1, protopr, 192 igmp_stats, NULL, "igmp", IPPROTO_IGMP }, 193#ifdef IPSEC 194 { -1, N_IPSECSTAT, 1, 0, 195 ipsec_stats, NULL, "ipsec", 0}, 196#endif 197 { -1, -1, 1, 0, 198 bdg_stats, NULL, "bdg", 1 /* bridging... */ }, 199 { -1, -1, 0, 0, 200 0, NULL, 0 } 201}; 202 203#ifdef INET6 204struct protox ip6protox[] = { 205 { -1, -1, 1, protopr, 206 tcp_stats, NULL, "tcp", IPPROTO_TCP }, 207 { -1, -1, 1, protopr, 208 udp_stats, NULL, "udp", IPPROTO_UDP }, 209 { -1, N_IP6STAT, 1, 0, 210 ip6_stats, ip6_ifstats, "ip6", 0 }, 211 { -1, N_ICMP6STAT, 1, 0, 212 icmp6_stats, icmp6_ifstats, "icmp6",0 }, 213#ifdef IPSEC 214 { -1, N_IPSEC6STAT, 1, 0, 215 ipsec_stats, NULL, "ipsec6",0 }, 216#endif 217#ifdef notyet 218 { -1, N_PIM6STAT, 1, 0, 219 pim6_stats, NULL, "pim6", 0 }, 220#endif 221 { -1, -1, 1, 0, 222 rip6_stats, NULL, "rip6", 0 }, 223 { -1, -1, 1, 0, 224 bdg_stats, NULL, "bdg", 1 /* bridging... */ }, 225 { -1, -1, 0, 0, 226 0, NULL, 0, 0 } 227}; 228#endif /*INET6*/ 229 230#ifdef IPSEC 231struct protox pfkeyprotox[] = { 232 { -1, N_PFKEYSTAT, 1, 0, 233 pfkey_stats, NULL, "pfkey", 0 }, 234 { -1, -1, 0, 0, 235 0, NULL, 0, 0 } 236}; 237#endif 238 239struct protox atalkprotox[] = { 240 { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, 241 ddp_stats, NULL, "ddp" }, 242 { -1, -1, 0, 0, 243 0, NULL, 0 } 244}; 245 246struct protox netgraphprotox[] = { 247 { N_NGSOCKS, -1, 1, netgraphprotopr, 248 NULL, NULL, "ctrl" }, 249 { N_NGSOCKS, -1, 1, netgraphprotopr, 250 NULL, NULL, "data" }, 251 { -1, NULL, 0, 0, 252 0, NULL, 0 } 253}; 254 255struct protox ipxprotox[] = { 256 { N_IPX, N_IPXSTAT, 1, ipxprotopr, 257 ipx_stats, NULL, "ipx", 0 }, 258 { N_IPX, N_SPXSTAT, 1, ipxprotopr, 259 spx_stats, NULL, "spx", 0 }, 260 { -1, -1, 0, 0, 261 0, NULL, 0, 0 } 262}; 263 264#ifdef NS 265struct protox nsprotox[] = { 266 { N_IDP, N_IDPSTAT, 1, nsprotopr, 267 idp_stats, NULL, "idp" }, 268 { N_IDP, N_SPPSTAT, 1, nsprotopr, 269 spp_stats, NULL, "spp" }, 270 { -1, N_NSERR, 1, 0, 271 nserr_stats, NULL, "ns_err" }, 272 { -1, -1, 0, 0, 273 0, NULL, 0 } 274}; 275#endif 276 277#ifdef ISO 278struct protox isoprotox[] = { 279 { ISO_TP, N_TPSTAT, 1, iso_protopr, 280 tp_stats, NULL, "tp" }, 281 { N_CLTP, N_CLTPSTAT, 1, iso_protopr, 282 cltp_stats, NULL, "cltp" }, 283 { -1, N_CLNPSTAT, 1, 0, 284 clnp_stats, NULL, "clnp"}, 285 { -1, N_ESISSTAT, 1, 0, 286 esis_stats, NULL, "esis"}, 287 { -1, -1, 0, 0, 288 0, NULL, 0 } 289}; 290#endif 291 292struct protox *protoprotox[] = { 293 protox, 294#ifdef INET6 295 ip6protox, 296#endif 297#ifdef IPSEC 298 pfkeyprotox, 299#endif 300 ipxprotox, atalkprotox, 301#ifdef NS 302 nsprotox, 303#endif 304#ifdef ISO 305 isoprotox, 306#endif 307 NULL }; 308 309static void printproto (struct protox *, char *); 310static void usage (void); 311static struct protox *name2protox (char *); 312static struct protox *knownname (char *); 313 314static kvm_t *kvmd; 315static char *nlistf = NULL, *memf = NULL; 316 317int Aflag; /* show addresses of protocol control block */ 318int aflag; /* show all sockets (including servers) */ 319int bflag; /* show i/f total bytes in/out */ 320int dflag; /* show i/f dropped packets */ 321int gflag; /* show group (multicast) routing or stats */ 322int iflag; /* show interfaces */ 323int lflag; /* show routing table with use and ref */ 324int Lflag; /* show size of listen queues */ 325int mflag; /* show memory stats */ 326int numeric_addr; /* show addresses numerically */ 327int numeric_port; /* show ports numerically */ 328static int pflag; /* show given protocol */ 329int rflag; /* show routing tables (or routing stats) */ 330int sflag; /* show protocol statistics */ 331int tflag; /* show i/f watchdog timers */ 332int Wflag; /* wide display */ 333 334int interval; /* repeat interval for i/f stats */ 335 336char *interface; /* desired i/f for stats, or NULL for all i/fs */ 337int unit; /* unit number for above */ 338 339int af; /* address family */ 340 341int 342main(argc, argv) 343 int argc; 344 char *argv[]; 345{ 346 register struct protox *tp = NULL; /* for printing cblocks & stats */ 347 int ch; 348 349 af = AF_UNSPEC; 350 351 while ((ch = getopt(argc, argv, "Aabdf:gI:iLlM:mN:np:rSstuWw:")) != -1) 352 switch(ch) { 353 case 'A': 354 Aflag = 1; 355 break; 356 case 'a': 357 aflag = 1; 358 break; 359 case 'b': 360 bflag = 1; 361 break; 362 case 'd': 363 dflag = 1; 364 break; 365 case 'f': 366#ifdef NS 367 if (strcmp(optarg, "ns") == 0) 368 af = AF_NS; 369 else 370#endif 371 if (strcmp(optarg, "ipx") == 0) 372 af = AF_IPX; 373 else if (strcmp(optarg, "inet") == 0) 374 af = AF_INET; 375#ifdef INET6 376 else if (strcmp(optarg, "inet6") == 0) 377 af = AF_INET6; 378#endif /*INET6*/ 379#ifdef INET6 380 else if (strcmp(optarg, "pfkey") == 0) 381 af = PF_KEY; 382#endif /*INET6*/ 383 else if (strcmp(optarg, "unix") == 0) 384 af = AF_UNIX; 385 else if (strcmp(optarg, "atalk") == 0) 386 af = AF_APPLETALK; 387 else if (strcmp(optarg, "ng") == 0 388 || strcmp(optarg, "netgraph") == 0) 389 af = AF_NETGRAPH; 390#ifdef ISO 391 else if (strcmp(optarg, "iso") == 0) 392 af = AF_ISO; 393#endif 394 else { 395 errx(1, "%s: unknown address family", optarg); 396 } 397 break; 398 case 'g': 399 gflag = 1; 400 break; 401 case 'I': { 402 char *cp; 403 404 iflag = 1; 405 for (cp = interface = optarg; isalpha(*cp); cp++) 406 continue; 407 unit = atoi(cp); 408 break; 409 } 410 case 'i': 411 iflag = 1; 412 break; 413 case 'l': 414 lflag = 1; 415 break; 416 case 'L': 417 Lflag = 1; 418 break; 419 case 'M': 420 memf = optarg; 421 break; 422 case 'm': 423 mflag = 1; 424 break; 425 case 'N': 426 nlistf = optarg; 427 break; 428 case 'n': 429 numeric_addr = numeric_port = 1; 430 break; 431 case 'p': 432 if ((tp = name2protox(optarg)) == NULL) { 433 errx(1, 434 "%s: unknown or uninstrumented protocol", 435 optarg); 436 } 437 pflag = 1; 438 break; 439 case 'r': 440 rflag = 1; 441 break; 442 case 's': 443 ++sflag; 444 break; 445 case 'S': 446 numeric_addr = 1; 447 break; 448 case 't': 449 tflag = 1; 450 break; 451 case 'u': 452 af = AF_UNIX; 453 break; 454 case 'W': 455 Wflag = 1; 456 break; 457 case 'w': 458 interval = atoi(optarg); 459 iflag = 1; 460 break; 461 case '?': 462 default: 463 usage(); 464 } 465 argv += optind; 466 argc -= optind; 467 468#define BACKWARD_COMPATIBILITY 469#ifdef BACKWARD_COMPATIBILITY 470 if (*argv) { 471 if (isdigit(**argv)) { 472 interval = atoi(*argv); 473 if (interval <= 0) 474 usage(); 475 ++argv; 476 iflag = 1; 477 } 478 if (*argv) { 479 nlistf = *argv; 480 if (*++argv) 481 memf = *argv; 482 } 483 } 484#endif 485 486 /* 487 * Discard setgid privileges if not the running kernel so that bad 488 * guys can't print interesting stuff from kernel memory. 489 */ 490 if (nlistf != NULL || memf != NULL) 491 setgid(getgid()); 492 493 if (mflag) { 494 if (memf != NULL) { 495 if (kread(0, 0, 0) == 0) 496 mbpr(nl[N_MBSTAT].n_value, 497 nl[N_MBTYPES].n_value, 498 nl[N_NMBCLUSTERS].n_value, 499 nl[N_NMBUFS].n_value, 500 nl[N_MBLIM].n_value, 501 nl[N_CLLIM].n_value, 502 nl[N_NCPUS].n_value, 503 nl[N_PAGESZ].n_value, 504 nl[N_MBPSTAT].n_value); 505 } else 506 mbpr(0, 0, 0, 0, 0, 0, 0, 0, 0); 507 exit(0); 508 } 509#if 0 510 /* 511 * Keep file descriptors open to avoid overhead 512 * of open/close on each call to get* routines. 513 */ 514 sethostent(1); 515 setnetent(1); 516#else 517 /* 518 * This does not make sense any more with DNS being default over 519 * the files. Doing a setXXXXent(1) causes a tcp connection to be 520 * used for the queries, which is slower. 521 */ 522#endif 523 if (iflag && !sflag) { 524 kread(0, 0, 0); 525 intpr(interval, nl[N_IFNET].n_value, NULL); 526 exit(0); 527 } 528 if (rflag) { 529 kread(0, 0, 0); 530 if (sflag) 531 rt_stats(nl[N_RTSTAT].n_value); 532 else 533 routepr(nl[N_RTREE].n_value); 534 exit(0); 535 } 536 if (gflag) { 537 kread(0, 0, 0); 538 if (sflag) { 539 if (af == AF_INET || af == AF_UNSPEC) 540 mrt_stats(nl[N_MRTSTAT].n_value); 541#ifdef INET6 542 if (af == AF_INET6 || af == AF_UNSPEC) 543 mrt6_stats(nl[N_MRT6STAT].n_value); 544#endif 545 } else { 546 if (af == AF_INET || af == AF_UNSPEC) 547 mroutepr(nl[N_MFCTABLE].n_value, 548 nl[N_VIFTABLE].n_value); 549#ifdef INET6 550 if (af == AF_INET6 || af == AF_UNSPEC) 551 mroute6pr(nl[N_MF6CTABLE].n_value, 552 nl[N_MIF6TABLE].n_value); 553#endif 554 } 555 exit(0); 556 } 557 558 kread(0, 0, 0); 559 if (tp) { 560 printproto(tp, tp->pr_name); 561 exit(0); 562 } 563 if (af == AF_INET || af == AF_UNSPEC) 564 for (tp = protox; tp->pr_name; tp++) 565 printproto(tp, tp->pr_name); 566#ifdef INET6 567 if (af == AF_INET6 || af == AF_UNSPEC) 568 for (tp = ip6protox; tp->pr_name; tp++) 569 printproto(tp, tp->pr_name); 570#endif /*INET6*/ 571#ifdef IPSEC 572 if (af == PF_KEY || af == AF_UNSPEC) 573 for (tp = pfkeyprotox; tp->pr_name; tp++) 574 printproto(tp, tp->pr_name); 575#endif /*IPSEC*/ 576 if (af == AF_IPX || af == AF_UNSPEC) { 577 kread(0, 0, 0); 578 for (tp = ipxprotox; tp->pr_name; tp++) 579 printproto(tp, tp->pr_name); 580 } 581 if (af == AF_APPLETALK || af == AF_UNSPEC) 582 for (tp = atalkprotox; tp->pr_name; tp++) 583 printproto(tp, tp->pr_name); 584 if (af == AF_NETGRAPH || af == AF_UNSPEC) 585 for (tp = netgraphprotox; tp->pr_name; tp++) 586 printproto(tp, tp->pr_name); 587#ifdef NS 588 if (af == AF_NS || af == AF_UNSPEC) 589 for (tp = nsprotox; tp->pr_name; tp++) 590 printproto(tp, tp->pr_name); 591#endif 592#ifdef ISO 593 if (af == AF_ISO || af == AF_UNSPEC) 594 for (tp = isoprotox; tp->pr_name; tp++) 595 printproto(tp, tp->pr_name); 596#endif 597 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) 598 unixpr(); 599 exit(0); 600} 601 602/* 603 * Print out protocol statistics or control blocks (per sflag). 604 * If the interface was not specifically requested, and the symbol 605 * is not in the namelist, ignore this one. 606 */ 607static void 608printproto(tp, name) 609 register struct protox *tp; 610 char *name; 611{ 612 void (*pr)(u_long, char *, int); 613 u_long off; 614 615 if (sflag) { 616 if (iflag) { 617 if (tp->pr_istats) 618 intpr(interval, nl[N_IFNET].n_value, 619 tp->pr_istats); 620 else if (pflag) 621 printf("%s: no per-interface stats routine\n", 622 tp->pr_name); 623 return; 624 } 625 else { 626 pr = tp->pr_stats; 627 if (!pr) { 628 if (pflag) 629 printf("%s: no stats routine\n", 630 tp->pr_name); 631 return; 632 } 633 off = tp->pr_usesysctl ? tp->pr_usesysctl 634 : nl[tp->pr_sindex].n_value; 635 } 636 } else { 637 pr = tp->pr_cblocks; 638 if (!pr) { 639 if (pflag) 640 printf("%s: no PCB routine\n", tp->pr_name); 641 return; 642 } 643 off = tp->pr_usesysctl ? tp->pr_usesysctl 644 : nl[tp->pr_index].n_value; 645 } 646 if (pr != NULL && (off || af != AF_UNSPEC)) 647 (*pr)(off, name, af); 648} 649 650/* 651 * Read kernel memory, return 0 on success. 652 */ 653int 654kread(u_long addr, char *buf, int size) 655{ 656 if (kvmd == 0) { 657 /* 658 * XXX. 659 */ 660 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 661 if (kvmd != NULL) { 662 if (kvm_nlist(kvmd, nl) < 0) { 663 if(nlistf) 664 errx(1, "%s: kvm_nlist: %s", nlistf, 665 kvm_geterr(kvmd)); 666 else 667 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 668 } 669 670 if (nl[0].n_type == 0) { 671 if(nlistf) 672 errx(1, "%s: no namelist", nlistf); 673 else 674 errx(1, "no namelist"); 675 } 676 } else { 677 warnx("kvm not available"); 678 return(-1); 679 } 680 } 681 if (!buf) 682 return (0); 683 if (kvm_read(kvmd, addr, buf, size) != size) { 684 warnx("%s", kvm_geterr(kvmd)); 685 return (-1); 686 } 687 return (0); 688} 689 690char * 691plural(int n) 692{ 693 return (n != 1 ? "s" : ""); 694} 695 696char * 697plurales(int n) 698{ 699 return (n != 1 ? "es" : ""); 700} 701 702/* 703 * Find the protox for the given "well-known" name. 704 */ 705static struct protox * 706knownname(char *name) 707{ 708 struct protox **tpp, *tp; 709 710 for (tpp = protoprotox; *tpp; tpp++) 711 for (tp = *tpp; tp->pr_name; tp++) 712 if (strcmp(tp->pr_name, name) == 0) 713 return (tp); 714 return (NULL); 715} 716 717/* 718 * Find the protox corresponding to name. 719 */ 720static struct protox * 721name2protox(char *name) 722{ 723 struct protox *tp; 724 char **alias; /* alias from p->aliases */ 725 struct protoent *p; 726 727 /* 728 * Try to find the name in the list of "well-known" names. If that 729 * fails, check if name is an alias for an Internet protocol. 730 */ 731 if ((tp = knownname(name)) != NULL) 732 return (tp); 733 734 setprotoent(1); /* make protocol lookup cheaper */ 735 while ((p = getprotoent()) != NULL) { 736 /* assert: name not same as p->name */ 737 for (alias = p->p_aliases; *alias; alias++) 738 if (strcmp(name, *alias) == 0) { 739 endprotoent(); 740 return (knownname(p->p_name)); 741 } 742 } 743 endprotoent(); 744 return (NULL); 745} 746 747static void 748usage(void) 749{ 750 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 751"usage: netstat [-AaLlnW] [-f address_family] [-M core] [-N system]", 752" netstat [-abdgilnrsS] [-f address_family] [-M core] [-N system]", 753" netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]", 754" netstat -m [-M core] [-N system]", 755" netstat [-M core] [-N system] [-p protocol]"); 756 exit(1); 757} 758