]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/main.c
network_cmds-396.6.tar.gz
[apple/network_cmds.git] / netstat.tproj / main.c
1 /*
2 * Copyright (c) 2008-2012 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
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
105 static struct nlist nl[] = {
106 #define N_IFNET 0
107 { "_ifnet" },
108 #define N_IMP 1
109 { "_imp_softc" },
110 #define N_RTSTAT 2
111 { "_rtstat" },
112 #define N_UNIXSW 3
113 { "_localsw" },
114 #define N_IDP 4
115 { "_nspcb"},
116 #define N_IDPSTAT 5
117 { "_idpstat"},
118 #define N_SPPSTAT 6
119 { "_spp_istat"},
120 #define N_NSERR 7
121 { "_ns_errstat"},
122 #define N_CLNPSTAT 8
123 { "_clnp_stat"},
124 #define IN_NOTUSED 9
125 { "_tp_inpcb" },
126 #define ISO_TP 10
127 { "_tp_refinfo" },
128 #define N_TPSTAT 11
129 { "_tp_stat" },
130 #define N_ESISSTAT 12
131 { "_esis_stat"},
132 #define N_NIMP 13
133 { "_nimp"},
134 #define N_RTREE 14
135 { "_rt_tables"},
136 #define N_CLTP 15
137 { "_cltb"},
138 #define N_CLTPSTAT 16
139 { "_cltpstat"},
140 #define N_NFILE 17
141 { "_nfile" },
142 #define N_FILE 18
143 { "_file" },
144 #define N_IPX 22
145 { "_ipxpcb"},
146 #define N_IPXSTAT 23
147 { "_ipxstat"},
148 #define N_SPXSTAT 24
149 { "_spx_istat"},
150 #define N_DDPSTAT 25
151 { "_ddpstat"},
152 #define N_DDPCB 26
153 { "_ddpcb"},
154 #define N_NGSOCKS 27
155 { "_ngsocklist"},
156 #define N_IP6STAT 28
157 { "_ip6stat" },
158 #define N_ICMP6STAT 29
159 { "_icmp6stat" },
160 #define N_IPSECSTAT 30
161 { "_ipsecstat" },
162 #define N_IPSEC6STAT 31
163 { "_ipsec6stat" },
164 #define N_PIM6STAT 32
165 { "_pim6stat" },
166 #define N_MRT6PROTO 33
167 { "_ip6_mrtproto" },
168 #define N_MRT6STAT 34
169 { "_mrt6stat" },
170 #define N_MF6CTABLE 35
171 { "_mf6ctable" },
172 #define N_MIF6TABLE 36
173 { "_mif6table" },
174 #define N_PFKEYSTAT 37
175 { "_pfkeystat" },
176 #define N_MBSTAT 38
177 { "_mbstat" },
178 #define N_MBTYPES 39
179 { "_mbtypes" },
180 #define N_NMBCLUSTERS 40
181 { "_nmbclusters" },
182 #define N_NMBUFS 41
183 { "_nmbufs" },
184 #define N_RTTRASH 42
185 { "_rttrash" },
186 { "" },
187 };
188
189
190 struct protox {
191 u_char pr_index; /* index into nlist of cb head */
192 u_char pr_sindex; /* index into nlist of stat block */
193 u_char pr_wanted; /* 1 if wanted, 0 otherwise */
194 void (*pr_cblocks)(uint32_t, char *, int);
195 /* control blocks printing routine */
196 void (*pr_stats)(uint32_t, char *, int);
197 /* statistics printing routine */
198 void (*pr_istats)(char *); /* per/if statistics printing routine */
199 char *pr_name; /* well-known name */
200 int pr_usesysctl; /* true if we use sysctl, not kvm */
201 } protox[] = {
202 { -1, -1, 1, protopr,
203 tcp_stats, NULL, "tcp", IPPROTO_TCP },
204 { -1, -1, 1, protopr,
205 udp_stats, NULL, "udp", IPPROTO_UDP },
206 { -1, -1, 1, protopr,
207 NULL, NULL, "divert",IPPROTO_DIVERT },
208 { -1, -1, 1, protopr,
209 ip_stats, NULL, "ip", IPPROTO_RAW },
210 { -1, -1, 1, protopr,
211 icmp_stats, NULL, "icmp", IPPROTO_ICMP },
212 { -1, -1, 1, protopr,
213 igmp_stats, NULL, "igmp", IPPROTO_IGMP },
214 #ifdef IPSEC
215 { -1, -1, 1, 0,
216 ipsec_stats, NULL, "ipsec", IPPROTO_ESP},
217 #endif
218 { -1, -1, 0, 0,
219 0, NULL, 0 }
220 };
221
222 #ifdef INET6
223 struct protox ip6protox[] = {
224 { -1, -1, 1, protopr,
225 tcp_stats, NULL, "tcp", IPPROTO_TCP },
226 { -1, -1, 1, protopr,
227 udp_stats, NULL, "udp", IPPROTO_UDP },
228 { -1, N_IP6STAT, 1, protopr,
229 ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW },
230 { -1, N_ICMP6STAT, 1, protopr,
231 icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 },
232 #ifdef IPSEC
233 { -1, N_IPSEC6STAT, 1, 0,
234 ipsec_stats, NULL, "ipsec6",IPPROTO_ESP },
235 #endif
236 #ifdef notyet
237 { -1, N_PIM6STAT, 1, 0,
238 pim6_stats, NULL, "pim6", 0 },
239 #endif
240 { -1, -1, 1, 0,
241 rip6_stats, NULL, "rip6", IPPROTO_RAW },
242 { -1, -1, 0, 0,
243 0, NULL, 0, 0 }
244 };
245 #endif /*INET6*/
246
247 #ifdef IPSEC
248 struct protox pfkeyprotox[] = {
249 { -1, N_PFKEYSTAT, 1, 0,
250 pfkey_stats, NULL, "pfkey", PF_KEY_V2 },
251 { -1, -1, 0, 0,
252 0, NULL, 0, 0 }
253 };
254 #endif
255
256 struct protox *protoprotox[] = {
257 protox,
258 #ifdef INET6
259 ip6protox,
260 #endif
261 #ifdef IPSEC
262 pfkeyprotox,
263 #endif
264 NULL };
265
266 static void printproto (struct protox *, char *);
267 static void usage (void);
268 static struct protox *name2protox (char *);
269 static struct protox *knownname (char *);
270 #ifdef SRVCACHE
271 extern void _serv_cache_close();
272 #endif
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 cflag; /* show specific classq */
278 int dflag; /* show i/f dropped packets */
279 #if defined(__APPLE__)
280 int gflag; /* show group (multicast) routing or stats */
281 #endif
282 int iflag; /* show interfaces */
283 int lflag; /* show routing table with use and ref */
284 int Lflag; /* show size of listen queues */
285 int mflag; /* show memory stats */
286 int nflag; /* show addresses numerically */
287 static int pflag; /* show given protocol */
288 int prioflag = -1; /* show packet priority statistics */
289 int Rflag; /* show reachability information */
290 int rflag; /* show routing tables (or routing stats) */
291 int sflag; /* show protocol statistics */
292 int tflag; /* show i/f watchdog timers */
293 int vflag; /* more verbose */
294 int Wflag; /* wide display */
295 int qflag; /* classq stats display */
296 int Qflag; /* opportunistic polling stats display */
297 int xflag; /* show extended link-layer reachability information */
298
299 int cq = -1; /* send classq index (-1 for all) */
300 int interval; /* repeat interval for i/f stats */
301
302 char *interface; /* desired i/f for stats, or NULL for all i/fs */
303 int unit; /* unit number for above */
304
305 int af; /* address family */
306
307 int
308 main(argc, argv)
309 int argc;
310 char *argv[];
311 {
312 register struct protox *tp = NULL; /* for printing cblocks & stats */
313 int ch;
314
315 af = AF_UNSPEC;
316
317 while ((ch = getopt(argc, argv, "Aabc:df:gI:iLlmnP:p:qQrRstuvWw:x")) != -1)
318 switch(ch) {
319 case 'A':
320 Aflag = 1;
321 break;
322 case 'a':
323 aflag = 1;
324 break;
325 case 'b':
326 bflag = 1;
327 break;
328 case 'c':
329 cflag = 1;
330 cq = atoi(optarg);
331 break;
332 case 'd':
333 dflag = 1;
334 break;
335 case 'f':
336 if (strcmp(optarg, "ipx") == 0)
337 af = AF_IPX;
338 else if (strcmp(optarg, "inet") == 0)
339 af = AF_INET;
340 #ifdef INET6
341 else if (strcmp(optarg, "inet6") == 0)
342 af = AF_INET6;
343 #endif /*INET6*/
344 #ifdef INET6
345 else if (strcmp(optarg, "pfkey") == 0)
346 af = PF_KEY;
347 #endif /*INET6*/
348 else if (strcmp(optarg, "unix") == 0)
349 af = AF_UNIX;
350 else {
351 errx(1, "%s: unknown address family", optarg);
352 }
353 break;
354 #if defined(__APPLE__)
355 case 'g':
356 gflag = 1;
357 break;
358 #endif
359 case 'I': {
360 char *cp;
361
362 iflag = 1;
363 for (cp = interface = optarg; isalpha(*cp); cp++)
364 continue;
365 unit = atoi(cp);
366 break;
367 }
368 case 'i':
369 iflag = 1;
370 break;
371 case 'l':
372 lflag = 1;
373 break;
374 case 'L':
375 Lflag = 1;
376 break;
377 case 'm':
378 mflag++;
379 break;
380 case 'n':
381 nflag = 1;
382 break;
383 case 'P':
384 prioflag = atoi(optarg);
385 break;
386 case 'p':
387 if ((tp = name2protox(optarg)) == NULL) {
388 errx(1,
389 "%s: unknown or uninstrumented protocol",
390 optarg);
391 }
392 pflag = 1;
393 break;
394 case 'q':
395 qflag++;
396 break;
397 case 'Q':
398 Qflag++;
399 break;
400 case 'R':
401 Rflag = 1;
402 break;
403 case 'r':
404 rflag = 1;
405 break;
406 case 's':
407 ++sflag;
408 break;
409 case 't':
410 tflag = 1;
411 break;
412 case 'u':
413 af = AF_UNIX;
414 break;
415 case 'v':
416 vflag++;
417 break;
418 case 'W':
419 Wflag = 1;
420 break;
421 case 'w':
422 interval = atoi(optarg);
423 iflag = 1;
424 break;
425 case 'x':
426 xflag = 1;
427 Rflag = 1;
428 break;
429 case '?':
430 default:
431 usage();
432 }
433 argv += optind;
434 argc -= optind;
435
436 #define BACKWARD_COMPATIBILITY
437 #ifdef BACKWARD_COMPATIBILITY
438 if (*argv) {
439 if (isdigit(**argv)) {
440 interval = atoi(*argv);
441 if (interval <= 0)
442 usage();
443 ++argv;
444 iflag = 1;
445 }
446 }
447 #endif
448
449 if (mflag) {
450 mbpr();
451 exit(0);
452 }
453 if (iflag && !sflag && !gflag && !qflag && !Qflag) {
454 if (Rflag)
455 intpr_ri(NULL);
456 else
457 intpr(NULL);
458 exit(0);
459 }
460 if (rflag) {
461 if (sflag)
462 rt_stats();
463 else
464 routepr(nl[N_RTREE].n_value);
465 exit(0);
466 }
467 if (qflag || Qflag) {
468 if (interface == NULL) {
469 fprintf(stderr, "%s statistics option "
470 "requires interface name\n", qflag ? "Queue" :
471 "Polling");
472 } else if (qflag) {
473 aqstatpr();
474 } else {
475 rxpollstatpr();
476 }
477 exit(0);
478 }
479
480 #if defined(__APPLE__)
481 if (gflag) {
482 #if !TARGET_OS_EMBEDDED
483 if (sflag) {
484 if (af == AF_INET || af == AF_UNSPEC)
485 mrt_stats();
486 #ifdef INET6
487 if (af == AF_INET6 || af == AF_UNSPEC)
488 mrt6_stats();
489 #endif
490 } else {
491 if (af == AF_INET || af == AF_UNSPEC)
492 mroutepr();
493 #ifdef INET6
494 if (af == AF_INET6 || af == AF_UNSPEC)
495 mroute6pr();
496 #endif
497 }
498 #endif /* !TARGET_OS_EMBEDDED */
499 ifmalist_dump();
500 exit(0);
501 }
502 #endif
503
504 if (tp) {
505 printproto(tp, tp->pr_name);
506 exit(0);
507 }
508 if (af == AF_INET || af == AF_UNSPEC)
509 for (tp = protox; tp->pr_name; tp++)
510 printproto(tp, tp->pr_name);
511 #ifdef INET6
512 if (af == AF_INET6 || af == AF_UNSPEC)
513 for (tp = ip6protox; tp->pr_name; tp++)
514 printproto(tp, tp->pr_name);
515 #endif /*INET6*/
516 #ifdef IPSEC
517 if (af == PF_KEY || af == AF_UNSPEC)
518 for (tp = pfkeyprotox; tp->pr_name; tp++)
519 printproto(tp, tp->pr_name);
520 #endif /*IPSEC*/
521 if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
522 unixpr();
523 #ifdef SRVCACHE
524 _serv_cache_close();
525 #endif
526 exit(0);
527 }
528
529 /*
530 * Print out protocol statistics or control blocks (per sflag).
531 * If the interface was not specifically requested, and the symbol
532 * is not in the namelist, ignore this one.
533 */
534 static void
535 printproto(tp, name)
536 register struct protox *tp;
537 char *name;
538 {
539 void (*pr)(uint32_t, char *, int);
540 uint32_t off;
541
542 if (sflag) {
543 if (iflag && !pflag) {
544 if (tp->pr_istats)
545 intpr(tp->pr_istats);
546 else
547 printf("%s: no per-interface stats routine\n",
548 tp->pr_name);
549 return;
550 }
551 else {
552 pr = tp->pr_stats;
553 if (!pr) {
554 if (pflag)
555 printf("%s: no stats routine\n",
556 tp->pr_name);
557 return;
558 }
559 off = tp->pr_usesysctl ? tp->pr_usesysctl
560 : nl[tp->pr_sindex].n_value;
561 }
562 } else {
563 pr = tp->pr_cblocks;
564 if (!pr) {
565 if (pflag)
566 printf("%s: no PCB routine\n", tp->pr_name);
567 return;
568 }
569 off = tp->pr_usesysctl ? tp->pr_usesysctl
570 : nl[tp->pr_index].n_value;
571 }
572 if (pr != NULL && (off || af != AF_UNSPEC)) {
573 if (sflag && iflag && pflag)
574 intervalpr(pr, off, name, af);
575 else
576 (*pr)(off, name, af);
577 } else {
578 printf("### no stats for %s\n", name);
579 }
580 }
581
582 char *
583 plural(int n)
584 {
585 return (n != 1 ? "s" : "");
586 }
587
588 char *
589 plurales(int n)
590 {
591 return (n != 1 ? "es" : "");
592 }
593
594 /*
595 * Find the protox for the given "well-known" name.
596 */
597 static struct protox *
598 knownname(char *name)
599 {
600 struct protox **tpp, *tp;
601
602 for (tpp = protoprotox; *tpp; tpp++)
603 for (tp = *tpp; tp->pr_name; tp++)
604 if (strcmp(tp->pr_name, name) == 0)
605 return (tp);
606 return (NULL);
607 }
608
609 /*
610 * Find the protox corresponding to name.
611 */
612 static struct protox *
613 name2protox(char *name)
614 {
615 struct protox *tp;
616 char **alias; /* alias from p->aliases */
617 struct protoent *p;
618
619 /*
620 * Try to find the name in the list of "well-known" names. If that
621 * fails, check if name is an alias for an Internet protocol.
622 */
623 if ((tp = knownname(name)) != NULL)
624 return (tp);
625
626 setprotoent(1); /* make protocol lookup cheaper */
627 while ((p = getprotoent()) != NULL) {
628 /* assert: name not same as p->name */
629 for (alias = p->p_aliases; *alias; alias++)
630 if (strcmp(name, *alias) == 0) {
631 endprotoent();
632 return (knownname(p->p_name));
633 }
634 }
635 endprotoent();
636 return (NULL);
637 }
638
639 #define NETSTAT_USAGE "\
640 Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
641 netstat [-gilns] [-f address_family]\n\
642 netstat -i | -I interface [-w wait] [-abdgRt]\n\
643 netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
644 netstat -i | -I interface -s [-f address_family | -p protocol]\n\
645 netstat -m [-m]\n\
646 netstat -r [-Aaln] [-f address_family]\n\
647 netstat -rs [-s]\n\
648 "
649
650 static void
651 usage(void)
652 {
653 (void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
654 exit(1);
655 }