]> git.cameronkatri.com Git - apple_cmds.git/blob - network_cmds/netstat.tproj/main.c
md5: Don't symlink non working bins, setuid appropriate bins
[apple_cmds.git] / network_cmds / netstat.tproj / main.c
1 /*
2 * Copyright (c) 2008-2020 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
62 char 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
106 struct 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
130 struct 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
145 struct protox pfkeyprotox[] = {
146 { NULL, pfkey_stats, NULL, "pfkey", PF_KEY_V2 },
147 { NULL, NULL, NULL, NULL, 0 }
148 };
149 #endif
150
151
152 struct 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
159 struct protox nstatprotox[] = {
160 { NULL, print_nstat_stats, NULL, "nstat", 0 },
161 { NULL, NULL, NULL, NULL, 0 }
162 };
163
164 struct protox ipcprotox[] = {
165 { NULL, print_extbkidle_stats, NULL, "xbkidle", 0 },
166 { NULL, NULL, NULL, NULL, 0 }
167 };
168
169 struct protox kernprotox[] = {
170 { NULL, print_net_api_stats, NULL, "net_api", 0 },
171 { NULL, NULL, NULL, NULL, 0 }
172 };
173
174 #ifdef AF_VSOCK
175 struct protox vsockprotox[] = {
176 { vsockpr, NULL, NULL, "vsock", 0 },
177 { NULL, NULL, NULL, NULL, 0 }
178 };
179 #endif
180
181 struct protox *protoprotox[] = {
182 protox,
183 #ifdef INET6
184 ip6protox,
185 #endif
186 #ifdef IPSEC
187 pfkeyprotox,
188 #endif
189 systmprotox,
190 nstatprotox,
191 ipcprotox,
192 kernprotox,
193 #ifdef AF_VSOCK
194 vsockprotox,
195 #endif
196 NULL
197 };
198
199 static void printproto (struct protox *, char *);
200 static void usage (void);
201 static struct protox *name2protox (char *);
202 static struct protox *knownname (char *);
203 #ifdef SRVCACHE
204 extern void _serv_cache_close();
205 #endif
206
207 int Aflag; /* show addresses of protocol control block */
208 int aflag; /* show all sockets (including servers) */
209 int bflag; /* show i/f total bytes in/out */
210 int cflag; /* show specific classq */
211 int dflag; /* show i/f dropped packets */
212 int Fflag; /* show i/f forwarded packets */
213 #if defined(__APPLE__)
214 int gflag; /* show group (multicast) routing or stats */
215 #endif
216 int iflag; /* show interfaces */
217 int lflag; /* show routing table with more information */
218 int Lflag; /* show size of listen queues */
219 int mflag; /* show memory stats */
220 int nflag; /* show addresses numerically */
221 static int pflag; /* show given protocol */
222 int prioflag = -1; /* show packet priority statistics */
223 int Rflag; /* show reachability information */
224 int rflag; /* show routing tables (or routing stats) */
225 int sflag; /* show protocol statistics */
226 int Sflag; /* show additional i/f link status */
227 int tflag; /* show i/f watchdog timers */
228 int vflag; /* more verbose */
229 int Wflag; /* wide display */
230 int qflag; /* classq stats display */
231 int Qflag; /* opportunistic polling stats display */
232 int xflag; /* show extended link-layer reachability information */
233 int zflag; /* show only entries with non zero rtt metrics */
234
235 int cq = -1; /* send classq index (-1 for all) */
236 int interval; /* repeat interval for i/f stats */
237
238 char *interface; /* desired i/f for stats, or NULL for all i/fs */
239 int unit; /* unit number for above */
240
241 int af; /* address family */
242
243 int
244 main(argc, argv)
245 int argc;
246 char *argv[];
247 {
248 register struct protox *tp = NULL; /* for printing cblocks & stats */
249 int ch;
250
251 af = AF_UNSPEC;
252
253 while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:xz")) != -1)
254 switch(ch) {
255 case 'A':
256 Aflag = 1;
257 break;
258 case 'a':
259 aflag = 1;
260 break;
261 case 'b':
262 bflag = 1;
263 break;
264 case 'c':
265 cflag = 1;
266 cq = atoi(optarg);
267 break;
268 case 'd':
269 dflag = 1;
270 break;
271 case 'F':
272 Fflag = 1;
273 break;
274 case 'f':
275 if (strcmp(optarg, "ipx") == 0)
276 af = AF_IPX;
277 else if (strcmp(optarg, "inet") == 0)
278 af = AF_INET;
279 #ifdef INET6
280 else if (strcmp(optarg, "inet6") == 0)
281 af = AF_INET6;
282 #endif /*INET6*/
283 #ifdef INET6
284 else if (strcmp(optarg, "pfkey") == 0)
285 af = PF_KEY;
286 #endif /*INET6*/
287 else if (strcmp(optarg, "unix") == 0)
288 af = AF_UNIX;
289 else if (strcmp(optarg, "systm") == 0)
290 af = AF_SYSTEM;
291 else {
292 errx(1, "%s: unknown address family", optarg);
293 }
294 break;
295 #if defined(__APPLE__)
296 case 'g':
297 gflag = 1;
298 break;
299 #endif
300 case 'I': {
301 char *cp;
302
303 iflag = 1;
304 for (cp = interface = optarg; isalpha(*cp); cp++)
305 continue;
306 unit = atoi(cp);
307 break;
308 }
309 case 'i':
310 iflag = 1;
311 break;
312 case 'l':
313 lflag += 1;
314 break;
315 case 'L':
316 Lflag = 1;
317 break;
318 case 'm':
319 mflag++;
320 break;
321 case 'n':
322 nflag = 1;
323 break;
324 case 'P':
325 prioflag = atoi(optarg);
326 break;
327 case 'p':
328 if ((tp = name2protox(optarg)) == NULL) {
329 errx(1,
330 "%s: unknown or uninstrumented protocol",
331 optarg);
332 }
333 pflag = 1;
334 break;
335 case 'q':
336 qflag++;
337 break;
338 case 'Q':
339 Qflag++;
340 break;
341 case 'R':
342 Rflag = 1;
343 break;
344 case 'r':
345 rflag = 1;
346 break;
347 case 's':
348 ++sflag;
349 break;
350 case 'S':
351 Sflag = 1;
352 break;
353 case 't':
354 tflag = 1;
355 break;
356 case 'u':
357 af = AF_UNIX;
358 break;
359 case 'v':
360 vflag++;
361 break;
362 case 'W':
363 Wflag = 1;
364 break;
365 case 'w':
366 interval = atoi(optarg);
367 iflag = 1;
368 break;
369 case 'x':
370 xflag = 1;
371 Rflag = 1;
372 break;
373 case 'z':
374 zflag = 1;
375 break;
376 case '?':
377 default:
378 usage();
379 }
380 argv += optind;
381 argc -= optind;
382
383 #define BACKWARD_COMPATIBILITY
384 #ifdef BACKWARD_COMPATIBILITY
385 if (*argv) {
386 if (isdigit(**argv)) {
387 interval = atoi(*argv);
388 if (interval <= 0)
389 usage();
390 ++argv;
391 iflag = 1;
392 }
393 }
394 #endif
395
396 if (mflag) {
397 mbpr();
398 exit(0);
399 }
400 if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) {
401 if (Rflag)
402 intpr_ri(NULL);
403 else
404 intpr(NULL);
405 exit(0);
406 }
407 if (rflag) {
408 if (sflag)
409 rt_stats();
410 else
411 routepr();
412 exit(0);
413 }
414 if (qflag || Qflag) {
415 if (interface == NULL) {
416 fprintf(stderr, "%s statistics option "
417 "requires interface name\n", qflag ? "Queue" :
418 "Polling");
419 } else if (qflag) {
420 aqstatpr();
421 } else {
422 rxpollstatpr();
423 }
424 exit(0);
425 }
426 if (Sflag) {
427 if (interface == NULL) {
428 fprintf(stderr, "additional link status option"
429 " requires interface name\n");
430 } else {
431 print_link_status(interface);
432 }
433 exit(0);
434 }
435
436 #if defined(__APPLE__)
437 if (gflag) {
438 ifmalist_dump();
439 exit(0);
440 }
441 #endif
442
443 if (tp) {
444 printproto(tp, tp->pr_name);
445 exit(0);
446 }
447 if (af == AF_INET || af == AF_UNSPEC)
448 for (tp = protox; tp->pr_name; tp++)
449 printproto(tp, tp->pr_name);
450 #ifdef INET6
451 if (af == AF_INET6 || af == AF_UNSPEC)
452 for (tp = ip6protox; tp->pr_name; tp++)
453 printproto(tp, tp->pr_name);
454 #endif /*INET6*/
455 #ifdef IPSEC
456 if (af == PF_KEY || af == AF_UNSPEC)
457 for (tp = pfkeyprotox; tp->pr_name; tp++)
458 printproto(tp, tp->pr_name);
459 #endif /*IPSEC*/
460 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
461 unixpr();
462
463 if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag)
464 for (tp = systmprotox; tp->pr_name; tp++)
465 printproto(tp, tp->pr_name);
466 #if TARGET_OS_IPHONE
467 if (af == AF_UNSPEC && !Lflag)
468 for (tp = nstatprotox; tp->pr_name; tp++)
469 printproto(tp, tp->pr_name);
470 #endif /* TARGET_OS_IPHONE */
471
472 if (af == AF_UNSPEC && !Lflag)
473 for (tp = ipcprotox; tp->pr_name; tp++)
474 printproto(tp, tp->pr_name);
475
476 if (af == AF_UNSPEC && !Lflag)
477 for (tp = kernprotox; tp->pr_name; tp++)
478 printproto(tp, tp->pr_name);
479
480 #ifdef AF_VSOCK
481 if (af == AF_VSOCK || af == AF_UNSPEC)
482 for (tp = vsockprotox; tp->pr_name; tp++)
483 printproto(tp, tp->pr_name);
484 #endif /*AF_VSOCK*/
485
486 #ifdef SRVCACHE
487 _serv_cache_close();
488 #endif
489 exit(0);
490 }
491
492 /*
493 * Print out protocol statistics or control blocks (per sflag).
494 * If the interface was not specifically requested, and the symbol
495 * is not in the namelist, ignore this one.
496 */
497 static void
498 printproto(tp, name)
499 register struct protox *tp;
500 char *name;
501 {
502 void (*pr)(uint32_t, char *, int);
503 uint32_t off;
504
505 if (sflag) {
506 if (iflag && !pflag) {
507 if (tp->pr_istats)
508 intpr(tp->pr_istats);
509 else if (vflag)
510 printf("%s: no per-interface stats routine\n",
511 tp->pr_name);
512 return;
513 }
514 else {
515 pr = tp->pr_stats;
516 if (!pr) {
517 if (pflag && vflag)
518 printf("%s: no stats routine\n",
519 tp->pr_name);
520 return;
521 }
522 off = tp->pr_protocol;
523 }
524 } else {
525 pr = tp->pr_cblocks;
526 if (!pr) {
527 if (pflag && vflag)
528 printf("%s: no PCB routine\n", tp->pr_name);
529 return;
530 }
531 off = tp->pr_protocol;
532 }
533 if (pr != NULL) {
534 if (sflag && iflag && pflag)
535 intervalpr(pr, off, name, af);
536 else
537 (*pr)(off, name, af);
538 } else {
539 printf("### no stats for %s\n", name);
540 }
541 }
542
543 char *
544 plural(int n)
545 {
546 return (n > 1 ? "s" : "");
547 }
548
549 char *
550 plurales(int n)
551 {
552 return (n > 1 ? "es" : "");
553 }
554
555 char *
556 pluralies(int n)
557 {
558 return (n > 1 ? "ies" : "y");
559 }
560
561 /*
562 * Find the protox for the given "well-known" name.
563 */
564 static struct protox *
565 knownname(char *name)
566 {
567 struct protox **tpp, *tp;
568
569 for (tpp = protoprotox; *tpp; tpp++)
570 for (tp = *tpp; tp->pr_name; tp++)
571 if (strcmp(tp->pr_name, name) == 0)
572 return (tp);
573 return (NULL);
574 }
575
576 /*
577 * Find the protox corresponding to name.
578 */
579 static struct protox *
580 name2protox(char *name)
581 {
582 struct protox *tp;
583 char **alias; /* alias from p->aliases */
584 struct protoent *p;
585
586 /*
587 * Try to find the name in the list of "well-known" names. If that
588 * fails, check if name is an alias for an Internet protocol.
589 */
590 if ((tp = knownname(name)) != NULL)
591 return (tp);
592
593 setprotoent(1); /* make protocol lookup cheaper */
594 while ((p = getprotoent()) != NULL) {
595 /* assert: name not same as p->name */
596 for (alias = p->p_aliases; *alias; alias++)
597 if (strcmp(name, *alias) == 0) {
598 tp = knownname(p->p_name);
599 endprotoent();
600 return tp;
601 }
602 }
603 endprotoent();
604 return (NULL);
605 }
606
607 #define NETSTAT_USAGE "\
608 Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
609 netstat [-gilns] [-f address_family]\n\
610 netstat -i | -I interface [-w wait] [-abdgRtS]\n\
611 netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
612 netstat -i | -I interface -s [-f address_family | -p protocol]\n\
613 netstat -m [-m]\n\
614 netstat -r [-Aaln] [-f address_family]\n\
615 netstat -rs [-s]\n\
616 "
617
618 static void
619 usage(void)
620 {
621 (void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
622 exit(1);
623 }
624
625 int
626 print_time(void)
627 {
628 time_t now;
629 struct tm tm;
630 int num_written = 0;
631
632 (void) time(&now);
633 (void) localtime_r(&now, &tm);
634
635 num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec);
636
637 return (num_written);
638 }
639