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 * 3. 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 * @(#) Copyright (c) 1983, 1988, 1993 Regents of the University of California. All rights reserved. 30 * @(#)main.c 8.4 (Berkeley) 3/1/94 31 * $FreeBSD: src/usr.bin/netstat/main.c,v 1.34.2.12 2001/09/17 15:17:46 ru Exp $ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/file.h> 36 #include <sys/protosw.h> 37 #include <sys/socket.h> 38 39 #include <netinet/in.h> 40 41 #include <netgraph/socket/ng_socket.h> 42 43 #include <ctype.h> 44 #include <err.h> 45 #include <errno.h> 46 #include <kvm.h> 47 #include <limits.h> 48 #include <netdb.h> 49 #include <nlist.h> 50 #include <paths.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include "netstat.h" 56 57 static struct nlist nl[] = { 58 #define N_IFNET 0 59 { .n_name = "_ifnet" }, 60 #define N_IMP 1 61 { .n_name = "_imp_softc" }, 62 #define N_RTSTAT 2 63 { .n_name = "_rtstat" }, 64 #define N_UNIXSW 3 65 { .n_name = "_localsw" }, 66 #define N_IDP 4 67 { .n_name = "_nspcb"}, 68 #define N_IDPSTAT 5 69 { .n_name = "_idpstat"}, 70 #define N_SPPSTAT 6 71 { .n_name = "_spp_istat"}, 72 #define N_NSERR 7 73 { .n_name = "_ns_errstat"}, 74 #define N_CLNPSTAT 8 75 { .n_name = "_clnp_stat"}, 76 #define IN_NOTUSED 9 77 { .n_name = "_tp_inpcb" }, 78 #define ISO_TP 10 79 { .n_name = "_tp_refinfo" }, 80 #define N_TPSTAT 11 81 { .n_name = "_tp_stat" }, 82 #define N_ESISSTAT 12 83 { .n_name = "_esis_stat"}, 84 #define N_NIMP 13 85 { .n_name = "_nimp"}, 86 #define N_RTREE 14 87 { .n_name = "_rt_tables"}, 88 #define N_CLTP 15 89 { .n_name = "_cltb"}, 90 #define N_CLTPSTAT 16 91 { .n_name = "_cltpstat"}, 92 #define N_NFILE 17 93 { .n_name = "_nfile" }, 94 #define N_FILE 18 95 { .n_name = "_file" }, 96 #define N_MRTSTAT 19 97 { .n_name = "_mrtstat" }, 98 #define N_MFCTABLE 20 99 { .n_name = "_mfctable" }, 100 #define N_VIFTABLE 21 101 { .n_name = "_viftable" }, 102 #define N_IPX 22 103 { .n_name = "_ipxpcb"}, 104 #define N_IPXSTAT 23 105 { .n_name = "_ipxstat"}, 106 #define N_SPXSTAT 24 107 { .n_name = "_spx_istat"}, 108 #define N_NGSOCKS 25 109 { .n_name = "_ngsocklist"}, 110 #define N_IP6STAT 26 111 { .n_name = "_ip6stat" }, 112 #define N_ICMP6STAT 27 113 { .n_name = "_icmp6stat" }, 114 #define N_IPSECSTAT 28 115 { .n_name = "_ipsecstat" }, 116 #define N_IPSEC6STAT 29 117 { .n_name = "_ipsec6stat" }, 118 #define N_PIM6STAT 30 119 { .n_name = "_pim6stat" }, 120 #define N_MRT6PROTO 31 121 { .n_name = "_ip6_mrtproto" }, 122 #define N_MRT6STAT 32 123 { .n_name = "_mrt6stat" }, 124 #define N_MF6CTABLE 33 125 { .n_name = "_mf6ctable" }, 126 #define N_MIF6TABLE 34 127 { .n_name = "_mif6table" }, 128 #define N_PFKEYSTAT 35 129 { .n_name = "_pfkeystat" }, 130 #define N_MBSTAT 36 131 { .n_name = "_mbstat" }, 132 #define N_MBTYPES 37 133 { .n_name = "_mbtypes" }, 134 #define N_NMBCLUSTERS 38 135 { .n_name = "_nmbclusters" }, 136 #define N_NMBUFS 39 137 { .n_name = "_nmbufs" }, 138 #define N_RTTRASH 40 139 { .n_name = "_rttrash" }, 140 #define N_NCPUS 41 141 { .n_name = "_ncpus" }, 142 #define N_CARPSTAT 42 143 { .n_name = "_carpstats" }, 144 #define N_NMBJCLUSTERS 43 145 { .n_name = "_nmbjclusters" }, 146 { .n_name = NULL }, 147 }; 148 149 struct protox { 150 u_char pr_index; /* index into nlist of cb head */ 151 u_char pr_sindex; /* index into nlist of stat block */ 152 u_char pr_wanted; /* 1 if wanted, 0 otherwise */ 153 void (*pr_cblocks)(u_long, const char *, int); 154 /* control blocks printing routine */ 155 void (*pr_stats)(u_long, const char *, int); 156 /* statistics printing routine */ 157 void (*pr_istats)(char *); /* per/if statistics printing routine */ 158 const char *pr_name; /* well-known name */ 159 u_int pr_usesysctl; /* true if we use sysctl, not kvm */ 160 } protox[] = { 161 { -1, -1, 1, protopr, 162 tcp_stats, NULL, "tcp", IPPROTO_TCP }, 163 { -1, -1, 1, protopr, 164 udp_stats, NULL, "udp", IPPROTO_UDP }, 165 { -1, -1, 1, protopr, 166 NULL, NULL, "divert",IPPROTO_DIVERT }, 167 { -1, -1, 1, protopr, 168 ip_stats, NULL, "ip", IPPROTO_RAW }, 169 { -1, -1, 1, protopr, 170 icmp_stats, NULL, "icmp", IPPROTO_ICMP }, 171 { -1, -1, 1, protopr, 172 igmp_stats, NULL, "igmp", IPPROTO_IGMP }, 173 #ifdef IPSEC 174 { -1, N_IPSECSTAT, 1, 0, 175 ipsec_stats, NULL, "ipsec", 0}, 176 #endif 177 { -1, N_CARPSTAT, 1, 0, 178 carp_stats, NULL, "carp", 0}, 179 { -1, -1, 0, 0, 180 0, NULL, NULL, 0} 181 }; 182 183 #ifdef INET6 184 struct protox ip6protox[] = { 185 { -1, -1, 1, protopr, 186 tcp_stats, NULL, "tcp", IPPROTO_TCP }, 187 { -1, -1, 1, protopr, 188 udp_stats, NULL, "udp", IPPROTO_UDP }, 189 { -1, N_IP6STAT, 1, protopr, 190 ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, 191 { -1, N_ICMP6STAT, 1, protopr, 192 icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, 193 #ifdef IPSEC 194 { -1, N_IPSEC6STAT, 1, 0, 195 ipsec_stats, NULL, "ipsec6",0 }, 196 #endif 197 #ifdef notyet 198 { -1, N_PIM6STAT, 1, 0, 199 pim6_stats, NULL, "pim6", 0 }, 200 #endif 201 { -1, -1, 1, 0, 202 rip6_stats, NULL, "rip6", 0 }, 203 { -1, -1, 1, protopr, 204 pim_stats, NULL, "pim", IPPROTO_PIM }, 205 { -1, -1, 0, 0, 206 0, NULL, 0, 0 } 207 }; 208 #endif /*INET6*/ 209 210 #ifdef IPSEC 211 struct protox pfkeyprotox[] = { 212 { -1, N_PFKEYSTAT, 1, 0, 213 pfkey_stats, NULL, "pfkey", 0 }, 214 { -1, -1, 0, 0, 215 0, NULL, 0, 0 } 216 }; 217 #endif 218 219 struct protox netgraphprotox[] = { 220 { N_NGSOCKS, -1, 1, netgraphprotopr, 221 NULL, NULL, "ctrl", 0 }, 222 { N_NGSOCKS, -1, 1, netgraphprotopr, 223 NULL, NULL, "data", 0 }, 224 { -1, -1, 0, 0, 225 0, NULL, NULL, 0 } 226 }; 227 228 struct protox ipxprotox[] = { 229 { N_IPX, N_IPXSTAT, 1, ipxprotopr, 230 ipx_stats, NULL, "ipx", 0 }, 231 { N_IPX, N_SPXSTAT, 1, ipxprotopr, 232 spx_stats, NULL, "spx", 0 }, 233 { -1, -1, 0, 0, 234 0, NULL, 0, 0 } 235 }; 236 237 #ifdef ISO 238 struct protox isoprotox[] = { 239 { ISO_TP, N_TPSTAT, 1, iso_protopr, 240 tp_stats, NULL, "tp" }, 241 { N_CLTP, N_CLTPSTAT, 1, iso_protopr, 242 cltp_stats, NULL, "cltp" }, 243 { -1, N_CLNPSTAT, 1, 0, 244 clnp_stats, NULL, "clnp"}, 245 { -1, N_ESISSTAT, 1, 0, 246 esis_stats, NULL, "esis"}, 247 { -1, -1, 0, 0, 248 0, NULL, 0 } 249 }; 250 #endif 251 252 struct protox *protoprotox[] = { 253 protox, 254 #ifdef INET6 255 ip6protox, 256 #endif 257 #ifdef IPSEC 258 pfkeyprotox, 259 #endif 260 ipxprotox, 261 #ifdef ISO 262 isoprotox, 263 #endif 264 NULL }; 265 266 static void printproto (struct protox *, const char *, u_long); 267 static void usage (void); 268 static struct protox *name2protox (char *); 269 static struct protox *knownname (char *); 270 271 static kvm_t *kvmd; 272 static char *nlistf = NULL, *memf = NULL; 273 274 int Aflag; /* show addresses of protocol control block */ 275 int aflag; /* show all sockets (including servers) */ 276 int bflag; /* show i/f total bytes in/out */ 277 int cpuflag = -1; /* dump route table from specific cpu */ 278 int dflag; /* show i/f dropped packets */ 279 int gflag; /* show group (multicast) routing or stats */ 280 int iflag; /* show interfaces */ 281 int Lflag; /* show size of listen queues */ 282 int mflag; /* show memory stats */ 283 int Pflag; /* show more protocol info (go past 80 columns) */ 284 int numeric_addr; /* show addresses numerically */ 285 int numeric_port; /* show ports numerically */ 286 static int pflag; /* show given protocol */ 287 int rflag; /* show routing tables (or routing stats) */ 288 int sflag; /* show protocol statistics */ 289 int tflag; /* show i/f watchdog timers */ 290 int Bflag; /* show buffer limit instead of buffer use */ 291 int Wflag; /* wide display */ 292 int zflag; /* zero stats */ 293 294 int interval; /* repeat interval for i/f stats */ 295 296 char *interface; /* desired i/f for stats, or NULL for all i/fs */ 297 int unit; /* unit number for above */ 298 299 int af; /* address family */ 300 301 int 302 main(int argc, char **argv) 303 { 304 struct protox *tp = NULL; /* for printing cblocks & stats */ 305 int ch; 306 int n; 307 308 af = AF_UNSPEC; 309 310 while ((ch = getopt(argc, argv, "Aabc:df:gI:iLlM:mN:nPp:rSsBtuWw:z")) != -1) 311 switch(ch) { 312 case 'A': 313 Aflag = 1; 314 break; 315 case 'a': 316 aflag = 1; 317 break; 318 case 'b': 319 bflag = 1; 320 break; 321 case 'c': 322 kread(0, 0, 0); 323 kread(nl[N_NCPUS].n_value, (char *)&n, sizeof(n)); 324 cpuflag = strtol(optarg, NULL, 0); 325 if (cpuflag < 0 || cpuflag >= n) 326 errx(1, "cpu %d does not exist", cpuflag); 327 break; 328 case 'd': 329 dflag = 1; 330 break; 331 case 'f': 332 if (strcmp(optarg, "ipx") == 0) 333 af = AF_IPX; 334 else if (strcmp(optarg, "inet") == 0) 335 af = AF_INET; 336 #ifdef INET6 337 else if (strcmp(optarg, "inet6") == 0) 338 af = AF_INET6; 339 #endif /*INET6*/ 340 #ifdef INET6 341 else if (strcmp(optarg, "pfkey") == 0) 342 af = PF_KEY; 343 #endif /*INET6*/ 344 else if (strcmp(optarg, "unix") == 0) 345 af = AF_UNIX; 346 else if (strcmp(optarg, "ng") == 0 347 || strcmp(optarg, "netgraph") == 0) 348 af = AF_NETGRAPH; 349 #ifdef ISO 350 else if (strcmp(optarg, "iso") == 0) 351 af = AF_ISO; 352 #endif 353 else if (strcmp(optarg, "link") == 0) 354 af = AF_LINK; 355 else if (strcmp(optarg, "mpls") == 0) 356 af = AF_MPLS; 357 else { 358 errx(1, "%s: unknown address family", optarg); 359 } 360 break; 361 case 'g': 362 gflag = 1; 363 break; 364 case 'I': { 365 char *cp; 366 367 iflag = 1; 368 for (cp = interface = optarg; isalpha(*cp); cp++) 369 continue; 370 unit = atoi(cp); 371 break; 372 } 373 case 'i': 374 iflag = 1; 375 break; 376 case 'L': 377 Lflag = 1; 378 break; 379 case 'M': 380 memf = optarg; 381 break; 382 case 'm': 383 mflag = 1; 384 break; 385 case 'N': 386 nlistf = optarg; 387 break; 388 case 'n': 389 numeric_addr = numeric_port = 1; 390 break; 391 case 'P': 392 Pflag = 1; 393 break; 394 case 'p': 395 if ((tp = name2protox(optarg)) == NULL) { 396 errx(1, 397 "%s: unknown or uninstrumented protocol", 398 optarg); 399 } 400 pflag = 1; 401 break; 402 case 'r': 403 rflag = 1; 404 break; 405 case 's': 406 ++sflag; 407 break; 408 case 'S': 409 numeric_addr = 1; 410 break; 411 case 'B': 412 Bflag = 1; 413 break; 414 case 't': 415 tflag = 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 'z': 429 zflag = 1; 430 break; 431 case '?': 432 default: 433 usage(); 434 } 435 argv += optind; 436 argc -= optind; 437 438 #define BACKWARD_COMPATIBILITY 439 #ifdef BACKWARD_COMPATIBILITY 440 if (*argv) { 441 if (isdigit(**argv)) { 442 interval = atoi(*argv); 443 if (interval <= 0) 444 usage(); 445 ++argv; 446 iflag = 1; 447 } 448 if (*argv) { 449 nlistf = *argv; 450 if (*++argv) 451 memf = *argv; 452 } 453 } 454 #endif 455 456 /* 457 * Discard setgid privileges if not the running kernel so that bad 458 * guys can't print interesting stuff from kernel memory. 459 */ 460 if (nlistf != NULL || memf != NULL) 461 setgid(getgid()); 462 463 if (mflag) { 464 if (memf != NULL) { 465 if (kread(0, 0, 0) == 0) 466 mbpr(nl[N_MBSTAT].n_value, 467 nl[N_MBTYPES].n_value, 468 nl[N_NMBCLUSTERS].n_value, 469 nl[N_NMBJCLUSTERS].n_value, 470 nl[N_NMBUFS].n_value, 471 nl[N_NCPUS].n_value); 472 } else { 473 mbpr(0, 0, 0, 0, 0, 0); 474 } 475 exit(0); 476 } 477 #if 0 478 /* 479 * Keep file descriptors open to avoid overhead 480 * of open/close on each call to get* routines. 481 */ 482 sethostent(1); 483 setnetent(1); 484 #else 485 /* 486 * This does not make sense any more with DNS being default over 487 * the files. Doing a setXXXXent(1) causes a tcp connection to be 488 * used for the queries, which is slower. 489 */ 490 #endif 491 if (iflag && !sflag) { 492 kread(0, 0, 0); 493 intpr(interval, nl[N_IFNET].n_value, NULL, nl[N_NCPUS].n_value); 494 exit(0); 495 } 496 if (rflag) { 497 kread(0, 0, 0); 498 if (sflag) 499 rt_stats(); 500 else 501 routepr(nl[N_RTREE].n_value); 502 exit(0); 503 } 504 if (gflag) { 505 kread(0, 0, 0); 506 if (sflag) { 507 if (af == AF_INET || af == AF_UNSPEC) 508 mrt_stats(nl[N_MRTSTAT].n_value); 509 #ifdef INET6 510 if (af == AF_INET6 || af == AF_UNSPEC) 511 mrt6_stats(nl[N_MRT6STAT].n_value); 512 #endif 513 } else { 514 if (af == AF_INET || af == AF_UNSPEC) 515 mroutepr(nl[N_MFCTABLE].n_value, 516 nl[N_VIFTABLE].n_value); 517 #ifdef INET6 518 if (af == AF_INET6 || af == AF_UNSPEC) 519 mroute6pr(nl[N_MF6CTABLE].n_value, 520 nl[N_MIF6TABLE].n_value); 521 #endif 522 } 523 exit(0); 524 } 525 526 kread(0, 0, 0); 527 if (tp) { 528 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 529 exit(0); 530 } 531 if (af == AF_INET || af == AF_UNSPEC) 532 for (tp = protox; tp->pr_name; tp++) 533 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 534 #ifdef INET6 535 if (af == AF_INET6 || af == AF_UNSPEC) 536 for (tp = ip6protox; tp->pr_name; tp++) 537 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 538 #endif /*INET6*/ 539 #ifdef IPSEC 540 if (af == PF_KEY || af == AF_UNSPEC) 541 for (tp = pfkeyprotox; tp->pr_name; tp++) 542 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 543 #endif /*IPSEC*/ 544 if (af == AF_IPX || af == AF_UNSPEC) { 545 kread(0, 0, 0); 546 for (tp = ipxprotox; tp->pr_name; tp++) 547 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 548 } 549 if (af == AF_NETGRAPH || af == AF_UNSPEC) 550 for (tp = netgraphprotox; tp->pr_name; tp++) 551 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 552 #ifdef ISO 553 if (af == AF_ISO || af == AF_UNSPEC) 554 for (tp = isoprotox; tp->pr_name; tp++) 555 printproto(tp, tp->pr_name, nl[N_NCPUS].n_value); 556 #endif 557 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) 558 unixpr(); 559 exit(0); 560 } 561 562 /* 563 * Print out protocol statistics or control blocks (per sflag). 564 * If the interface was not specifically requested, and the symbol 565 * is not in the namelist, ignore this one. 566 */ 567 static void 568 printproto(struct protox *tp, const char *name, u_long ncpusaddr) 569 { 570 void (*pr)(u_long, const char *, int); 571 u_long off; 572 573 if (sflag) { 574 if (iflag) { 575 if (tp->pr_istats) 576 intpr(interval, nl[N_IFNET].n_value, 577 tp->pr_istats, ncpusaddr); 578 else if (pflag) 579 printf("%s: no per-interface stats routine\n", 580 tp->pr_name); 581 return; 582 } 583 else { 584 pr = tp->pr_stats; 585 if (!pr) { 586 if (pflag) 587 printf("%s: no stats routine\n", 588 tp->pr_name); 589 return; 590 } 591 off = tp->pr_usesysctl ? tp->pr_usesysctl 592 : nl[tp->pr_sindex].n_value; 593 } 594 } else { 595 pr = tp->pr_cblocks; 596 if (!pr) { 597 if (pflag) 598 printf("%s: no PCB routine\n", tp->pr_name); 599 return; 600 } 601 off = tp->pr_usesysctl ? tp->pr_usesysctl 602 : nl[tp->pr_index].n_value; 603 } 604 if (pr != NULL && (off || af != AF_UNSPEC)) 605 (*pr)(off, name, af); 606 } 607 608 /* 609 * Read kernel memory, return 0 on success. 610 */ 611 int 612 kread(u_long addr, char *buf, int size) 613 { 614 if (kvmd == NULL) { 615 /* 616 * XXX. 617 */ 618 kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); 619 if (kvmd != NULL) { 620 if (kvm_nlist(kvmd, nl) < 0) { 621 if(nlistf) 622 errx(1, "%s: kvm_nlist: %s", nlistf, 623 kvm_geterr(kvmd)); 624 else 625 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); 626 } 627 628 if (nl[0].n_type == 0) { 629 if(nlistf) 630 errx(1, "%s: no namelist", nlistf); 631 else 632 errx(1, "no namelist"); 633 } 634 } else { 635 warnx("kvm not available"); 636 return(-1); 637 } 638 } 639 if (!buf) 640 return (0); 641 if (kvm_read(kvmd, addr, buf, size) != size) { 642 warnx("%s", kvm_geterr(kvmd)); 643 return (-1); 644 } 645 return (0); 646 } 647 648 const char * 649 plural(int n) 650 { 651 return (n != 1 ? "s" : ""); 652 } 653 654 const char * 655 plurales(int n) 656 { 657 return (n != 1 ? "es" : ""); 658 } 659 660 /* 661 * Find the protox for the given "well-known" name. 662 */ 663 static struct protox * 664 knownname(char *name) 665 { 666 struct protox **tpp, *tp; 667 668 for (tpp = protoprotox; *tpp; tpp++) 669 for (tp = *tpp; tp->pr_name; tp++) 670 if (strcmp(tp->pr_name, name) == 0) 671 return (tp); 672 return (NULL); 673 } 674 675 /* 676 * Find the protox corresponding to name. 677 */ 678 static struct protox * 679 name2protox(char *name) 680 { 681 struct protox *tp; 682 char **alias; /* alias from p->aliases */ 683 struct protoent *p; 684 685 /* 686 * Try to find the name in the list of "well-known" names. If that 687 * fails, check if name is an alias for an Internet protocol. 688 */ 689 if ((tp = knownname(name)) != NULL) 690 return (tp); 691 692 setprotoent(1); /* make protocol lookup cheaper */ 693 while ((p = getprotoent()) != NULL) { 694 /* assert: name not same as p->name */ 695 for (alias = p->p_aliases; *alias; alias++) 696 if (strcmp(name, *alias) == 0) { 697 endprotoent(); 698 return (knownname(p->p_name)); 699 } 700 } 701 endprotoent(); 702 return (NULL); 703 } 704 705 static void 706 usage(void) 707 { 708 (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 709 "usage: netstat [-AaLnPSW] [-c cpu] [-f protocol_family | -p protocol]\n" 710 " [-M core] [-N system]", 711 " netstat -i | -I interface [-aBbdnt] [-f address_family]\n" 712 " [-M core] [-N system]", 713 " netstat -w wait [-I interface] [-d] [-M core] [-N system]", 714 " netstat -s [-s] [-z] [-f protocol_family | -p protocol] [-M core]", 715 " netstat -i | -I interface -s [-f protocol_family | -p protocol]\n" 716 " [-M core] [-N system]", 717 " netstat -m [-M core] [-N system]", 718 " netstat -r [-AanW] [-f address_family] [-M core] [-N system]", 719 " netstat -rs [-s] [-M core] [-N system]", 720 " netstat -g [-W] [-f address_family] [-M core] [-N system]", 721 " netstat -gs [-s] [-f address_family] [-M core] [-N system]"); 722 exit(1); 723 } 724