]>
git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/main.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1983, 1988, 1993
25 * Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 char const copyright
[] =
58 "@(#) Copyright (c) 1983, 1988, 1993\n\
59 Regents of the University of California. All rights reserved.\n";
64 static char sccsid
[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
66 static const char rcsid
[] =
67 "$Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $";
70 #include <sys/param.h>
72 #include <sys/socket.h>
74 #include <netinet/in.h>
75 #include <net/pfkeyv2.h>
90 #include <sys/types.h>
91 #include <sys/sysctl.h>
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 * ----------------------------------------------------------------------------
102 * $Id: main.c,v 1.8 2004/10/14 22:24:09 lindak Exp $
106 static struct nlist nl
[] = {
131 #define N_ESISSTAT 12
139 #define N_CLTPSTAT 16
159 #define N_ICMP6STAT 29
161 #define N_IPSECSTAT 30
163 #define N_IPSEC6STAT 31
165 #define N_PIM6STAT 32
167 #define N_MRT6PROTO 33
169 #define N_MRT6STAT 34
171 #define N_MF6CTABLE 35
173 #define N_MIF6TABLE 36
175 #define N_PFKEYSTAT 37
181 #define N_NMBCLUSTERS 40
192 u_char pr_index
; /* index into nlist of cb head */
193 u_char pr_sindex
; /* index into nlist of stat block */
194 u_char pr_wanted
; /* 1 if wanted, 0 otherwise */
195 void (*pr_cblocks
)(u_long
, char *, int);
196 /* control blocks printing routine */
197 void (*pr_stats
)(u_long
, char *, int);
198 /* statistics printing routine */
199 void (*pr_istats
)(char *); /* per/if statistics printing routine */
200 char *pr_name
; /* well-known name */
201 int pr_usesysctl
; /* true if we use sysctl, not kvm */
203 { -1, -1, 1, protopr
,
204 tcp_stats
, NULL
, "tcp", IPPROTO_TCP
},
205 { -1, -1, 1, protopr
,
206 udp_stats
, NULL
, "udp", IPPROTO_UDP
},
207 { -1, -1, 1, protopr
,
208 NULL
, NULL
, "divert",IPPROTO_DIVERT
},
209 { -1, -1, 1, protopr
,
210 ip_stats
, NULL
, "ip", IPPROTO_RAW
},
211 { -1, -1, 1, protopr
,
212 icmp_stats
, NULL
, "icmp", IPPROTO_ICMP
},
213 { -1, -1, 1, protopr
,
214 igmp_stats
, NULL
, "igmp", IPPROTO_IGMP
},
217 ipsec_stats
, NULL
, "ipsec", IPPROTO_ESP
},
221 bdg_stats
, NULL
, "bdg", 1 /* bridging... */ },
228 struct protox ip6protox
[] = {
229 { -1, -1, 1, protopr
,
230 tcp_stats
, NULL
, "tcp", IPPROTO_TCP
},
231 { -1, -1, 1, protopr
,
232 udp_stats
, NULL
, "udp", IPPROTO_UDP
},
233 { -1, N_IP6STAT
, 1, protopr
,
234 ip6_stats
, ip6_ifstats
, "ip6", IPPROTO_RAW
},
235 { -1, N_ICMP6STAT
, 1, protopr
,
236 icmp6_stats
, icmp6_ifstats
, "icmp6",IPPROTO_ICMPV6
},
238 { -1, N_IPSEC6STAT
, 1, 0,
239 ipsec_stats
, NULL
, "ipsec6",IPPROTO_ESP
},
242 { -1, N_PIM6STAT
, 1, 0,
243 pim6_stats
, NULL
, "pim6", 0 },
246 rip6_stats
, NULL
, "rip6", IPPROTO_RAW
},
249 bdg_stats
, NULL
, "bdg", 1 /* bridging... */ },
257 struct protox pfkeyprotox
[] = {
258 { -1, N_PFKEYSTAT
, 1, 0,
259 pfkey_stats
, NULL
, "pfkey", PF_KEY_V2
},
265 struct protox atalkprotox
[] = {
266 { N_DDPCB
, N_DDPSTAT
, 1, atalkprotopr
,
267 ddp_stats
, NULL
, "ddp" },
272 struct protox netgraphprotox
[] = {
273 { N_NGSOCKS
, -1, 1, netgraphprotopr
,
274 NULL
, NULL
, "ctrl" },
275 { N_NGSOCKS
, -1, 1, netgraphprotopr
,
276 NULL
, NULL
, "data" },
281 struct protox ipxprotox
[] = {
282 { N_IPX
, N_IPXSTAT
, 1, ipxprotopr
,
283 ipx_stats
, NULL
, "ipx", 0 },
284 { N_IPX
, N_SPXSTAT
, 1, ipxprotopr
,
285 spx_stats
, NULL
, "spx", 0 },
291 struct protox nsprotox
[] = {
292 { N_IDP
, N_IDPSTAT
, 1, nsprotopr
,
293 idp_stats
, NULL
, "idp" },
294 { N_IDP
, N_SPPSTAT
, 1, nsprotopr
,
295 spp_stats
, NULL
, "spp" },
297 nserr_stats
, NULL
, "ns_err" },
304 struct protox isoprotox
[] = {
305 { ISO_TP
, N_TPSTAT
, 1, iso_protopr
,
306 tp_stats
, NULL
, "tp" },
307 { N_CLTP
, N_CLTPSTAT
, 1, iso_protopr
,
308 cltp_stats
, NULL
, "cltp" },
309 { -1, N_CLNPSTAT
, 1, 0,
310 clnp_stats
, NULL
, "clnp"},
311 { -1, N_ESISSTAT
, 1, 0,
312 esis_stats
, NULL
, "esis"},
318 struct protox
*protoprotox
[] = {
327 ipxprotox
, atalkprotox
,
337 static void printproto (struct protox
*, char *);
338 static void usage (void);
339 static struct protox
*name2protox (char *);
340 static struct protox
*knownname (char *);
342 extern void _serv_cache_close();
348 static char *nlistf
= NULL
, *memf
= NULL
;
350 int Aflag
; /* show addresses of protocol control block */
351 int aflag
; /* show all sockets (including servers) */
352 int bflag
; /* show i/f total bytes in/out */
353 int dflag
; /* show i/f dropped packets */
354 int gflag
; /* show group (multicast) routing or stats */
355 int iflag
; /* show interfaces */
356 int lflag
; /* show routing table with use and ref */
357 int Lflag
; /* show size of listen queues */
358 int mflag
; /* show memory stats */
359 int nflag
; /* show addresses numerically */
360 static int pflag
; /* show given protocol */
361 int rflag
; /* show routing tables (or routing stats) */
362 int sflag
; /* show protocol statistics */
363 int tflag
; /* show i/f watchdog timers */
364 int Wflag
; /* wide display */
366 int interval
; /* repeat interval for i/f stats */
368 char *interface
; /* desired i/f for stats, or NULL for all i/fs */
369 int unit
; /* unit number for above */
371 int af
; /* address family */
378 register struct protox
*tp
= NULL
; /* for printing cblocks & stats */
383 while ((ch
= getopt(argc
, argv
, "Aabdf:gI:iLlM:mN:np:rRstuWw:")) != -1)
399 if (strcmp(optarg
, "ns") == 0)
403 if (strcmp(optarg
, "ipx") == 0)
405 else if (strcmp(optarg
, "inet") == 0)
408 else if (strcmp(optarg
, "inet6") == 0)
412 else if (strcmp(optarg
, "pfkey") == 0)
415 else if (strcmp(optarg
, "unix") == 0)
418 else if (strcmp(optarg
, "atalk") == 0)
420 else if (strcmp(optarg
, "ng") == 0
421 || strcmp(optarg
, "netgraph") == 0)
425 else if (strcmp(optarg
, "iso") == 0)
429 errx(1, "%s: unknown address family", optarg
);
439 for (cp
= interface
= optarg
; isalpha(*cp
); cp
++)
466 if ((tp
= name2protox(optarg
)) == NULL
) {
468 "%s: unknown or uninstrumented protocol",
489 interval
= atoi(optarg
);
499 #define BACKWARD_COMPATIBILITY
500 #ifdef BACKWARD_COMPATIBILITY
502 if (isdigit(**argv
)) {
503 interval
= atoi(*argv
);
518 * Discard setgid privileges if not the running kernel so that bad
519 * guys can't print interesting stuff from kernel memory.
521 if (nlistf
!= NULL
|| memf
!= NULL
)
530 * Keep file descriptors open to avoid overhead
531 * of open/close on each call to get* routines.
537 * This does not make sense any more with DNS being default over
538 * the files. Doing a setXXXXent(1) causes a tcp connection to be
539 * used for the queries, which is slower.
542 if (iflag
&& !sflag
) {
550 routepr(nl
[N_RTREE
].n_value
);
555 if (af
== AF_INET
|| af
== AF_UNSPEC
)
558 if (af
== AF_INET6
|| af
== AF_UNSPEC
)
562 if (af
== AF_INET
|| af
== AF_UNSPEC
)
565 if (af
== AF_INET6
|| af
== AF_UNSPEC
)
573 printproto(tp
, tp
->pr_name
);
576 if (af
== AF_INET
|| af
== AF_UNSPEC
)
577 for (tp
= protox
; tp
->pr_name
; tp
++)
578 printproto(tp
, tp
->pr_name
);
580 if (af
== AF_INET6
|| af
== AF_UNSPEC
)
581 for (tp
= ip6protox
; tp
->pr_name
; tp
++)
582 printproto(tp
, tp
->pr_name
);
585 if (af
== PF_KEY
|| af
== AF_UNSPEC
)
586 for (tp
= pfkeyprotox
; tp
->pr_name
; tp
++)
587 printproto(tp
, tp
->pr_name
);
590 if (af
== AF_IPX
|| af
== AF_UNSPEC
) {
591 for (tp
= ipxprotox
; tp
->pr_name
; tp
++)
592 printproto(tp
, tp
->pr_name
);
594 if (af
== AF_APPLETALK
|| af
== AF_UNSPEC
)
595 for (tp
= atalkprotox
; tp
->pr_name
; tp
++)
596 printproto(tp
, tp
->pr_name
);
597 if (af
== AF_NETGRAPH
|| af
== AF_UNSPEC
)
598 for (tp
= netgraphprotox
; tp
->pr_name
; tp
++)
599 printproto(tp
, tp
->pr_name
);
602 if (af
== AF_NS
|| af
== AF_UNSPEC
)
603 for (tp
= nsprotox
; tp
->pr_name
; tp
++)
604 printproto(tp
, tp
->pr_name
);
607 if (af
== AF_ISO
|| af
== AF_UNSPEC
)
608 for (tp
= isoprotox
; tp
->pr_name
; tp
++)
609 printproto(tp
, tp
->pr_name
);
611 if ((af
== AF_UNIX
|| af
== AF_UNSPEC
) && !Lflag
&& !sflag
)
620 * Print out protocol statistics or control blocks (per sflag).
621 * If the interface was not specifically requested, and the symbol
622 * is not in the namelist, ignore this one.
626 register struct protox
*tp
;
629 void (*pr
)(u_long
, char *, int);
635 intpr(tp
->pr_istats
);
637 printf("%s: no per-interface stats routine\n",
645 printf("%s: no stats routine\n",
649 off
= tp
->pr_usesysctl
? tp
->pr_usesysctl
650 : nl
[tp
->pr_sindex
].n_value
;
656 printf("%s: no PCB routine\n", tp
->pr_name
);
659 off
= tp
->pr_usesysctl
? tp
->pr_usesysctl
660 : nl
[tp
->pr_index
].n_value
;
662 if (pr
!= NULL
&& (off
|| af
!= AF_UNSPEC
))
663 (*pr
)(off
, name
, af
);
665 printf("### no stats for %s\n", name
);
669 * Read kernel memory, return 0 on success.
673 kread(u_long addr
, char *buf
, int size
)
679 kvmd
= kvm_openfiles(nlistf
, memf
, NULL
, O_RDONLY
, buf
);
681 if (kvm_nlist(kvmd
, nl
) < 0) {
683 errx(1, "%s: kvm_nlist: %s", nlistf
,
686 errx(1, "kvm_nlist: %s", kvm_geterr(kvmd
));
689 if (nl
[0].n_type
== 0) {
691 errx(1, "%s: no namelist", nlistf
);
693 errx(1, "no namelist");
696 warnx("kvm not available");
702 if (kvm_read(kvmd
, addr
, buf
, size
) != size
) {
703 warnx("%s", kvm_geterr(kvmd
));
713 return (n
!= 1 ? "s" : "");
719 return (n
!= 1 ? "es" : "");
723 * Find the protox for the given "well-known" name.
725 static struct protox
*
726 knownname(char *name
)
728 struct protox
**tpp
, *tp
;
730 for (tpp
= protoprotox
; *tpp
; tpp
++)
731 for (tp
= *tpp
; tp
->pr_name
; tp
++)
732 if (strcmp(tp
->pr_name
, name
) == 0)
738 * Find the protox corresponding to name.
740 static struct protox
*
741 name2protox(char *name
)
744 char **alias
; /* alias from p->aliases */
748 * Try to find the name in the list of "well-known" names. If that
749 * fails, check if name is an alias for an Internet protocol.
751 if ((tp
= knownname(name
)) != NULL
)
754 setprotoent(1); /* make protocol lookup cheaper */
755 while ((p
= getprotoent()) != NULL
) {
756 /* assert: name not same as p->name */
757 for (alias
= p
->p_aliases
; *alias
; alias
++)
758 if (strcmp(name
, *alias
) == 0) {
760 return (knownname(p
->p_name
));
770 (void)fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n",
771 "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
772 " netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
773 " netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
774 " netstat -m [-M core] [-N system]",
775 " netstat [-M core] [-N system] [-p protocol]");