1/* 2 * Copyright (c) 2008-2013 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 71#include <netinet/in.h> 72#include <net/pfkeyv2.h> 73 74#include <ctype.h> 75#include <err.h> 76#include <errno.h> 77#include <limits.h> 78#include <netdb.h> 79#include <nlist.h> 80#include <paths.h> 81#include <stdio.h> 82#include <stdlib.h> 83#include <string.h> 84#include <unistd.h> 85#include "netstat.h" 86#include <sys/types.h> 87#include <sys/sysctl.h> 88 89#ifdef __APPLE__ 90#include <TargetConditionals.h> 91#endif 92 93/* 94 * ---------------------------------------------------------------------------- 95 * "THE BEER-WARE LICENSE" (Revision 42): 96 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 97 * can do whatever you want with this stuff. If we meet some day, and you think 98 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 99 * ---------------------------------------------------------------------------- 100 * 101 * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $ 102 * 103 */ 104 105struct protox { 106 void (*pr_cblocks)(uint32_t, char *, int); 107 /* control blocks printing routine */ 108 void (*pr_stats)(uint32_t, char *, int); 109 /* statistics printing routine */ 110 void (*pr_istats)(char *); /* per/if statistics printing routine */ 111 char *pr_name; /* well-known name */ 112 int pr_protocol; 113} protox[] = { 114 { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, 115 { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, 116 { protopr, NULL, NULL, "divert", IPPROTO_DIVERT }, 117 { protopr, ip_stats, NULL, "ip", IPPROTO_RAW }, 118 { protopr, icmp_stats, NULL, "icmp", IPPROTO_ICMP }, 119 { protopr, igmp_stats, NULL, "igmp", IPPROTO_IGMP }, 120#ifdef IPSEC 121 { NULL, ipsec_stats, NULL, "ipsec", IPPROTO_ESP}, 122#endif 123 { NULL, arp_stats, NULL, "arp", 0 }, 124#if TARGET_OS_EMBEDDED 125 { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, 126#endif 127 { NULL, NULL, NULL, NULL, 0 } 128}; 129 130#ifdef INET6 131struct protox ip6protox[] = { 132 { protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP }, 133 { protopr, udp_stats, NULL, "udp", IPPROTO_UDP }, 134 { protopr, ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW }, 135 { protopr, icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 }, 136#ifdef IPSEC 137 { NULL, ipsec_stats, NULL, "ipsec6", IPPROTO_ESP }, 138#endif 139#ifdef notyet 140 { NULL, pim6_stats, NULL, "pim6", 0 }, 141#endif 142 { NULL, rip6_stats, NULL, "rip6", IPPROTO_RAW }, 143#if TARGET_OS_EMBEDDED 144 { mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP }, 145#endif 146 { NULL, NULL, NULL, NULL, 0 } 147}; 148#endif /*INET6*/ 149 150#ifdef IPSEC 151struct protox pfkeyprotox[] = { 152 { NULL, pfkey_stats, NULL, "pfkey", PF_KEY_V2 }, 153 { NULL, NULL, NULL, NULL, 0 } 154}; 155#endif 156 157struct protox *protoprotox[] = { 158 protox, 159#ifdef INET6 160 ip6protox, 161#endif 162#ifdef IPSEC 163 pfkeyprotox, 164#endif 165 NULL 166}; 167 168static void printproto (struct protox *, char *); 169static void usage (void); 170static struct protox *name2protox (char *); 171static struct protox *knownname (char *); 172#ifdef SRVCACHE 173extern void _serv_cache_close(); 174#endif 175 176int Aflag; /* show addresses of protocol control block */ 177int aflag; /* show all sockets (including servers) */ 178int bflag; /* show i/f total bytes in/out */ 179int cflag; /* show specific classq */ 180int dflag; /* show i/f dropped packets */ 181int Fflag; /* show i/f forwarded packets */ 182#if defined(__APPLE__) 183int gflag; /* show group (multicast) routing or stats */ 184#endif 185int iflag; /* show interfaces */ 186int lflag; /* show routing table with use and ref */ 187int Lflag; /* show size of listen queues */ 188int mflag; /* show memory stats */ 189int nflag; /* show addresses numerically */ 190static int pflag; /* show given protocol */ 191int prioflag = -1; /* show packet priority statistics */ 192int Rflag; /* show reachability information */ 193int rflag; /* show routing tables (or routing stats) */ 194int sflag; /* show protocol statistics */ 195int tflag; /* show i/f watchdog timers */ 196int vflag; /* more verbose */ 197int Wflag; /* wide display */ 198int qflag; /* classq stats display */ 199int Qflag; /* opportunistic polling stats display */ 200int xflag; /* show extended link-layer reachability information */ 201 202int cq = -1; /* send classq index (-1 for all) */ 203int interval; /* repeat interval for i/f stats */ 204 205char *interface; /* desired i/f for stats, or NULL for all i/fs */ 206int unit; /* unit number for above */ 207 208int af; /* address family */ 209 210int 211main(argc, argv) 212 int argc; 213 char *argv[]; 214{ 215 register struct protox *tp = NULL; /* for printing cblocks & stats */ 216 int ch; 217 218 af = AF_UNSPEC; 219 220 while ((ch = getopt(argc, argv, "Aabc:dFf:gI:iLlmnP:p:qQrRstuvWw:x")) != -1) 221 switch(ch) { 222 case 'A': 223 Aflag = 1; 224 break; 225 case 'a': 226 aflag = 1; 227 break; 228 case 'b': 229 bflag = 1; 230 break; 231 case 'c': 232 cflag = 1; 233 cq = atoi(optarg); 234 break; 235 case 'd': 236 dflag = 1; 237 break; 238 case 'F': 239 Fflag = 1; 240 break; 241 case 'f': 242 if (strcmp(optarg, "ipx") == 0) 243 af = AF_IPX; 244 else if (strcmp(optarg, "inet") == 0) 245 af = AF_INET; 246#ifdef INET6 247 else if (strcmp(optarg, "inet6") == 0) 248 af = AF_INET6; 249#endif /*INET6*/ 250#ifdef INET6 251 else if (strcmp(optarg, "pfkey") == 0) 252 af = PF_KEY; 253#endif /*INET6*/ 254 else if (strcmp(optarg, "unix") == 0) 255 af = AF_UNIX; 256 else { 257 errx(1, "%s: unknown address family", optarg); 258 } 259 break; 260#if defined(__APPLE__) 261 case 'g': 262 gflag = 1; 263 break; 264#endif 265 case 'I': { 266 char *cp; 267 268 iflag = 1; 269 for (cp = interface = optarg; isalpha(*cp); cp++) 270 continue; 271 unit = atoi(cp); 272 break; 273 } 274 case 'i': 275 iflag = 1; 276 break; 277 case 'l': 278 lflag = 1; 279 break; 280 case 'L': 281 Lflag = 1; 282 break; 283 case 'm': 284 mflag++; 285 break; 286 case 'n': 287 nflag = 1; 288 break; 289 case 'P': 290 prioflag = atoi(optarg); 291 break; 292 case 'p': 293 if ((tp = name2protox(optarg)) == NULL) { 294 errx(1, 295 "%s: unknown or uninstrumented protocol", 296 optarg); 297 } 298 pflag = 1; 299 break; 300 case 'q': 301 qflag++; 302 break; 303 case 'Q': 304 Qflag++; 305 break; 306 case 'R': 307 Rflag = 1; 308 break; 309 case 'r': 310 rflag = 1; 311 break; 312 case 's': 313 ++sflag; 314 break; 315 case 't': 316 tflag = 1; 317 break; 318 case 'u': 319 af = AF_UNIX; 320 break; 321 case 'v': 322 vflag++; 323 break; 324 case 'W': 325 Wflag = 1; 326 break; 327 case 'w': 328 interval = atoi(optarg); 329 iflag = 1; 330 break; 331 case 'x': 332 xflag = 1; 333 Rflag = 1; 334 break; 335 case '?': 336 default: 337 usage(); 338 } 339 argv += optind; 340 argc -= optind; 341 342#define BACKWARD_COMPATIBILITY 343#ifdef BACKWARD_COMPATIBILITY 344 if (*argv) { 345 if (isdigit(**argv)) { 346 interval = atoi(*argv); 347 if (interval <= 0) 348 usage(); 349 ++argv; 350 iflag = 1; 351 } 352 } 353#endif 354 355 if (mflag) { 356 mbpr(); 357 exit(0); 358 } 359 if (iflag && !sflag && !gflag && !qflag && !Qflag) { 360 if (Rflag) 361 intpr_ri(NULL); 362 else 363 intpr(NULL); 364 exit(0); 365 } 366 if (rflag) { 367 if (sflag) 368 rt_stats(); 369 else 370 routepr(); 371 exit(0); 372 } 373 if (qflag || Qflag) { 374 if (interface == NULL) { 375 fprintf(stderr, "%s statistics option " 376 "requires interface name\n", qflag ? "Queue" : 377 "Polling"); 378 } else if (qflag) { 379 aqstatpr(); 380 } else { 381 rxpollstatpr(); 382 } 383 exit(0); 384 } 385 386#if defined(__APPLE__) 387 if (gflag) { 388#if !TARGET_OS_EMBEDDED 389 if (sflag) { 390 if (af == AF_INET || af == AF_UNSPEC) 391 mrt_stats(); 392#ifdef INET6 393 if (af == AF_INET6 || af == AF_UNSPEC) 394 mrt6_stats(); 395#endif 396 } else { 397 if (af == AF_INET || af == AF_UNSPEC) 398 mroutepr(); 399#ifdef INET6 400 if (af == AF_INET6 || af == AF_UNSPEC) 401 mroute6pr(); 402#endif 403 } 404#endif /* !TARGET_OS_EMBEDDED */ 405 ifmalist_dump(); 406 exit(0); 407 } 408#endif 409 410 if (tp) { 411 printproto(tp, tp->pr_name); 412 exit(0); 413 } 414 if (af == AF_INET || af == AF_UNSPEC) 415 for (tp = protox; tp->pr_name; tp++) 416 printproto(tp, tp->pr_name); 417#ifdef INET6 418 if (af == AF_INET6 || af == AF_UNSPEC) 419 for (tp = ip6protox; tp->pr_name; tp++) 420 printproto(tp, tp->pr_name); 421#endif /*INET6*/ 422#ifdef IPSEC 423 if (af == PF_KEY || af == AF_UNSPEC) 424 for (tp = pfkeyprotox; tp->pr_name; tp++) 425 printproto(tp, tp->pr_name); 426#endif /*IPSEC*/ 427 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag) 428 unixpr(); 429#ifdef SRVCACHE 430 _serv_cache_close(); 431#endif 432 exit(0); 433} 434 435/* 436 * Print out protocol statistics or control blocks (per sflag). 437 * If the interface was not specifically requested, and the symbol 438 * is not in the namelist, ignore this one. 439 */ 440static void 441printproto(tp, name) 442 register struct protox *tp; 443 char *name; 444{ 445 void (*pr)(uint32_t, char *, int); 446 uint32_t off; 447 448 if (sflag) { 449 if (iflag && !pflag) { 450 if (tp->pr_istats) 451 intpr(tp->pr_istats); 452 else if (vflag) 453 printf("%s: no per-interface stats routine\n", 454 tp->pr_name); 455 return; 456 } 457 else { 458 pr = tp->pr_stats; 459 if (!pr) { 460 if (pflag && vflag) 461 printf("%s: no stats routine\n", 462 tp->pr_name); 463 return; 464 } 465 off = tp->pr_protocol; 466 } 467 } else { 468 pr = tp->pr_cblocks; 469 if (!pr) { 470 if (pflag && vflag) 471 printf("%s: no PCB routine\n", tp->pr_name); 472 return; 473 } 474 off = tp->pr_protocol; 475 } 476 if (pr != NULL) { 477 if (sflag && iflag && pflag) 478 intervalpr(pr, off, name, af); 479 else 480 (*pr)(off, name, af); 481 } else { 482 printf("### no stats for %s\n", name); 483 } 484} 485 486char * 487plural(int n) 488{ 489 return (n != 1 ? "s" : ""); 490} 491 492char * 493plurales(int n) 494{ 495 return (n != 1 ? "es" : ""); 496} 497 498char * 499pluralies(int n) 500{ 501 return (n != 1 ? "ies" : "y"); 502} 503 504/* 505 * Find the protox for the given "well-known" name. 506 */ 507static struct protox * 508knownname(char *name) 509{ 510 struct protox **tpp, *tp; 511 512 for (tpp = protoprotox; *tpp; tpp++) 513 for (tp = *tpp; tp->pr_name; tp++) 514 if (strcmp(tp->pr_name, name) == 0) 515 return (tp); 516 return (NULL); 517} 518 519/* 520 * Find the protox corresponding to name. 521 */ 522static struct protox * 523name2protox(char *name) 524{ 525 struct protox *tp; 526 char **alias; /* alias from p->aliases */ 527 struct protoent *p; 528 529 /* 530 * Try to find the name in the list of "well-known" names. If that 531 * fails, check if name is an alias for an Internet protocol. 532 */ 533 if ((tp = knownname(name)) != NULL) 534 return (tp); 535 536 setprotoent(1); /* make protocol lookup cheaper */ 537 while ((p = getprotoent()) != NULL) { 538 /* assert: name not same as p->name */ 539 for (alias = p->p_aliases; *alias; alias++) 540 if (strcmp(name, *alias) == 0) { 541 endprotoent(); 542 return (knownname(p->p_name)); 543 } 544 } 545 endprotoent(); 546 return (NULL); 547} 548 549#define NETSTAT_USAGE "\ 550Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\ 551 netstat [-gilns] [-f address_family]\n\ 552 netstat -i | -I interface [-w wait] [-abdgRt]\n\ 553 netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\ 554 netstat -i | -I interface -s [-f address_family | -p protocol]\n\ 555 netstat -m [-m]\n\ 556 netstat -r [-Aaln] [-f address_family]\n\ 557 netstat -rs [-s]\n\ 558" 559 560static void 561usage(void) 562{ 563 (void) fprintf(stderr, "%s\n", NETSTAT_USAGE); 564 exit(1); 565} 566 567int 568print_time(void) 569{ 570 time_t now; 571 struct tm tm; 572 int num_written = 0; 573 574 (void) time(&now); 575 (void) localtime_r(&now, &tm); 576 577 num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); 578 579 return (num_written); 580} 581 582