xref: /f-stack/tools/netstat/main.c (revision d4a07e70)
11eaf0ac3Slogwang /*-
222ce4affSfengbojiang  * SPDX-License-Identifier: BSD-3-Clause
322ce4affSfengbojiang  *
41eaf0ac3Slogwang  * Copyright (c) 1983, 1988, 1993
51eaf0ac3Slogwang  *	Regents of the University of California.  All rights reserved.
61eaf0ac3Slogwang  *
71eaf0ac3Slogwang  * Redistribution and use in source and binary forms, with or without
81eaf0ac3Slogwang  * modification, are permitted provided that the following conditions
91eaf0ac3Slogwang  * are met:
101eaf0ac3Slogwang  * 1. Redistributions of source code must retain the above copyright
111eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer.
121eaf0ac3Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
131eaf0ac3Slogwang  *    notice, this list of conditions and the following disclaimer in the
141eaf0ac3Slogwang  *    documentation and/or other materials provided with the distribution.
1522ce4affSfengbojiang  * 3. Neither the name of the University nor the names of its contributors
161eaf0ac3Slogwang  *    may be used to endorse or promote products derived from this software
171eaf0ac3Slogwang  *    without specific prior written permission.
181eaf0ac3Slogwang  *
191eaf0ac3Slogwang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
201eaf0ac3Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211eaf0ac3Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221eaf0ac3Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
231eaf0ac3Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241eaf0ac3Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251eaf0ac3Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261eaf0ac3Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271eaf0ac3Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281eaf0ac3Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291eaf0ac3Slogwang  * SUCH DAMAGE.
301eaf0ac3Slogwang  */
311eaf0ac3Slogwang 
321eaf0ac3Slogwang #ifndef lint
331eaf0ac3Slogwang static char const copyright[] =
341eaf0ac3Slogwang "@(#) Copyright (c) 1983, 1988, 1993\n\
351eaf0ac3Slogwang 	Regents of the University of California.  All rights reserved.\n";
361eaf0ac3Slogwang #endif /* not lint */
371eaf0ac3Slogwang 
381eaf0ac3Slogwang #if 0
391eaf0ac3Slogwang #ifndef lint
401eaf0ac3Slogwang static char sccsid[] = "@(#)main.c	8.4 (Berkeley) 3/1/94";
411eaf0ac3Slogwang #endif /* not lint */
421eaf0ac3Slogwang #endif
431eaf0ac3Slogwang 
441eaf0ac3Slogwang #include <sys/cdefs.h>
451eaf0ac3Slogwang __FBSDID("$FreeBSD$");
461eaf0ac3Slogwang 
471eaf0ac3Slogwang #include <sys/param.h>
481eaf0ac3Slogwang #include <sys/file.h>
491eaf0ac3Slogwang #include <sys/protosw.h>
501eaf0ac3Slogwang #include <sys/socket.h>
511eaf0ac3Slogwang #include <sys/socketvar.h>
521eaf0ac3Slogwang #include <sys/sysctl.h>
531eaf0ac3Slogwang 
541eaf0ac3Slogwang #include <netinet/in.h>
551eaf0ac3Slogwang 
561eaf0ac3Slogwang #ifdef NETGRAPH
571eaf0ac3Slogwang #include <netgraph/ng_socket.h>
581eaf0ac3Slogwang #endif
591eaf0ac3Slogwang 
601eaf0ac3Slogwang #include <ctype.h>
611eaf0ac3Slogwang #include <err.h>
621eaf0ac3Slogwang #include <errno.h>
63*d4a07e70Sfengbojiang #ifndef FSTACK
641eaf0ac3Slogwang #include <kvm.h>
65*d4a07e70Sfengbojiang #endif
661eaf0ac3Slogwang #include <limits.h>
671eaf0ac3Slogwang #include <netdb.h>
681eaf0ac3Slogwang #include <nlist.h>
691eaf0ac3Slogwang #include <paths.h>
701eaf0ac3Slogwang #include <stdint.h>
711eaf0ac3Slogwang #include <stdio.h>
721eaf0ac3Slogwang #include <stdlib.h>
731eaf0ac3Slogwang #include <stdbool.h>
741eaf0ac3Slogwang #include <string.h>
751eaf0ac3Slogwang #include <unistd.h>
761eaf0ac3Slogwang #include "netstat.h"
771eaf0ac3Slogwang #include "nl_defs.h"
781eaf0ac3Slogwang #include <libxo/xo.h>
791eaf0ac3Slogwang 
80*d4a07e70Sfengbojiang #ifdef FSTACK
81*d4a07e70Sfengbojiang #include "ff_ipc.h"
82*d4a07e70Sfengbojiang #endif
83*d4a07e70Sfengbojiang 
841eaf0ac3Slogwang static struct protox {
851eaf0ac3Slogwang 	int	pr_index;		/* index into nlist of cb head */
861eaf0ac3Slogwang 	int	pr_sindex;		/* index into nlist of stat block */
871eaf0ac3Slogwang 	u_char	pr_wanted;		/* 1 if wanted, 0 otherwise */
881eaf0ac3Slogwang 	void	(*pr_cblocks)(u_long, const char *, int, int);
891eaf0ac3Slogwang 					/* control blocks printing routine */
901eaf0ac3Slogwang 	void	(*pr_stats)(u_long, const char *, int, int);
911eaf0ac3Slogwang 					/* statistics printing routine */
921eaf0ac3Slogwang 	void	(*pr_istats)(char *);	/* per/if statistics printing routine */
931eaf0ac3Slogwang 	const char	*pr_name;		/* well-known name */
941eaf0ac3Slogwang 	int	pr_usesysctl;		/* non-zero if we use sysctl, not kvm */
951eaf0ac3Slogwang 	int	pr_protocol;
961eaf0ac3Slogwang } protox[] = {
971eaf0ac3Slogwang 	{ N_TCBINFO,	N_TCPSTAT,	1,	protopr,
981eaf0ac3Slogwang 	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
991eaf0ac3Slogwang 	{ N_UDBINFO,	N_UDPSTAT,	1,	protopr,
1001eaf0ac3Slogwang 	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
1011eaf0ac3Slogwang #ifdef SCTP
1021eaf0ac3Slogwang 	{ -1,		N_SCTPSTAT,	1,	sctp_protopr,
1031eaf0ac3Slogwang 	  sctp_stats,	NULL,		"sctp",	1,	IPPROTO_SCTP },
1041eaf0ac3Slogwang #endif
1051eaf0ac3Slogwang #ifdef SDP
1061eaf0ac3Slogwang 	{ -1,		-1,		1,	protopr,
1071eaf0ac3Slogwang 	 NULL,		NULL,		"sdp",	1,	IPPROTO_TCP },
1081eaf0ac3Slogwang #endif
1091eaf0ac3Slogwang 	{ N_DIVCBINFO,	-1,		1,	protopr,
1101eaf0ac3Slogwang 	  NULL,		NULL,		"divert", 1,	IPPROTO_DIVERT },
1111eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_IPSTAT,	1,	protopr,
1121eaf0ac3Slogwang 	  ip_stats,	NULL,		"ip",	1,	IPPROTO_RAW },
1131eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_ICMPSTAT,	1,	protopr,
1141eaf0ac3Slogwang 	  icmp_stats,	NULL,		"icmp",	1,	IPPROTO_ICMP },
1151eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_IGMPSTAT,	1,	protopr,
1161eaf0ac3Slogwang 	  igmp_stats,	NULL,		"igmp",	1,	IPPROTO_IGMP },
1171eaf0ac3Slogwang #ifdef IPSEC
1181eaf0ac3Slogwang 	{ -1,		N_IPSEC4STAT,	1,	NULL,	/* keep as compat */
1191eaf0ac3Slogwang 	  ipsec_stats,	NULL,		"ipsec", 1,	0},
1201eaf0ac3Slogwang 	{ -1,		N_AHSTAT,	1,	NULL,
1211eaf0ac3Slogwang 	  ah_stats,	NULL,		"ah",	1,	0},
1221eaf0ac3Slogwang 	{ -1,		N_ESPSTAT,	1,	NULL,
1231eaf0ac3Slogwang 	  esp_stats,	NULL,		"esp",	1,	0},
1241eaf0ac3Slogwang 	{ -1,		N_IPCOMPSTAT,	1,	NULL,
1251eaf0ac3Slogwang 	  ipcomp_stats,	NULL,		"ipcomp", 1,	0},
1261eaf0ac3Slogwang #endif
1271eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_PIMSTAT,	1,	protopr,
1281eaf0ac3Slogwang 	  pim_stats,	NULL,		"pim",	1,	IPPROTO_PIM },
1291eaf0ac3Slogwang 	{ -1,		N_CARPSTATS,	1,	NULL,
1301eaf0ac3Slogwang 	  carp_stats,	NULL,		"carp",	1,	0 },
1311eaf0ac3Slogwang #ifdef PF
1321eaf0ac3Slogwang 	{ -1,		N_PFSYNCSTATS,	1,	NULL,
1331eaf0ac3Slogwang 	  pfsync_stats,	NULL,		"pfsync", 1,	0 },
1341eaf0ac3Slogwang #endif
1351eaf0ac3Slogwang 	{ -1,		N_ARPSTAT,	1,	NULL,
1361eaf0ac3Slogwang 	  arp_stats,	NULL,		"arp", 1,	0 },
1371eaf0ac3Slogwang 	{ -1,		-1,		0,	NULL,
1381eaf0ac3Slogwang 	  NULL,		NULL,		NULL,	0,	0 }
1391eaf0ac3Slogwang };
1401eaf0ac3Slogwang 
1411eaf0ac3Slogwang #ifdef INET6
1421eaf0ac3Slogwang static struct protox ip6protox[] = {
1431eaf0ac3Slogwang 	{ N_TCBINFO,	N_TCPSTAT,	1,	protopr,
1441eaf0ac3Slogwang 	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
1451eaf0ac3Slogwang 	{ N_UDBINFO,	N_UDPSTAT,	1,	protopr,
1461eaf0ac3Slogwang 	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
1471eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_IP6STAT,	1,	protopr,
1481eaf0ac3Slogwang 	  ip6_stats,	ip6_ifstats,	"ip6",	1,	IPPROTO_RAW },
1491eaf0ac3Slogwang 	{ N_RIPCBINFO,	N_ICMP6STAT,	1,	protopr,
1501eaf0ac3Slogwang 	  icmp6_stats,	icmp6_ifstats,	"icmp6", 1,	IPPROTO_ICMPV6 },
1511eaf0ac3Slogwang #ifdef SDP
1521eaf0ac3Slogwang 	{ -1,		-1,		1,	protopr,
1531eaf0ac3Slogwang 	 NULL,		NULL,		"sdp",	1,	IPPROTO_TCP },
1541eaf0ac3Slogwang #endif
1551eaf0ac3Slogwang #ifdef IPSEC
1561eaf0ac3Slogwang 	{ -1,		N_IPSEC6STAT,	1,	NULL,
1571eaf0ac3Slogwang 	  ipsec_stats,	NULL,		"ipsec6", 1,	0 },
1581eaf0ac3Slogwang #endif
1591eaf0ac3Slogwang #ifdef notyet
1601eaf0ac3Slogwang 	{ -1,		N_PIM6STAT,	1,	NULL,
1611eaf0ac3Slogwang 	  pim6_stats,	NULL,		"pim6",	1,	0 },
1621eaf0ac3Slogwang #endif
1631eaf0ac3Slogwang 	{ -1,		N_RIP6STAT,	1,	NULL,
1641eaf0ac3Slogwang 	  rip6_stats,	NULL,		"rip6",	1,	0 },
1651eaf0ac3Slogwang 	{ -1,		-1,		0,	NULL,
1661eaf0ac3Slogwang 	  NULL,		NULL,		NULL,	0,	0 }
1671eaf0ac3Slogwang };
1681eaf0ac3Slogwang #endif /*INET6*/
1691eaf0ac3Slogwang 
1701eaf0ac3Slogwang #ifdef IPSEC
1711eaf0ac3Slogwang static struct protox pfkeyprotox[] = {
1721eaf0ac3Slogwang 	{ -1,		N_PFKEYSTAT,	1,	NULL,
1731eaf0ac3Slogwang 	  pfkey_stats,	NULL,		"pfkey", 0,	0 },
1741eaf0ac3Slogwang 	{ -1,		-1,		0,	NULL,
1751eaf0ac3Slogwang 	  NULL,		NULL,		NULL,	0,	0 }
1761eaf0ac3Slogwang };
1771eaf0ac3Slogwang #endif
1781eaf0ac3Slogwang 
1791eaf0ac3Slogwang #ifdef NETGRAPH
1801eaf0ac3Slogwang static struct protox netgraphprotox[] = {
1811eaf0ac3Slogwang 	{ N_NGSOCKLIST,	-1,		1,	netgraphprotopr,
1821eaf0ac3Slogwang 	  NULL,		NULL,		"ctrl",	0,	0 },
1831eaf0ac3Slogwang 	{ N_NGSOCKLIST,	-1,		1,	netgraphprotopr,
1841eaf0ac3Slogwang 	  NULL,		NULL,		"data",	0,	0 },
1851eaf0ac3Slogwang 	{ -1,		-1,		0,	NULL,
1861eaf0ac3Slogwang 	  NULL,		NULL,		NULL,	0,	0 }
1871eaf0ac3Slogwang };
1881eaf0ac3Slogwang #endif
1891eaf0ac3Slogwang 
1901eaf0ac3Slogwang static struct protox *protoprotox[] = {
1911eaf0ac3Slogwang 					 protox,
1921eaf0ac3Slogwang #ifdef INET6
1931eaf0ac3Slogwang 					 ip6protox,
1941eaf0ac3Slogwang #endif
1951eaf0ac3Slogwang #ifdef IPSEC
1961eaf0ac3Slogwang 					 pfkeyprotox,
1971eaf0ac3Slogwang #endif
1981eaf0ac3Slogwang 					 NULL };
1991eaf0ac3Slogwang 
2001eaf0ac3Slogwang static void printproto(struct protox *, const char *, bool *);
2011eaf0ac3Slogwang static void usage(void);
2021eaf0ac3Slogwang static struct protox *name2protox(const char *);
2031eaf0ac3Slogwang static struct protox *knownname(const char *);
2041eaf0ac3Slogwang 
205*d4a07e70Sfengbojiang #ifndef FSTACK
2061eaf0ac3Slogwang static int kresolve_list(struct nlist *_nl);
2071eaf0ac3Slogwang 
2081eaf0ac3Slogwang static kvm_t *kvmd;
209*d4a07e70Sfengbojiang #endif
2101eaf0ac3Slogwang static char *nlistf = NULL, *memf = NULL;
2111eaf0ac3Slogwang 
2121eaf0ac3Slogwang int	Aflag;		/* show addresses of protocol control block */
2131eaf0ac3Slogwang int	aflag;		/* show all sockets (including servers) */
2141eaf0ac3Slogwang static int	Bflag;		/* show information about bpf consumers */
2151eaf0ac3Slogwang int	bflag;		/* show i/f total bytes in/out */
21622ce4affSfengbojiang int	cflag;		/* show TCP congestion control stack */
21722ce4affSfengbojiang int	Cflag;		/* show congestion control algo and vars */
2181eaf0ac3Slogwang int	dflag;		/* show i/f dropped packets */
2191eaf0ac3Slogwang int	gflag;		/* show group (multicast) routing or stats */
2201eaf0ac3Slogwang int	hflag;		/* show counters in human readable format */
2211eaf0ac3Slogwang int	iflag;		/* show interfaces */
2221eaf0ac3Slogwang int	Lflag;		/* show size of listen queues */
2231eaf0ac3Slogwang int	mflag;		/* show memory stats */
2241eaf0ac3Slogwang int	noutputs = 0;	/* how much outputs before we exit */
2251eaf0ac3Slogwang int	numeric_addr;	/* show addresses numerically */
2261eaf0ac3Slogwang int	numeric_port;	/* show ports numerically */
22722ce4affSfengbojiang int	Oflag;		/* show nhgrp objects*/
22822ce4affSfengbojiang int	oflag;		/* show nexthop objects*/
22922ce4affSfengbojiang int	Pflag;		/* show TCP log ID */
2301eaf0ac3Slogwang static int pflag;	/* show given protocol */
2311eaf0ac3Slogwang static int	Qflag;		/* show netisr information */
2321eaf0ac3Slogwang int	rflag;		/* show routing tables (or routing stats) */
2331eaf0ac3Slogwang int	Rflag;		/* show flow / RSS statistics */
2341eaf0ac3Slogwang int	sflag;		/* show protocol statistics */
2351eaf0ac3Slogwang int	Wflag;		/* wide display */
2361eaf0ac3Slogwang int	Tflag;		/* TCP Information */
2371eaf0ac3Slogwang int	xflag;		/* extra information, includes all socket buffer info */
2381eaf0ac3Slogwang int	zflag;		/* zero stats */
2391eaf0ac3Slogwang 
2401eaf0ac3Slogwang int	interval;	/* repeat interval for i/f stats */
2411eaf0ac3Slogwang 
2421eaf0ac3Slogwang char	*interface;	/* desired i/f for stats, or NULL for all i/fs */
2431eaf0ac3Slogwang int	unit;		/* unit number for above */
2441eaf0ac3Slogwang 
2451eaf0ac3Slogwang static int	af;		/* address family */
2461eaf0ac3Slogwang int	live;		/* true if we are examining a live system */
2471eaf0ac3Slogwang 
2481eaf0ac3Slogwang int
main(int argc,char * argv[])2491eaf0ac3Slogwang main(int argc, char *argv[])
2501eaf0ac3Slogwang {
2511eaf0ac3Slogwang 	struct protox *tp = NULL;  /* for printing cblocks & stats */
2521eaf0ac3Slogwang 	int ch;
2531eaf0ac3Slogwang 	int fib = -1;
2541eaf0ac3Slogwang 	char *endptr;
2551eaf0ac3Slogwang 	bool first = true;
2561eaf0ac3Slogwang 
257*d4a07e70Sfengbojiang #ifdef FSTACK
258*d4a07e70Sfengbojiang 	ff_ipc_init();
259*d4a07e70Sfengbojiang #endif
260*d4a07e70Sfengbojiang 
2611eaf0ac3Slogwang 	af = AF_UNSPEC;
2621eaf0ac3Slogwang 
2631eaf0ac3Slogwang 	argc = xo_parse_args(argc, argv);
26422ce4affSfengbojiang 	if (argc < 0)
265*d4a07e70Sfengbojiang #ifndef FSTACK
2661eaf0ac3Slogwang 		exit(EXIT_FAILURE);
2671eaf0ac3Slogwang 
26822ce4affSfengbojiang 	while ((ch = getopt(argc, argv, "46AaBbCcdF:f:ghI:iLlM:mN:nOoPp:Qq:RrSTsuWw:xz"))
269*d4a07e70Sfengbojiang #else
270*d4a07e70Sfengbojiang 	{
271*d4a07e70Sfengbojiang 		ff_ipc_exit();
272*d4a07e70Sfengbojiang 		exit(EXIT_FAILURE);
273*d4a07e70Sfengbojiang 	}
274*d4a07e70Sfengbojiang 
275*d4a07e70Sfengbojiang 	while ((ch = getopt(argc, argv, "46AaBbCcdF:f:ghI:iLlnOoPp:Qq:RrSTsuWw:xzt:"))
276*d4a07e70Sfengbojiang #endif
2771eaf0ac3Slogwang 	    != -1)
2781eaf0ac3Slogwang 		switch(ch) {
2791eaf0ac3Slogwang 		case '4':
2801eaf0ac3Slogwang #ifdef INET
2811eaf0ac3Slogwang 			af = AF_INET;
2821eaf0ac3Slogwang #else
2831eaf0ac3Slogwang 			errx(1, "IPv4 support is not compiled in");
2841eaf0ac3Slogwang #endif
2851eaf0ac3Slogwang 			break;
2861eaf0ac3Slogwang 		case '6':
2871eaf0ac3Slogwang #ifdef INET6
2881eaf0ac3Slogwang 			af = AF_INET6;
2891eaf0ac3Slogwang #else
2901eaf0ac3Slogwang 			errx(1, "IPv6 support is not compiled in");
2911eaf0ac3Slogwang #endif
2921eaf0ac3Slogwang 			break;
2931eaf0ac3Slogwang 		case 'A':
2941eaf0ac3Slogwang 			Aflag = 1;
2951eaf0ac3Slogwang 			break;
2961eaf0ac3Slogwang 		case 'a':
2971eaf0ac3Slogwang 			aflag = 1;
2981eaf0ac3Slogwang 			break;
2991eaf0ac3Slogwang 		case 'B':
3001eaf0ac3Slogwang 			Bflag = 1;
3011eaf0ac3Slogwang 			break;
3021eaf0ac3Slogwang 		case 'b':
3031eaf0ac3Slogwang 			bflag = 1;
3041eaf0ac3Slogwang 			break;
30522ce4affSfengbojiang 		case 'c':
30622ce4affSfengbojiang 			cflag = 1;
30722ce4affSfengbojiang 			break;
30822ce4affSfengbojiang 		case 'C':
30922ce4affSfengbojiang 			Cflag = 1;
31022ce4affSfengbojiang 			break;
3111eaf0ac3Slogwang 		case 'd':
3121eaf0ac3Slogwang 			dflag = 1;
3131eaf0ac3Slogwang 			break;
3141eaf0ac3Slogwang 		case 'F':
3151eaf0ac3Slogwang 			fib = strtol(optarg, &endptr, 0);
3161eaf0ac3Slogwang 			if (*endptr != '\0' ||
3171eaf0ac3Slogwang 			    (fib == 0 && (errno == EINVAL || errno == ERANGE)))
3181eaf0ac3Slogwang 				xo_errx(1, "%s: invalid fib", optarg);
3191eaf0ac3Slogwang 			break;
3201eaf0ac3Slogwang 		case 'f':
3211eaf0ac3Slogwang 			if (strcmp(optarg, "inet") == 0)
3221eaf0ac3Slogwang 				af = AF_INET;
3231eaf0ac3Slogwang #ifdef INET6
3241eaf0ac3Slogwang 			else if (strcmp(optarg, "inet6") == 0)
3251eaf0ac3Slogwang 				af = AF_INET6;
3261eaf0ac3Slogwang #endif
3271eaf0ac3Slogwang #ifdef IPSEC
3281eaf0ac3Slogwang 			else if (strcmp(optarg, "pfkey") == 0)
3291eaf0ac3Slogwang 				af = PF_KEY;
3301eaf0ac3Slogwang #endif
3311eaf0ac3Slogwang 			else if (strcmp(optarg, "unix") == 0 ||
3321eaf0ac3Slogwang 				 strcmp(optarg, "local") == 0)
3331eaf0ac3Slogwang 				af = AF_UNIX;
3341eaf0ac3Slogwang #ifdef NETGRAPH
3351eaf0ac3Slogwang 			else if (strcmp(optarg, "ng") == 0
3361eaf0ac3Slogwang 			    || strcmp(optarg, "netgraph") == 0)
3371eaf0ac3Slogwang 				af = AF_NETGRAPH;
3381eaf0ac3Slogwang #endif
3391eaf0ac3Slogwang 			else if (strcmp(optarg, "link") == 0)
3401eaf0ac3Slogwang 				af = AF_LINK;
3411eaf0ac3Slogwang 			else {
3421eaf0ac3Slogwang 				xo_errx(1, "%s: unknown address family",
3431eaf0ac3Slogwang 				    optarg);
3441eaf0ac3Slogwang 			}
3451eaf0ac3Slogwang 			break;
3461eaf0ac3Slogwang 		case 'g':
3471eaf0ac3Slogwang 			gflag = 1;
3481eaf0ac3Slogwang 			break;
3491eaf0ac3Slogwang 		case 'h':
3501eaf0ac3Slogwang 			hflag = 1;
3511eaf0ac3Slogwang 			break;
3521eaf0ac3Slogwang 		case 'I': {
3531eaf0ac3Slogwang 			char *cp;
3541eaf0ac3Slogwang 
3551eaf0ac3Slogwang 			iflag = 1;
3561eaf0ac3Slogwang 			for (cp = interface = optarg; isalpha(*cp); cp++)
3571eaf0ac3Slogwang 				continue;
3581eaf0ac3Slogwang 			unit = atoi(cp);
3591eaf0ac3Slogwang 			break;
3601eaf0ac3Slogwang 		}
3611eaf0ac3Slogwang 		case 'i':
3621eaf0ac3Slogwang 			iflag = 1;
3631eaf0ac3Slogwang 			break;
3641eaf0ac3Slogwang 		case 'L':
3651eaf0ac3Slogwang 			Lflag = 1;
3661eaf0ac3Slogwang 			break;
367*d4a07e70Sfengbojiang #ifndef FSTACK
3681eaf0ac3Slogwang 		case 'M':
3691eaf0ac3Slogwang 			memf = optarg;
3701eaf0ac3Slogwang 			break;
3711eaf0ac3Slogwang 		case 'm':
3721eaf0ac3Slogwang 			mflag = 1;
3731eaf0ac3Slogwang 			break;
3741eaf0ac3Slogwang 		case 'N':
3751eaf0ac3Slogwang 			nlistf = optarg;
3761eaf0ac3Slogwang 			break;
377*d4a07e70Sfengbojiang #endif
3781eaf0ac3Slogwang 		case 'n':
3791eaf0ac3Slogwang 			numeric_addr = numeric_port = 1;
3801eaf0ac3Slogwang 			break;
38122ce4affSfengbojiang 		case 'o':
38222ce4affSfengbojiang 			oflag = 1;
38322ce4affSfengbojiang 			break;
38422ce4affSfengbojiang 		case 'O':
38522ce4affSfengbojiang 			Oflag = 1;
38622ce4affSfengbojiang 			break;
38722ce4affSfengbojiang 		case 'P':
38822ce4affSfengbojiang 			Pflag = 1;
38922ce4affSfengbojiang 			break;
3901eaf0ac3Slogwang 		case 'p':
3911eaf0ac3Slogwang 			if ((tp = name2protox(optarg)) == NULL) {
3921eaf0ac3Slogwang 				xo_errx(1, "%s: unknown or uninstrumented "
3931eaf0ac3Slogwang 				    "protocol", optarg);
3941eaf0ac3Slogwang 			}
3951eaf0ac3Slogwang 			pflag = 1;
3961eaf0ac3Slogwang 			break;
3971eaf0ac3Slogwang 		case 'Q':
3981eaf0ac3Slogwang 			Qflag = 1;
3991eaf0ac3Slogwang 			break;
4001eaf0ac3Slogwang 		case 'q':
4011eaf0ac3Slogwang 			noutputs = atoi(optarg);
4021eaf0ac3Slogwang 			if (noutputs != 0)
4031eaf0ac3Slogwang 				noutputs++;
4041eaf0ac3Slogwang 			break;
4051eaf0ac3Slogwang 		case 'r':
4061eaf0ac3Slogwang 			rflag = 1;
4071eaf0ac3Slogwang 			break;
4081eaf0ac3Slogwang 		case 'R':
4091eaf0ac3Slogwang 			Rflag = 1;
4101eaf0ac3Slogwang 			break;
4111eaf0ac3Slogwang 		case 's':
4121eaf0ac3Slogwang 			++sflag;
4131eaf0ac3Slogwang 			break;
4141eaf0ac3Slogwang 		case 'S':
4151eaf0ac3Slogwang 			numeric_addr = 1;
4161eaf0ac3Slogwang 			break;
4171eaf0ac3Slogwang 		case 'u':
4181eaf0ac3Slogwang 			af = AF_UNIX;
4191eaf0ac3Slogwang 			break;
4201eaf0ac3Slogwang 		case 'W':
4211eaf0ac3Slogwang 		case 'l':
4221eaf0ac3Slogwang 			Wflag = 1;
4231eaf0ac3Slogwang 			break;
4241eaf0ac3Slogwang 		case 'w':
4251eaf0ac3Slogwang 			interval = atoi(optarg);
4261eaf0ac3Slogwang 			iflag = 1;
4271eaf0ac3Slogwang 			break;
4281eaf0ac3Slogwang 		case 'T':
4291eaf0ac3Slogwang 			Tflag = 1;
4301eaf0ac3Slogwang 			break;
4311eaf0ac3Slogwang 		case 'x':
4321eaf0ac3Slogwang 			xflag = 1;
4331eaf0ac3Slogwang 			break;
4341eaf0ac3Slogwang 		case 'z':
4351eaf0ac3Slogwang 			zflag = 1;
4361eaf0ac3Slogwang 			break;
437*d4a07e70Sfengbojiang #ifdef FSTACK
438*d4a07e70Sfengbojiang 		case 't':
439*d4a07e70Sfengbojiang 			ff_set_proc_id(atoi(optarg));
440*d4a07e70Sfengbojiang 			break;
441*d4a07e70Sfengbojiang #endif
4421eaf0ac3Slogwang 		case '?':
4431eaf0ac3Slogwang 		default:
4441eaf0ac3Slogwang 			usage();
4451eaf0ac3Slogwang 		}
4461eaf0ac3Slogwang 	argv += optind;
4471eaf0ac3Slogwang 	argc -= optind;
4481eaf0ac3Slogwang 
4491eaf0ac3Slogwang #define	BACKWARD_COMPATIBILITY
4501eaf0ac3Slogwang #ifdef	BACKWARD_COMPATIBILITY
4511eaf0ac3Slogwang 	if (*argv) {
4521eaf0ac3Slogwang 		if (isdigit(**argv)) {
4531eaf0ac3Slogwang 			interval = atoi(*argv);
4541eaf0ac3Slogwang 			if (interval <= 0)
4551eaf0ac3Slogwang 				usage();
4561eaf0ac3Slogwang 			++argv;
4571eaf0ac3Slogwang 			iflag = 1;
4581eaf0ac3Slogwang 		}
4591eaf0ac3Slogwang 		if (*argv) {
4601eaf0ac3Slogwang 			nlistf = *argv;
4611eaf0ac3Slogwang 			if (*++argv)
4621eaf0ac3Slogwang 				memf = *argv;
4631eaf0ac3Slogwang 		}
4641eaf0ac3Slogwang 	}
4651eaf0ac3Slogwang #endif
4661eaf0ac3Slogwang 
4671eaf0ac3Slogwang 	/*
4681eaf0ac3Slogwang 	 * Discard setgid privileges if not the running kernel so that bad
4691eaf0ac3Slogwang 	 * guys can't print interesting stuff from kernel memory.
4701eaf0ac3Slogwang 	 */
471*d4a07e70Sfengbojiang #ifndef FSTACK
4721eaf0ac3Slogwang 	live = (nlistf == NULL && memf == NULL);
473*d4a07e70Sfengbojiang #else
474*d4a07e70Sfengbojiang 	live = 1;
475*d4a07e70Sfengbojiang #endif
4761eaf0ac3Slogwang 	if (!live) {
4771eaf0ac3Slogwang 		if (setgid(getgid()) != 0)
4781eaf0ac3Slogwang 			xo_err(-1, "setgid");
479*d4a07e70Sfengbojiang #ifndef FSTACK
48022ce4affSfengbojiang 		/* Load all necessary kvm symbols */
48122ce4affSfengbojiang 		kresolve_list(nl);
482*d4a07e70Sfengbojiang #endif
4831eaf0ac3Slogwang 	}
4841eaf0ac3Slogwang 
4851eaf0ac3Slogwang 	if (xflag && Tflag)
4861eaf0ac3Slogwang 		xo_errx(1, "-x and -T are incompatible, pick one.");
4871eaf0ac3Slogwang 
4881eaf0ac3Slogwang 	if (Bflag) {
4891eaf0ac3Slogwang 		if (!live)
4901eaf0ac3Slogwang 			usage();
4911eaf0ac3Slogwang 		bpf_stats(interface);
4921eaf0ac3Slogwang 		xo_finish();
493*d4a07e70Sfengbojiang #ifdef FSTACK
494*d4a07e70Sfengbojiang 		ff_ipc_exit();
495*d4a07e70Sfengbojiang #endif
4961eaf0ac3Slogwang 		exit(0);
4971eaf0ac3Slogwang 	}
4981eaf0ac3Slogwang 	if (mflag) {
4991eaf0ac3Slogwang 		if (!live) {
500*d4a07e70Sfengbojiang #ifndef FSTACK
5011eaf0ac3Slogwang 			if (kread(0, NULL, 0) == 0)
5021eaf0ac3Slogwang 				mbpr(kvmd, nl[N_SFSTAT].n_value);
503*d4a07e70Sfengbojiang #endif
5041eaf0ac3Slogwang 		} else
5051eaf0ac3Slogwang 			mbpr(NULL, 0);
5061eaf0ac3Slogwang 		xo_finish();
507*d4a07e70Sfengbojiang #ifdef FSTACK
508*d4a07e70Sfengbojiang 		ff_ipc_exit();
509*d4a07e70Sfengbojiang #endif
5101eaf0ac3Slogwang 		exit(0);
5111eaf0ac3Slogwang 	}
5121eaf0ac3Slogwang 	if (Qflag) {
5131eaf0ac3Slogwang 		if (!live) {
514*d4a07e70Sfengbojiang #ifndef FSTACK
5151eaf0ac3Slogwang 			if (kread(0, NULL, 0) == 0)
5161eaf0ac3Slogwang 				netisr_stats();
517*d4a07e70Sfengbojiang #endif
5181eaf0ac3Slogwang 		} else
5191eaf0ac3Slogwang 			netisr_stats();
5201eaf0ac3Slogwang 		xo_finish();
521*d4a07e70Sfengbojiang #ifdef FSTACK
522*d4a07e70Sfengbojiang 		ff_ipc_exit();
523*d4a07e70Sfengbojiang #endif
5241eaf0ac3Slogwang 		exit(0);
5251eaf0ac3Slogwang 	}
5261eaf0ac3Slogwang #if 0
5271eaf0ac3Slogwang 	/*
5281eaf0ac3Slogwang 	 * Keep file descriptors open to avoid overhead
5291eaf0ac3Slogwang 	 * of open/close on each call to get* routines.
5301eaf0ac3Slogwang 	 */
5311eaf0ac3Slogwang 	sethostent(1);
5321eaf0ac3Slogwang 	setnetent(1);
5331eaf0ac3Slogwang #else
5341eaf0ac3Slogwang 	/*
5351eaf0ac3Slogwang 	 * This does not make sense any more with DNS being default over
5361eaf0ac3Slogwang 	 * the files.  Doing a setXXXXent(1) causes a tcp connection to be
5371eaf0ac3Slogwang 	 * used for the queries, which is slower.
5381eaf0ac3Slogwang 	 */
5391eaf0ac3Slogwang #endif
5401eaf0ac3Slogwang 	if (iflag && !sflag) {
5411eaf0ac3Slogwang 		xo_open_container("statistics");
5421eaf0ac3Slogwang 		intpr(NULL, af);
5431eaf0ac3Slogwang 		xo_close_container("statistics");
5441eaf0ac3Slogwang 		xo_finish();
545*d4a07e70Sfengbojiang #ifdef FSTACK
546*d4a07e70Sfengbojiang 		ff_ipc_exit();
547*d4a07e70Sfengbojiang #endif
5481eaf0ac3Slogwang 		exit(0);
5491eaf0ac3Slogwang 	}
5501eaf0ac3Slogwang 	if (rflag) {
5511eaf0ac3Slogwang 		xo_open_container("statistics");
5521eaf0ac3Slogwang 		if (sflag) {
55322ce4affSfengbojiang 			if (live) {
554*d4a07e70Sfengbojiang #ifndef FSTACK
55522ce4affSfengbojiang 				kresolve_list(nl);
556*d4a07e70Sfengbojiang #endif
55722ce4affSfengbojiang 			}
5581eaf0ac3Slogwang 			rt_stats();
5591eaf0ac3Slogwang 		} else
5601eaf0ac3Slogwang 			routepr(fib, af);
5611eaf0ac3Slogwang 		xo_close_container("statistics");
5621eaf0ac3Slogwang 		xo_finish();
563*d4a07e70Sfengbojiang #ifdef FSTACK
564*d4a07e70Sfengbojiang 		ff_ipc_exit();
565*d4a07e70Sfengbojiang #endif
5661eaf0ac3Slogwang 		exit(0);
5671eaf0ac3Slogwang 	}
56822ce4affSfengbojiang 	if (oflag) {
56922ce4affSfengbojiang 		xo_open_container("statistics");
57022ce4affSfengbojiang 		nhops_print(fib, af);
57122ce4affSfengbojiang 		xo_close_container("statistics");
57222ce4affSfengbojiang 		xo_finish();
573*d4a07e70Sfengbojiang #ifdef FSTACK
574*d4a07e70Sfengbojiang 		ff_ipc_exit();
575*d4a07e70Sfengbojiang #endif
57622ce4affSfengbojiang 		exit(0);
57722ce4affSfengbojiang 	}
57822ce4affSfengbojiang 	if (Oflag) {
57922ce4affSfengbojiang 		xo_open_container("statistics");
58022ce4affSfengbojiang 		nhgrp_print(fib, af);
58122ce4affSfengbojiang 		xo_close_container("statistics");
58222ce4affSfengbojiang 		xo_finish();
583*d4a07e70Sfengbojiang #ifdef FSTACK
584*d4a07e70Sfengbojiang 		ff_ipc_exit();
585*d4a07e70Sfengbojiang #endif
58622ce4affSfengbojiang 		exit(0);
58722ce4affSfengbojiang 	}
58822ce4affSfengbojiang 
58922ce4affSfengbojiang 
5901eaf0ac3Slogwang 
5911eaf0ac3Slogwang 	if (gflag) {
5921eaf0ac3Slogwang 		xo_open_container("statistics");
5931eaf0ac3Slogwang 		if (sflag) {
5941eaf0ac3Slogwang 			if (af == AF_INET || af == AF_UNSPEC)
5951eaf0ac3Slogwang 				mrt_stats();
5961eaf0ac3Slogwang #ifdef INET6
5971eaf0ac3Slogwang 			if (af == AF_INET6 || af == AF_UNSPEC)
5981eaf0ac3Slogwang 				mrt6_stats();
5991eaf0ac3Slogwang #endif
6001eaf0ac3Slogwang 		} else {
6011eaf0ac3Slogwang 			if (af == AF_INET || af == AF_UNSPEC)
6021eaf0ac3Slogwang 				mroutepr();
6031eaf0ac3Slogwang #ifdef INET6
6041eaf0ac3Slogwang 			if (af == AF_INET6 || af == AF_UNSPEC)
6051eaf0ac3Slogwang 				mroute6pr();
6061eaf0ac3Slogwang #endif
6071eaf0ac3Slogwang 		}
6081eaf0ac3Slogwang 		xo_close_container("statistics");
6091eaf0ac3Slogwang 		xo_finish();
610*d4a07e70Sfengbojiang #ifdef FSTACK
611*d4a07e70Sfengbojiang 		ff_ipc_exit();
612*d4a07e70Sfengbojiang #endif
6131eaf0ac3Slogwang 		exit(0);
6141eaf0ac3Slogwang 	}
6151eaf0ac3Slogwang 
6161eaf0ac3Slogwang 	if (tp) {
6171eaf0ac3Slogwang 		xo_open_container("statistics");
6181eaf0ac3Slogwang 		printproto(tp, tp->pr_name, &first);
6191eaf0ac3Slogwang 		if (!first)
6201eaf0ac3Slogwang 			xo_close_list("socket");
6211eaf0ac3Slogwang 		xo_close_container("statistics");
6221eaf0ac3Slogwang 		xo_finish();
623*d4a07e70Sfengbojiang #ifdef FSTACK
624*d4a07e70Sfengbojiang 		ff_ipc_exit();
625*d4a07e70Sfengbojiang #endif
6261eaf0ac3Slogwang 		exit(0);
6271eaf0ac3Slogwang 	}
6281eaf0ac3Slogwang 
6291eaf0ac3Slogwang 	xo_open_container("statistics");
6301eaf0ac3Slogwang 	if (af == AF_INET || af == AF_UNSPEC)
6311eaf0ac3Slogwang 		for (tp = protox; tp->pr_name; tp++)
6321eaf0ac3Slogwang 			printproto(tp, tp->pr_name, &first);
6331eaf0ac3Slogwang #ifdef INET6
6341eaf0ac3Slogwang 	if (af == AF_INET6 || af == AF_UNSPEC)
6351eaf0ac3Slogwang 		for (tp = ip6protox; tp->pr_name; tp++)
6361eaf0ac3Slogwang 			printproto(tp, tp->pr_name, &first);
6371eaf0ac3Slogwang #endif /*INET6*/
6381eaf0ac3Slogwang #ifdef IPSEC
6391eaf0ac3Slogwang 	if (af == PF_KEY || af == AF_UNSPEC)
6401eaf0ac3Slogwang 		for (tp = pfkeyprotox; tp->pr_name; tp++)
6411eaf0ac3Slogwang 			printproto(tp, tp->pr_name, &first);
6421eaf0ac3Slogwang #endif /*IPSEC*/
6431eaf0ac3Slogwang #ifdef NETGRAPH
6441eaf0ac3Slogwang 	if (af == AF_NETGRAPH || af == AF_UNSPEC)
6451eaf0ac3Slogwang 		for (tp = netgraphprotox; tp->pr_name; tp++)
6461eaf0ac3Slogwang 			printproto(tp, tp->pr_name, &first);
6471eaf0ac3Slogwang #endif /* NETGRAPH */
6481eaf0ac3Slogwang 	if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
6491eaf0ac3Slogwang 		unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
6501eaf0ac3Slogwang 		    nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value,
6511eaf0ac3Slogwang 		    nl[N_UNP_SPHEAD].n_value, &first);
6521eaf0ac3Slogwang 
6531eaf0ac3Slogwang 	if (!first)
6541eaf0ac3Slogwang 		xo_close_list("socket");
6551eaf0ac3Slogwang 	xo_close_container("statistics");
6561eaf0ac3Slogwang 	xo_finish();
657*d4a07e70Sfengbojiang 
658*d4a07e70Sfengbojiang #ifdef FSTACK
659*d4a07e70Sfengbojiang 	ff_ipc_exit();
660*d4a07e70Sfengbojiang #endif
661*d4a07e70Sfengbojiang 
6621eaf0ac3Slogwang 	exit(0);
6631eaf0ac3Slogwang }
6641eaf0ac3Slogwang 
6651eaf0ac3Slogwang static int
fetch_stats_internal(const char * sysctlname,u_long off,void * stats,size_t len,kreadfn_t kreadfn,int zero)6661eaf0ac3Slogwang fetch_stats_internal(const char *sysctlname, u_long off, void *stats,
6671eaf0ac3Slogwang     size_t len, kreadfn_t kreadfn, int zero)
6681eaf0ac3Slogwang {
6691eaf0ac3Slogwang 	int error;
6701eaf0ac3Slogwang 
6711eaf0ac3Slogwang 	if (live) {
6721eaf0ac3Slogwang 		memset(stats, 0, len);
6731eaf0ac3Slogwang 		if (zero)
6741eaf0ac3Slogwang 			error = sysctlbyname(sysctlname, NULL, NULL, stats,
6751eaf0ac3Slogwang 			    len);
6761eaf0ac3Slogwang 		else
6771eaf0ac3Slogwang 			error = sysctlbyname(sysctlname, stats, &len, NULL, 0);
6781eaf0ac3Slogwang 		if (error == -1 && errno != ENOENT)
6791eaf0ac3Slogwang 			xo_warn("sysctl %s", sysctlname);
6801eaf0ac3Slogwang 	} else {
6811eaf0ac3Slogwang 		if (off == 0)
6821eaf0ac3Slogwang 			return (1);
6831eaf0ac3Slogwang 		error = kreadfn(off, stats, len);
6841eaf0ac3Slogwang 	}
6851eaf0ac3Slogwang 	return (error);
6861eaf0ac3Slogwang }
6871eaf0ac3Slogwang 
6881eaf0ac3Slogwang int
fetch_stats(const char * sysctlname,u_long off,void * stats,size_t len,kreadfn_t kreadfn)6891eaf0ac3Slogwang fetch_stats(const char *sysctlname, u_long off, void *stats,
6901eaf0ac3Slogwang     size_t len, kreadfn_t kreadfn)
6911eaf0ac3Slogwang {
6921eaf0ac3Slogwang 
6931eaf0ac3Slogwang 	return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn,
6941eaf0ac3Slogwang     zflag));
6951eaf0ac3Slogwang }
6961eaf0ac3Slogwang 
6971eaf0ac3Slogwang int
fetch_stats_ro(const char * sysctlname,u_long off,void * stats,size_t len,kreadfn_t kreadfn)6981eaf0ac3Slogwang fetch_stats_ro(const char *sysctlname, u_long off, void *stats,
6991eaf0ac3Slogwang     size_t len, kreadfn_t kreadfn)
7001eaf0ac3Slogwang {
7011eaf0ac3Slogwang 
7021eaf0ac3Slogwang 	return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0));
7031eaf0ac3Slogwang }
7041eaf0ac3Slogwang 
7051eaf0ac3Slogwang /*
7061eaf0ac3Slogwang  * Print out protocol statistics or control blocks (per sflag).
7071eaf0ac3Slogwang  * If the interface was not specifically requested, and the symbol
7081eaf0ac3Slogwang  * is not in the namelist, ignore this one.
7091eaf0ac3Slogwang  */
7101eaf0ac3Slogwang static void
printproto(struct protox * tp,const char * name,bool * first)7111eaf0ac3Slogwang printproto(struct protox *tp, const char *name, bool *first)
7121eaf0ac3Slogwang {
7131eaf0ac3Slogwang 	void (*pr)(u_long, const char *, int, int);
7141eaf0ac3Slogwang 	u_long off;
7151eaf0ac3Slogwang 	bool doingdblocks = false;
7161eaf0ac3Slogwang 
7171eaf0ac3Slogwang 	if (sflag) {
7181eaf0ac3Slogwang 		if (iflag) {
7191eaf0ac3Slogwang 			if (tp->pr_istats)
7201eaf0ac3Slogwang 				intpr(tp->pr_istats, af);
7211eaf0ac3Slogwang 			else if (pflag)
7221eaf0ac3Slogwang 				xo_message("%s: no per-interface stats routine",
7231eaf0ac3Slogwang 				    tp->pr_name);
7241eaf0ac3Slogwang 			return;
7251eaf0ac3Slogwang 		} else {
7261eaf0ac3Slogwang 			pr = tp->pr_stats;
7271eaf0ac3Slogwang 			if (!pr) {
7281eaf0ac3Slogwang 				if (pflag)
7291eaf0ac3Slogwang 					xo_message("%s: no stats routine",
7301eaf0ac3Slogwang 					    tp->pr_name);
7311eaf0ac3Slogwang 				return;
7321eaf0ac3Slogwang 			}
7331eaf0ac3Slogwang 			if (tp->pr_usesysctl && live)
7341eaf0ac3Slogwang 				off = 0;
7351eaf0ac3Slogwang 			else if (tp->pr_sindex < 0) {
7361eaf0ac3Slogwang 				if (pflag)
7371eaf0ac3Slogwang 					xo_message("%s: stats routine doesn't "
7381eaf0ac3Slogwang 					    "work on cores", tp->pr_name);
7391eaf0ac3Slogwang 				return;
7401eaf0ac3Slogwang 			} else
7411eaf0ac3Slogwang 				off = nl[tp->pr_sindex].n_value;
7421eaf0ac3Slogwang 		}
7431eaf0ac3Slogwang 	} else {
7441eaf0ac3Slogwang 		doingdblocks = true;
7451eaf0ac3Slogwang 		pr = tp->pr_cblocks;
7461eaf0ac3Slogwang 		if (!pr) {
7471eaf0ac3Slogwang 			if (pflag)
7481eaf0ac3Slogwang 				xo_message("%s: no PCB routine", tp->pr_name);
7491eaf0ac3Slogwang 			return;
7501eaf0ac3Slogwang 		}
7511eaf0ac3Slogwang 		if (tp->pr_usesysctl && live)
7521eaf0ac3Slogwang 			off = 0;
7531eaf0ac3Slogwang 		else if (tp->pr_index < 0) {
7541eaf0ac3Slogwang 			if (pflag)
7551eaf0ac3Slogwang 				xo_message("%s: PCB routine doesn't work on "
7561eaf0ac3Slogwang 				    "cores", tp->pr_name);
7571eaf0ac3Slogwang 			return;
7581eaf0ac3Slogwang 		} else
7591eaf0ac3Slogwang 			off = nl[tp->pr_index].n_value;
7601eaf0ac3Slogwang 	}
7611eaf0ac3Slogwang 	if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
7621eaf0ac3Slogwang 	    af != AF_UNSPEC)) {
7631eaf0ac3Slogwang 		if (doingdblocks && *first) {
7641eaf0ac3Slogwang 			xo_open_list("socket");
7651eaf0ac3Slogwang 			*first = false;
7661eaf0ac3Slogwang 		}
7671eaf0ac3Slogwang 
7681eaf0ac3Slogwang 		(*pr)(off, name, af, tp->pr_protocol);
7691eaf0ac3Slogwang 	}
7701eaf0ac3Slogwang }
7711eaf0ac3Slogwang 
772*d4a07e70Sfengbojiang #ifndef FSTACK
7731eaf0ac3Slogwang static int
kvmd_init(void)7741eaf0ac3Slogwang kvmd_init(void)
7751eaf0ac3Slogwang {
7761eaf0ac3Slogwang 	char errbuf[_POSIX2_LINE_MAX];
7771eaf0ac3Slogwang 
7781eaf0ac3Slogwang 	if (kvmd != NULL)
7791eaf0ac3Slogwang 		return (0);
7801eaf0ac3Slogwang 
7811eaf0ac3Slogwang 	kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
7821eaf0ac3Slogwang 	if (setgid(getgid()) != 0)
7831eaf0ac3Slogwang 		xo_err(-1, "setgid");
7841eaf0ac3Slogwang 
7851eaf0ac3Slogwang 	if (kvmd == NULL) {
7861eaf0ac3Slogwang 		xo_warnx("kvm not available: %s", errbuf);
7871eaf0ac3Slogwang 		return (-1);
7881eaf0ac3Slogwang 	}
7891eaf0ac3Slogwang 
7901eaf0ac3Slogwang 	return (0);
7911eaf0ac3Slogwang }
7921eaf0ac3Slogwang 
7931eaf0ac3Slogwang /*
7941eaf0ac3Slogwang  * Resolve symbol list, return 0 on success.
7951eaf0ac3Slogwang  */
7961eaf0ac3Slogwang static int
kresolve_list(struct nlist * _nl)7971eaf0ac3Slogwang kresolve_list(struct nlist *_nl)
7981eaf0ac3Slogwang {
7991eaf0ac3Slogwang 
8001eaf0ac3Slogwang 	if ((kvmd == NULL) && (kvmd_init() != 0))
8011eaf0ac3Slogwang 		return (-1);
8021eaf0ac3Slogwang 
8031eaf0ac3Slogwang 	if (_nl[0].n_type != 0)
8041eaf0ac3Slogwang 		return (0);
8051eaf0ac3Slogwang 
8061eaf0ac3Slogwang 	if (kvm_nlist(kvmd, _nl) < 0) {
8071eaf0ac3Slogwang 		if (nlistf)
8081eaf0ac3Slogwang 			xo_errx(1, "%s: kvm_nlist: %s", nlistf,
8091eaf0ac3Slogwang 			    kvm_geterr(kvmd));
8101eaf0ac3Slogwang 		else
8111eaf0ac3Slogwang 			xo_errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
8121eaf0ac3Slogwang 	}
8131eaf0ac3Slogwang 
8141eaf0ac3Slogwang 	return (0);
8151eaf0ac3Slogwang }
8161eaf0ac3Slogwang 
8171eaf0ac3Slogwang /*
8181eaf0ac3Slogwang  * Wrapper of kvm_dpcpu_setcpu().
8191eaf0ac3Slogwang  */
8201eaf0ac3Slogwang void
kset_dpcpu(u_int cpuid)8211eaf0ac3Slogwang kset_dpcpu(u_int cpuid)
8221eaf0ac3Slogwang {
8231eaf0ac3Slogwang 
8241eaf0ac3Slogwang 	if ((kvmd == NULL) && (kvmd_init() != 0))
8251eaf0ac3Slogwang 		xo_errx(-1, "%s: kvm is not available", __func__);
8261eaf0ac3Slogwang 
8271eaf0ac3Slogwang 	if (kvm_dpcpu_setcpu(kvmd, cpuid) < 0)
8281eaf0ac3Slogwang 		xo_errx(-1, "%s: kvm_dpcpu_setcpu(%u): %s", __func__,
8291eaf0ac3Slogwang 		    cpuid, kvm_geterr(kvmd));
8301eaf0ac3Slogwang 	return;
8311eaf0ac3Slogwang }
8321eaf0ac3Slogwang 
8331eaf0ac3Slogwang /*
8341eaf0ac3Slogwang  * Read kernel memory, return 0 on success.
8351eaf0ac3Slogwang  */
8361eaf0ac3Slogwang int
kread(u_long addr,void * buf,size_t size)8371eaf0ac3Slogwang kread(u_long addr, void *buf, size_t size)
8381eaf0ac3Slogwang {
8391eaf0ac3Slogwang 
8401eaf0ac3Slogwang 	if (kvmd_init() < 0)
8411eaf0ac3Slogwang 		return (-1);
8421eaf0ac3Slogwang 
8431eaf0ac3Slogwang 	if (!buf)
8441eaf0ac3Slogwang 		return (0);
8451eaf0ac3Slogwang 	if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
8461eaf0ac3Slogwang 		xo_warnx("%s", kvm_geterr(kvmd));
8471eaf0ac3Slogwang 		return (-1);
8481eaf0ac3Slogwang 	}
8491eaf0ac3Slogwang 	return (0);
8501eaf0ac3Slogwang }
8511eaf0ac3Slogwang 
8521eaf0ac3Slogwang /*
8531eaf0ac3Slogwang  * Read single counter(9).
8541eaf0ac3Slogwang  */
8551eaf0ac3Slogwang uint64_t
kread_counter(u_long addr)8561eaf0ac3Slogwang kread_counter(u_long addr)
8571eaf0ac3Slogwang {
8581eaf0ac3Slogwang 
8591eaf0ac3Slogwang 	if (kvmd_init() < 0)
8601eaf0ac3Slogwang 		return (-1);
8611eaf0ac3Slogwang 
8621eaf0ac3Slogwang 	return (kvm_counter_u64_fetch(kvmd, addr));
8631eaf0ac3Slogwang }
8641eaf0ac3Slogwang 
8651eaf0ac3Slogwang /*
8661eaf0ac3Slogwang  * Read an array of N counters in kernel memory into array of N uint64_t's.
8671eaf0ac3Slogwang  */
8681eaf0ac3Slogwang int
kread_counters(u_long addr,void * buf,size_t size)8691eaf0ac3Slogwang kread_counters(u_long addr, void *buf, size_t size)
8701eaf0ac3Slogwang {
8711eaf0ac3Slogwang 	uint64_t *c;
8721eaf0ac3Slogwang 	u_long *counters;
8731eaf0ac3Slogwang 	size_t i, n;
8741eaf0ac3Slogwang 
8751eaf0ac3Slogwang 	if (kvmd_init() < 0)
8761eaf0ac3Slogwang 		return (-1);
8771eaf0ac3Slogwang 
8781eaf0ac3Slogwang 	if (size % sizeof(uint64_t) != 0) {
8791eaf0ac3Slogwang 		xo_warnx("kread_counters: invalid counter set size");
8801eaf0ac3Slogwang 		return (-1);
8811eaf0ac3Slogwang 	}
8821eaf0ac3Slogwang 
8831eaf0ac3Slogwang 	n = size / sizeof(uint64_t);
8841eaf0ac3Slogwang 	if ((counters = malloc(n * sizeof(u_long))) == NULL)
8851eaf0ac3Slogwang 		xo_err(-1, "malloc");
8861eaf0ac3Slogwang 	if (kread(addr, counters, n * sizeof(u_long)) < 0) {
8871eaf0ac3Slogwang 		free(counters);
8881eaf0ac3Slogwang 		return (-1);
8891eaf0ac3Slogwang 	}
8901eaf0ac3Slogwang 
8911eaf0ac3Slogwang 	c = buf;
8921eaf0ac3Slogwang 	for (i = 0; i < n; i++)
8931eaf0ac3Slogwang 		c[i] = kvm_counter_u64_fetch(kvmd, counters[i]);
8941eaf0ac3Slogwang 
8951eaf0ac3Slogwang 	free(counters);
8961eaf0ac3Slogwang 	return (0);
8971eaf0ac3Slogwang }
8981eaf0ac3Slogwang 
899*d4a07e70Sfengbojiang #else
900*d4a07e70Sfengbojiang int
kread(u_long addr,void * buf,size_t size)901*d4a07e70Sfengbojiang kread(u_long addr, void *buf, size_t size)
902*d4a07e70Sfengbojiang {
903*d4a07e70Sfengbojiang 	return 0;
904*d4a07e70Sfengbojiang }
905*d4a07e70Sfengbojiang 
906*d4a07e70Sfengbojiang uint64_t
kread_counter(u_long addr)907*d4a07e70Sfengbojiang kread_counter(u_long addr)
908*d4a07e70Sfengbojiang {
909*d4a07e70Sfengbojiang 	return 0;
910*d4a07e70Sfengbojiang }
911*d4a07e70Sfengbojiang 
912*d4a07e70Sfengbojiang int
kread_counters(u_long addr,void * buf,size_t size)913*d4a07e70Sfengbojiang kread_counters(u_long addr, void *buf, size_t size)
914*d4a07e70Sfengbojiang {
915*d4a07e70Sfengbojiang 	return 0;
916*d4a07e70Sfengbojiang }
917*d4a07e70Sfengbojiang void
kset_dpcpu(u_int cpuid)918*d4a07e70Sfengbojiang kset_dpcpu(u_int cpuid)
919*d4a07e70Sfengbojiang {
920*d4a07e70Sfengbojiang 
921*d4a07e70Sfengbojiang }
922*d4a07e70Sfengbojiang 
923*d4a07e70Sfengbojiang #endif
924*d4a07e70Sfengbojiang 
9251eaf0ac3Slogwang const char *
plural(uintmax_t n)9261eaf0ac3Slogwang plural(uintmax_t n)
9271eaf0ac3Slogwang {
9281eaf0ac3Slogwang 	return (n != 1 ? "s" : "");
9291eaf0ac3Slogwang }
9301eaf0ac3Slogwang 
9311eaf0ac3Slogwang const char *
plurales(uintmax_t n)9321eaf0ac3Slogwang plurales(uintmax_t n)
9331eaf0ac3Slogwang {
9341eaf0ac3Slogwang 	return (n != 1 ? "es" : "");
9351eaf0ac3Slogwang }
9361eaf0ac3Slogwang 
9371eaf0ac3Slogwang const char *
pluralies(uintmax_t n)9381eaf0ac3Slogwang pluralies(uintmax_t n)
9391eaf0ac3Slogwang {
9401eaf0ac3Slogwang 	return (n != 1 ? "ies" : "y");
9411eaf0ac3Slogwang }
9421eaf0ac3Slogwang 
9431eaf0ac3Slogwang /*
9441eaf0ac3Slogwang  * Find the protox for the given "well-known" name.
9451eaf0ac3Slogwang  */
9461eaf0ac3Slogwang static struct protox *
knownname(const char * name)9471eaf0ac3Slogwang knownname(const char *name)
9481eaf0ac3Slogwang {
9491eaf0ac3Slogwang 	struct protox **tpp, *tp;
9501eaf0ac3Slogwang 
9511eaf0ac3Slogwang 	for (tpp = protoprotox; *tpp; tpp++)
9521eaf0ac3Slogwang 		for (tp = *tpp; tp->pr_name; tp++)
9531eaf0ac3Slogwang 			if (strcmp(tp->pr_name, name) == 0)
9541eaf0ac3Slogwang 				return (tp);
9551eaf0ac3Slogwang 	return (NULL);
9561eaf0ac3Slogwang }
9571eaf0ac3Slogwang 
9581eaf0ac3Slogwang /*
9591eaf0ac3Slogwang  * Find the protox corresponding to name.
9601eaf0ac3Slogwang  */
9611eaf0ac3Slogwang static struct protox *
name2protox(const char * name)9621eaf0ac3Slogwang name2protox(const char *name)
9631eaf0ac3Slogwang {
9641eaf0ac3Slogwang 	struct protox *tp;
9651eaf0ac3Slogwang 	char **alias;			/* alias from p->aliases */
9661eaf0ac3Slogwang 	struct protoent *p;
9671eaf0ac3Slogwang 
9681eaf0ac3Slogwang 	/*
9691eaf0ac3Slogwang 	 * Try to find the name in the list of "well-known" names. If that
9701eaf0ac3Slogwang 	 * fails, check if name is an alias for an Internet protocol.
9711eaf0ac3Slogwang 	 */
9721eaf0ac3Slogwang 	if ((tp = knownname(name)) != NULL)
9731eaf0ac3Slogwang 		return (tp);
9741eaf0ac3Slogwang 
9751eaf0ac3Slogwang 	setprotoent(1);			/* make protocol lookup cheaper */
9761eaf0ac3Slogwang 	while ((p = getprotoent()) != NULL) {
9771eaf0ac3Slogwang 		/* assert: name not same as p->name */
9781eaf0ac3Slogwang 		for (alias = p->p_aliases; *alias; alias++)
9791eaf0ac3Slogwang 			if (strcmp(name, *alias) == 0) {
9801eaf0ac3Slogwang 				endprotoent();
9811eaf0ac3Slogwang 				return (knownname(p->p_name));
9821eaf0ac3Slogwang 			}
9831eaf0ac3Slogwang 	}
9841eaf0ac3Slogwang 	endprotoent();
9851eaf0ac3Slogwang 	return (NULL);
9861eaf0ac3Slogwang }
9871eaf0ac3Slogwang 
9881eaf0ac3Slogwang static void
usage(void)9891eaf0ac3Slogwang usage(void)
9901eaf0ac3Slogwang {
9911eaf0ac3Slogwang 	(void)xo_error("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
992*d4a07e70Sfengbojiang #ifndef FSTACK
99322ce4affSfengbojiang "usage: netstat [-46AaCcLnRSTWx] [-f protocol_family | -p protocol]\n"
9941eaf0ac3Slogwang "               [-M core] [-N system]",
9951eaf0ac3Slogwang "       netstat -i | -I interface [-46abdhnW] [-f address_family]\n"
9961eaf0ac3Slogwang "               [-M core] [-N system]",
9971eaf0ac3Slogwang "       netstat -w wait [-I interface] [-46d] [-M core] [-N system]\n"
9981eaf0ac3Slogwang "               [-q howmany]",
9991eaf0ac3Slogwang "       netstat -s [-46sz] [-f protocol_family | -p protocol]\n"
10001eaf0ac3Slogwang "               [-M core] [-N system]",
10011eaf0ac3Slogwang "       netstat -i | -I interface -s [-46s]\n"
10021eaf0ac3Slogwang "               [-f protocol_family | -p protocol] [-M core] [-N system]",
10031eaf0ac3Slogwang "       netstat -m [-M core] [-N system]",
10041eaf0ac3Slogwang "       netstat -B [-z] [-I interface]",
10051eaf0ac3Slogwang "       netstat -r [-46AnW] [-F fibnum] [-f address_family]\n"
10061eaf0ac3Slogwang "               [-M core] [-N system]",
10071eaf0ac3Slogwang "       netstat -rs [-s] [-M core] [-N system]",
10081eaf0ac3Slogwang "       netstat -g [-46W] [-f address_family] [-M core] [-N system]",
10091eaf0ac3Slogwang "       netstat -gs [-46s] [-f address_family] [-M core] [-N system]",
10101eaf0ac3Slogwang "       netstat -Q");
1011*d4a07e70Sfengbojiang #else
1012*d4a07e70Sfengbojiang "usage: netstat -t <f-stack proc_id> [-46AaLnRSTWx] [-f protocol_family | -p protocol]",
1013*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -i | -I interface [-46abdhnW] [-f address_family]",
1014*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -w wait [-I interface] [-46d] [-q howmany]",
1015*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -s [-46sz] [-f protocol_family | -p protocol]",
1016*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -i | -I interface -s [-46s]\n"
1017*d4a07e70Sfengbojiang "               [-f protocol_family | -p protocol]",
1018*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -B [-z] [-I interface]",
1019*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -r [-46AnW] [-F fibnum] [-f address_family]",
1020*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -rs [-s]",
1021*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -g [-46W] [-f address_family]",
1022*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -gs [-46s] [-f address_family]",
1023*d4a07e70Sfengbojiang "       netstat -t <f-stack proc_id> -Q");
1024*d4a07e70Sfengbojiang 
1025*d4a07e70Sfengbojiang #endif
10261eaf0ac3Slogwang 	xo_finish();
1027*d4a07e70Sfengbojiang #ifdef FSTACK
1028*d4a07e70Sfengbojiang 	ff_ipc_exit();
1029*d4a07e70Sfengbojiang #endif
10301eaf0ac3Slogwang 	exit(1);
10311eaf0ac3Slogwang }
1032