1/* 2 * Copyright (c) 2008-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1983, 1988, 1993 30 * Regents of the University of California. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Berkeley and its contributors. 44 * 4. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61#ifndef lint 62char const copyright[] = 63"@(#) Copyright (c) 1983, 1988, 1993\n\ 64 Regents of the University of California. All rights reserved.\n"; 65#endif /* not lint */ 66 67#include <sys/param.h> 68#include <sys/file.h> 69#include <sys/socket.h> 70#include <sys/sys_domain.h> 71 72#include <netinet/in.h> 73#include <net/pfkeyv2.h> 74 75#include <ctype.h> 76#include <err.h> 77#include <errno.h> 78#include <limits.h> 79#include <netdb.h> 80#include <nlist.h> 81#include <paths.h> 82#include <stdio.h> 83#include <stdlib.h> 84#include <string.h> 85#include <unistd.h> 86#include "netstat.h" 87#include <sys/types.h> 88#include <sys/sysctl.h> 89 90#ifdef __APPLE__ 91#include <TargetConditionals.h> 92#endif 93 94/* 95 * ---------------------------------------------------------------------------- 96 * "THE BEER-WARE LICENSE" (Revision 42): 97 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 98 * can do whatever you want with this stuff. If we meet some day, and you think 99 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 100 * ---------------------------------------------------------------------------- 101 * 102 * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $ 103 * 104 */ 105 106struct protox { 107 void (*pr_cblocks)(uint32_t, char *, int); 108 /* control blocks printing routine */ 109 void (*pr_stats)(uint32_t, char *, int); 110 /* statistics printing routine */ 111 void (*pr_istats)(char *); /* per/if statistics printing routine */ 112 char *pr_name; /* well-known name */ 113 int pr_protocol; 114} protox[] = { 115 { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, 116 { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, 117 { protopr, NULL, NULL, "divert", IPPROTO_DIVERT }, 118 { protopr, ip_stats, NULL, "ip", IPPROTO_RAW }, 119 { protopr, icmp_stats, NULL, "icmp", IPPROTO_ICMP }, 120 { protopr, igmp_stats, NULL, "igmp", IPPROTO_IGMP }, 121#ifdef IPSEC 122 { NULL, ipsec_stats, NULL, "ipsec", IPPROTO_ESP}, 123#endif 124 { NULL, arp_stats, NULL, "arp", 0 }, 125 { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, 126 { NULL, NULL, NULL, NULL, 0 } 127}; 128 129#ifdef INET6 130struct protox ip6protox[] = { 131 { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, 132 { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, 133 { protopr, ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, 134 { protopr, icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, 135#ifdef IPSEC 136 { NULL, ipsec_stats, NULL, "ipsec6", IPPROTO_ESP }, 137#endif 138 { NULL, rip6_stats, NULL, "rip6", IPPROTO_RAW }, 139 { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, 140 { NULL, NULL, NULL, NULL, 0 } 141}; 142#endif /*INET6*/ 143 144#ifdef IPSEC 145struct protox pfkeyprotox[] = { 146 { NULL, pfkey_stats, NULL, "pfkey", PF_KEY_V2 }, 147 { NULL, NULL, NULL, NULL, 0 } 148}; 149#endif 150 151 152struct protox systmprotox[] = { 153 { systmpr, NULL, NULL, "reg", 0 }, 154 { systmpr, kevt_stats, NULL, "kevt", SYSPROTO_EVENT }, 155 { systmpr, kctl_stats, NULL, "kctl", SYSPROTO_CONTROL }, 156 { NULL, NULL, NULL, NULL, 0 } 157}; 158 159struct protox *protoprotox[] = { 160 protox, 161#ifdef INET6 162 ip6protox, 163#endif 164#ifdef IPSEC 165 pfkeyprotox, 166#endif 167 systmprotox, 168 NULL 169}; 170 171static void printproto (struct protox *, char *); 172static void usage (void); 173static struct protox *name2protox (char *); 174static struct protox *knownname (char *); 175#ifdef SRVCACHE 176extern void _serv_cache_close(); 177#endif 178 179int Aflag; /* show addresses of protocol control block */ 180int aflag; /* show all sockets (including servers) */ 181int bflag; /* show i/f total bytes in/out */ 182int cflag; /* show specific classq */ 183int dflag; /* show i/f dropped packets */ 184int Fflag; /* show i/f forwarded packets */ 185#if defined(__APPLE__) 186int gflag; /* show group (multicast) routing or stats */ 187#endif 188int iflag; /* show interfaces */ 189int lflag; /* show routing table with use and ref */ 190int Lflag; /* show size of listen queues */ 191int mflag; /* show memory stats */ 192int nflag; /* show addresses numerically */ 193static int pflag; /* show given protocol */ 194int prioflag = -1; /* show packet priority statistics */ 195int Rflag; /* show reachability information */ 196int rflag; /* show routing tables (or routing stats) */ 197int sflag; /* show protocol statistics */ 198int tflag; /* show i/f watchdog timers */ 199int vflag; /* more verbose */ 200int Wflag; /* wide display */ 201int qflag; /* classq stats display */ 202int Qflag; /* opportunistic polling stats display */ 203int xflag; /* show extended link-layer reachability information */ 204 205int cq = -1; /* send classq index (-1 for all) */ 206int interval; /* repeat interval for i/f stats */ 207 208char *interface; /* desired i/f for stats, or NULL for all i/fs */ 209int unit; /* unit number for above */ 210 211int af; /* address family */ 212 213int 214main(argc, argv) 215 int argc; 216 char *argv[]; 217{ 218 register struct protox *tp = NULL; /* for printing cblocks & stats */ 219 int ch; 220 221 af = AF_UNSPEC; 222 223 while ((ch = getopt(argc, argv, "Aabc:dFf:gI:iLlmnP:p:qQrRstuvWw:x")) != -1) 224 switch(ch) { 225 case 'A': 226 Aflag = 1; 227 break; 228 case 'a': 229 aflag = 1; 230 break; 231 case 'b': 232 bflag = 1; 233 break; 234 case 'c': 235 cflag = 1; 236 cq = atoi(optarg); 237 break; 238 case 'd': 239 dflag = 1; 240 break; 241 case 'F': 242 Fflag = 1; 243 break; 244 case 'f': 245 if (strcmp(optarg, "ipx") == 0) 246 af = AF_IPX; 247 else if (strcmp(optarg, "inet") == 0) 248 af = AF_INET; 249#ifdef INET6 250 else if (strcmp(optarg, "inet6") == 0) 251 af = AF_INET6; 252#endif /*INET6*/ 253#ifdef INET6 254 else if (strcmp(optarg, "pfkey") == 0) 255 af = PF_KEY; 256#endif /*INET6*/ 257 else if (strcmp(optarg, "unix") == 0) 258 af = AF_UNIX; 259 else if (strcmp(optarg, "systm") == 0) 260 af = AF_SYSTEM; 261 else { 262 errx(1, "%s: unknown address family", optarg); 263 } 264 break; 265#if defined(__APPLE__) 266 case 'g': 267 gflag = 1; 268 break; 269#endif 270 case 'I': { 271 char *cp; 272 273 iflag = 1; 274 for (cp = interface = optarg; isalpha(*cp); cp++) 275 continue; 276 unit = atoi(cp); 277 break; 278 } 279 case 'i': 280 iflag = 1; 281 break; 282 case 'l': 283 lflag = 1; 284 break; 285 case 'L': 286 Lflag = 1; 287 break; 288 case 'm': 289 mflag++; 290 break; 291 case 'n': 292 nflag = 1; 293 break; 294 case 'P': 295 prioflag = atoi(optarg); 296 break; 297 case 'p': 298 if ((tp = name2protox(optarg)) == NULL) { 299 errx(1, 300 "%s: unknown or uninstrumented protocol", 301 optarg); 302 } 303 pflag = 1; 304 break; 305 case 'q': 306 qflag++; 307 break; 308 case 'Q': 309 Qflag++; 310 break; 311 case 'R': 312 Rflag = 1; 313 break; 314 case 'r': 315 rflag = 1; 316 break; 317 case 's': 318 ++sflag; 319 break; 320 case 't': 321 tflag = 1; 322 break; 323 case 'u': 324 af = AF_UNIX; 325 break; 326 case 'v': 327 vflag++; 328 break; 329 case 'W': 330 Wflag = 1; 331 break; 332 case 'w': 333 interval = atoi(optarg); 334 iflag = 1; 335 break; 336 case 'x': 337 xflag = 1; 338 Rflag = 1; 339 break; 340 case '?': 341 default: 342 usage(); 343 } 344 argv += optind; 345 argc -= optind; 346 347#define BACKWARD_COMPATIBILITY 348#ifdef BACKWARD_COMPATIBILITY 349 if (*argv) { 350 if (isdigit(**argv)) { 351 interval = atoi(*argv); 352 if (interval <= 0) 353 usage(); 354 ++argv; 355 iflag = 1; 356 } 357 } 358#endif 359 360 if (mflag) { 361 mbpr(); 362 exit(0); 363 } 364 if (iflag && !sflag && !gflag && !qflag && !Qflag) { 365 if (Rflag) 366 intpr_ri(NULL); 367 else 368 intpr(NULL); 369 exit(0); 370 } 371 if (rflag) { 372 if (sflag) 373 rt_stats(); 374 else 375 routepr(); 376 exit(0); 377 } 378 if (qflag || Qflag) { 379 if (interface == NULL) { 380 fprintf(stderr, "%s statistics option " 381 "requires interface name\n", qflag ? "Queue" : 382 "Polling"); 383 } else if (qflag) { 384 aqstatpr(); 385 } else { 386 rxpollstatpr(); 387 } 388 exit(0); 389 } 390 391#if defined(__APPLE__) 392 if (gflag) { 393 ifmalist_dump(); 394 exit(0); 395 } 396#endif 397 398 if (tp) { 399 printproto(tp, tp->pr_name); 400 exit(0); 401 } 402 if (af == AF_INET || af == AF_UNSPEC) 403 for (tp = protox; tp->pr_name; tp++) 404 printproto(tp, tp->pr_name); 405#ifdef INET6 406 if (af == AF_INET6 || af == AF_UNSPEC) 407 for (tp = ip6protox; tp->pr_name; tp++) 408 printproto(tp, tp->pr_name); 409#endif /*INET6*/ 410#ifdef IPSEC 411 if (af == PF_KEY || af == AF_UNSPEC) 412 for (tp = pfkeyprotox; tp->pr_name; tp++) 413 printproto(tp, tp->pr_name); 414#endif /*IPSEC*/ 415 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) 416 unixpr(); 417 418 if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag) 419 for (tp = systmprotox; tp->pr_name; tp++) 420 printproto(tp, tp->pr_name); 421 422#ifdef SRVCACHE 423 _serv_cache_close(); 424#endif 425 exit(0); 426} 427 428/* 429 * Print out protocol statistics or control blocks (per sflag). 430 * If the interface was not specifically requested, and the symbol 431 * is not in the namelist, ignore this one. 432 */ 433static void 434printproto(tp, name) 435 register struct protox *tp; 436 char *name; 437{ 438 void (*pr)(uint32_t, char *, int); 439 uint32_t off; 440 441 if (sflag) { 442 if (iflag && !pflag) { 443 if (tp->pr_istats) 444 intpr(tp->pr_istats); 445 else if (vflag) 446 printf("%s: no per-interface stats routine\n", 447 tp->pr_name); 448 return; 449 } 450 else { 451 pr = tp->pr_stats; 452 if (!pr) { 453 if (pflag && vflag) 454 printf("%s: no stats routine\n", 455 tp->pr_name); 456 return; 457 } 458 off = tp->pr_protocol; 459 } 460 } else { 461 pr = tp->pr_cblocks; 462 if (!pr) { 463 if (pflag && vflag) 464 printf("%s: no PCB routine\n", tp->pr_name); 465 return; 466 } 467 off = tp->pr_protocol; 468 } 469 if (pr != NULL) { 470 if (sflag && iflag && pflag) 471 intervalpr(pr, off, name, af); 472 else 473 (*pr)(off, name, af); 474 } else { 475 printf("### no stats for %s\n", name); 476 } 477} 478 479char * 480plural(int n) 481{ 482 return (n != 1 ? "s" : ""); 483} 484 485char * 486plurales(int n) 487{ 488 return (n != 1 ? "es" : ""); 489} 490 491char * 492pluralies(int n) 493{ 494 return (n != 1 ? "ies" : "y"); 495} 496 497/* 498 * Find the protox for the given "well-known" name. 499 */ 500static struct protox * 501knownname(char *name) 502{ 503 struct protox **tpp, *tp; 504 505 for (tpp = protoprotox; *tpp; tpp++) 506 for (tp = *tpp; tp->pr_name; tp++) 507 if (strcmp(tp->pr_name, name) == 0) 508 return (tp); 509 return (NULL); 510} 511 512/* 513 * Find the protox corresponding to name. 514 */ 515static struct protox * 516name2protox(char *name) 517{ 518 struct protox *tp; 519 char **alias; /* alias from p->aliases */ 520 struct protoent *p; 521 522 /* 523 * Try to find the name in the list of "well-known" names. If that 524 * fails, check if name is an alias for an Internet protocol. 525 */ 526 if ((tp = knownname(name)) != NULL) 527 return (tp); 528 529 setprotoent(1); /* make protocol lookup cheaper */ 530 while ((p = getprotoent()) != NULL) { 531 /* assert: name not same as p->name */ 532 for (alias = p->p_aliases; *alias; alias++) 533 if (strcmp(name, *alias) == 0) { 534 endprotoent(); 535 return (knownname(p->p_name)); 536 } 537 } 538 endprotoent(); 539 return (NULL); 540} 541 542#define NETSTAT_USAGE "\ 543Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\ 544 netstat [-gilns] [-f address_family]\n\ 545 netstat -i | -I interface [-w wait] [-abdgRt]\n\ 546 netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\ 547 netstat -i | -I interface -s [-f address_family | -p protocol]\n\ 548 netstat -m [-m]\n\ 549 netstat -r [-Aaln] [-f address_family]\n\ 550 netstat -rs [-s]\n\ 551" 552 553static void 554usage(void) 555{ 556 (void) fprintf(stderr, "%s\n", NETSTAT_USAGE); 557 exit(1); 558} 559 560int 561print_time(void) 562{ 563 time_t now; 564 struct tm tm; 565 int num_written = 0; 566 567 (void) time(&now); 568 (void) localtime_r(&now, &tm); 569 570 num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); 571 572 return (num_written); 573} 574 575