17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22550b6e40SSowmini Varadhan  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1990  Mentat Inc.
247c478bd9Sstevel@tonic-gate  * netstat.c 2.2, last change 9/9/91
257c478bd9Sstevel@tonic-gate  * MROUTING Revision 3.5
26d38b7101SDan McDonald  * Copyright 2018, Joyent, Inc.
27a02120c4SAndy Fiddaman  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
28*cdfd7f6bSJason King  * Copyright 2021 Racktop Systems, Inc.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * simple netstat based on snmp/mib-2 interface to the TCP/IP stack
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * TODO:
357c478bd9Sstevel@tonic-gate  *	Add ability to request subsets from kernel (with level = MIB2_IP;
367c478bd9Sstevel@tonic-gate  *	name = 0 meaning everything for compatibility)
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <stdarg.h>
427c478bd9Sstevel@tonic-gate #include <unistd.h>
437c478bd9Sstevel@tonic-gate #include <strings.h>
447c478bd9Sstevel@tonic-gate #include <string.h>
457c478bd9Sstevel@tonic-gate #include <errno.h>
467c478bd9Sstevel@tonic-gate #include <ctype.h>
477c478bd9Sstevel@tonic-gate #include <kstat.h>
487c478bd9Sstevel@tonic-gate #include <assert.h>
4926fd7700SKrishnendu Sadhukhan - Sun Microsystems #include <locale.h>
50afee3dc6SRobert Mustacchi #include <synch.h>
51afee3dc6SRobert Mustacchi #include <thread.h>
5278a2e113SAndy Fiddaman #include <pwd.h>
5378a2e113SAndy Fiddaman #include <limits.h>
5478a2e113SAndy Fiddaman #include <sys/ccompile.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <sys/types.h>
5778a2e113SAndy Fiddaman #include <sys/stat.h>
587c478bd9Sstevel@tonic-gate #include <sys/stream.h>
597c478bd9Sstevel@tonic-gate #include <stropts.h>
607c478bd9Sstevel@tonic-gate #include <sys/strstat.h>
617c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
6278a2e113SAndy Fiddaman #include <procfs.h>
6378a2e113SAndy Fiddaman #include <dirent.h>
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #include <sys/socket.h>
6678a2e113SAndy Fiddaman #include <sys/socketvar.h>
677c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
687c478bd9Sstevel@tonic-gate #include <netinet/in.h>
697c478bd9Sstevel@tonic-gate #include <net/if.h>
707c478bd9Sstevel@tonic-gate #include <net/route.h>
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #include <inet/mib2.h>
737c478bd9Sstevel@tonic-gate #include <inet/ip.h>
747c478bd9Sstevel@tonic-gate #include <inet/arp.h>
757c478bd9Sstevel@tonic-gate #include <inet/tcp.h>
767c478bd9Sstevel@tonic-gate #include <netinet/igmp_var.h>
777c478bd9Sstevel@tonic-gate #include <netinet/ip_mroute.h>
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
807c478bd9Sstevel@tonic-gate #include <netdb.h>
817c478bd9Sstevel@tonic-gate #include <fcntl.h>
827c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
837c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h>
867c478bd9Sstevel@tonic-gate #include <dhcpagent_ipc.h>
877c478bd9Sstevel@tonic-gate #include <dhcpagent_util.h>
887c478bd9Sstevel@tonic-gate #include <compat.h>
8978a2e113SAndy Fiddaman #include <sys/mkdev.h>
907c478bd9Sstevel@tonic-gate 
9145916cd2Sjpk #include <libtsnet.h>
9245916cd2Sjpk #include <tsol/label.h>
9345916cd2Sjpk 
9478a2e113SAndy Fiddaman #include <libproc.h>
9526fd7700SKrishnendu Sadhukhan - Sun Microsystems 
9678a2e113SAndy Fiddaman #include "statcommon.h"
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	STR_EXPAND	4
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #define	V4MASK_TO_V6(v4, v6)	((v6)._S6_un._S6_u32[0] = 0xfffffffful, \
1017c478bd9Sstevel@tonic-gate 				(v6)._S6_un._S6_u32[1] = 0xfffffffful, \
1027c478bd9Sstevel@tonic-gate 				(v6)._S6_un._S6_u32[2] = 0xfffffffful, \
1037c478bd9Sstevel@tonic-gate 				(v6)._S6_un._S6_u32[3] = (v4))
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #define	IN6_IS_V4MASK(v6)	((v6)._S6_un._S6_u32[0] == 0xfffffffful && \
1067c478bd9Sstevel@tonic-gate 				(v6)._S6_un._S6_u32[1] == 0xfffffffful && \
1077c478bd9Sstevel@tonic-gate 				(v6)._S6_un._S6_u32[2] == 0xfffffffful)
1087c478bd9Sstevel@tonic-gate 
109d04ccbb3Scarlsonj /*
110d04ccbb3Scarlsonj  * This is used as a cushion in the buffer allocation directed by SIOCGLIFNUM.
111d04ccbb3Scarlsonj  * Because there's no locking between SIOCGLIFNUM and SIOCGLIFCONF, it's
112d04ccbb3Scarlsonj  * possible for an administrator to plumb new interfaces between those two
113d04ccbb3Scarlsonj  * calls, resulting in the failure of the latter.  This addition makes that
114d04ccbb3Scarlsonj  * less likely.
115d04ccbb3Scarlsonj  */
116d04ccbb3Scarlsonj #define	LIFN_GUARD_VALUE	10
117d04ccbb3Scarlsonj 
1187c478bd9Sstevel@tonic-gate typedef struct mib_item_s {
1197c478bd9Sstevel@tonic-gate 	struct mib_item_s	*next_item;
1207c478bd9Sstevel@tonic-gate 	int			group;
1217c478bd9Sstevel@tonic-gate 	int			mib_id;
1227c478bd9Sstevel@tonic-gate 	int			length;
1237c478bd9Sstevel@tonic-gate 	void			*valp;
1247c478bd9Sstevel@tonic-gate } mib_item_t;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate struct	ifstat {
1277c478bd9Sstevel@tonic-gate 	uint64_t	ipackets;
1287c478bd9Sstevel@tonic-gate 	uint64_t	ierrors;
1297c478bd9Sstevel@tonic-gate 	uint64_t	opackets;
1307c478bd9Sstevel@tonic-gate 	uint64_t	oerrors;
1317c478bd9Sstevel@tonic-gate 	uint64_t	collisions;
1327c478bd9Sstevel@tonic-gate };
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate struct iflist {
1357c478bd9Sstevel@tonic-gate 	struct iflist	*next_if;
1367c478bd9Sstevel@tonic-gate 	char		ifname[LIFNAMSIZ];
1377c478bd9Sstevel@tonic-gate 	struct ifstat	tot;
1387c478bd9Sstevel@tonic-gate };
1397c478bd9Sstevel@tonic-gate 
14078a2e113SAndy Fiddaman static void fatal(int, char *, ...) __NORETURN;
14178a2e113SAndy Fiddaman 
1427c478bd9Sstevel@tonic-gate static	mib_item_t	*mibget(int sd);
1437c478bd9Sstevel@tonic-gate static	void		mibfree(mib_item_t *firstitem);
1447c478bd9Sstevel@tonic-gate static	int		mibopen(void);
1457c478bd9Sstevel@tonic-gate static void		mib_get_constants(mib_item_t *item);
1467c478bd9Sstevel@tonic-gate static mib_item_t	*mib_item_dup(mib_item_t *item);
14778a2e113SAndy Fiddaman static mib_item_t	*mib_item_diff(mib_item_t *item1, mib_item_t *item2);
1487c478bd9Sstevel@tonic-gate static void		mib_item_destroy(mib_item_t **item);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate static boolean_t	octetstrmatch(const Octet_t *a, const Octet_t *b);
15145916cd2Sjpk static char		*octetstr(const Octet_t *op, int code,
1527c478bd9Sstevel@tonic-gate 			    char *dst, uint_t dstlen);
15378a2e113SAndy Fiddaman static char		*pr_addr(uint_t addr, char *dst, uint_t dstlen);
1547c478bd9Sstevel@tonic-gate static char		*pr_addrnz(ipaddr_t addr, char *dst, uint_t dstlen);
1557c478bd9Sstevel@tonic-gate static char		*pr_addr6(const in6_addr_t *addr,
1567c478bd9Sstevel@tonic-gate 			    char *dst, uint_t dstlen);
15778a2e113SAndy Fiddaman static char		*pr_mask(uint_t addr, char *dst, uint_t dstlen);
15845916cd2Sjpk static char		*pr_prefix6(const struct in6_addr *addr,
15945916cd2Sjpk 			    uint_t prefixlen, char *dst, uint_t dstlen);
1607c478bd9Sstevel@tonic-gate static char		*pr_ap(uint_t addr, uint_t port,
1617c478bd9Sstevel@tonic-gate 			    char *proto, char *dst, uint_t dstlen);
1627c478bd9Sstevel@tonic-gate static char		*pr_ap6(const in6_addr_t *addr, uint_t port,
1637c478bd9Sstevel@tonic-gate 			    char *proto, char *dst, uint_t dstlen);
1647c478bd9Sstevel@tonic-gate static char		*pr_net(uint_t addr, uint_t mask,
1657c478bd9Sstevel@tonic-gate 			    char *dst, uint_t dstlen);
1667c478bd9Sstevel@tonic-gate static char		*pr_netaddr(uint_t addr, uint_t mask,
1677c478bd9Sstevel@tonic-gate 			    char *dst, uint_t dstlen);
1687c478bd9Sstevel@tonic-gate static char		*fmodestr(uint_t fmode);
1697c478bd9Sstevel@tonic-gate static char		*portname(uint_t port, char *proto,
1707c478bd9Sstevel@tonic-gate 			    char *dst, uint_t dstlen);
1717c478bd9Sstevel@tonic-gate 
17245916cd2Sjpk static const char	*mitcp_state(int code,
17345916cd2Sjpk 			    const mib2_transportMLPEntry_t *attr);
17445916cd2Sjpk static const char	*miudp_state(int code,
17545916cd2Sjpk 			    const mib2_transportMLPEntry_t *attr);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate static void		stat_report(mib_item_t *item);
1787c478bd9Sstevel@tonic-gate static void		mrt_stat_report(mib_item_t *item);
1797c478bd9Sstevel@tonic-gate static void		arp_report(mib_item_t *item);
1807c478bd9Sstevel@tonic-gate static void		ndp_report(mib_item_t *item);
1817c478bd9Sstevel@tonic-gate static void		mrt_report(mib_item_t *item);
1827c478bd9Sstevel@tonic-gate static void		if_stat_total(struct ifstat *oldstats,
1837c478bd9Sstevel@tonic-gate 			    struct ifstat *newstats, struct ifstat *sumstats);
1847c478bd9Sstevel@tonic-gate static void		if_report(mib_item_t *item, char *ifname,
1857c478bd9Sstevel@tonic-gate 			    int Iflag_only, boolean_t once_only);
1867c478bd9Sstevel@tonic-gate static void		if_report_ip4(mib2_ipAddrEntry_t *ap,
1877c478bd9Sstevel@tonic-gate 			    char ifname[], char logintname[],
1887c478bd9Sstevel@tonic-gate 			    struct ifstat *statptr, boolean_t ksp_not_null);
1897c478bd9Sstevel@tonic-gate static void		if_report_ip6(mib2_ipv6AddrEntry_t *ap6,
1907c478bd9Sstevel@tonic-gate 			    char ifname[], char logintname[],
1917c478bd9Sstevel@tonic-gate 			    struct ifstat *statptr, boolean_t ksp_not_null);
19245916cd2Sjpk static void		ire_report(const mib_item_t *item);
19345916cd2Sjpk static void		tcp_report(const mib_item_t *item);
19445916cd2Sjpk static void		udp_report(const mib_item_t *item);
19578a2e113SAndy Fiddaman static void		uds_report(kstat_ctl_t *);
1967c478bd9Sstevel@tonic-gate static void		group_report(mib_item_t *item);
197bd670b35SErik Nordmark static void		dce_report(mib_item_t *item);
1987c478bd9Sstevel@tonic-gate static void		print_ip_stats(mib2_ip_t *ip);
1997c478bd9Sstevel@tonic-gate static void		print_icmp_stats(mib2_icmp_t *icmp);
2007c478bd9Sstevel@tonic-gate static void		print_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6);
2017c478bd9Sstevel@tonic-gate static void		print_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6);
2027c478bd9Sstevel@tonic-gate static void		print_sctp_stats(mib2_sctp_t *tcp);
2037c478bd9Sstevel@tonic-gate static void		print_tcp_stats(mib2_tcp_t *tcp);
2047c478bd9Sstevel@tonic-gate static void		print_udp_stats(mib2_udp_t *udp);
2057c478bd9Sstevel@tonic-gate static void		print_rawip_stats(mib2_rawip_t *rawip);
2067c478bd9Sstevel@tonic-gate static void		print_igmp_stats(struct igmpstat *igps);
2077c478bd9Sstevel@tonic-gate static void		print_mrt_stats(struct mrtstat *mrts);
20845916cd2Sjpk static void		sctp_report(const mib_item_t *item);
2097c478bd9Sstevel@tonic-gate static void		sum_ip6_stats(mib2_ipv6IfStatsEntry_t *ip6,
2107c478bd9Sstevel@tonic-gate 			    mib2_ipv6IfStatsEntry_t *sum6);
2117c478bd9Sstevel@tonic-gate static void		sum_icmp6_stats(mib2_ipv6IfIcmpEntry_t *icmp6,
2127c478bd9Sstevel@tonic-gate 			    mib2_ipv6IfIcmpEntry_t *sum6);
2137c478bd9Sstevel@tonic-gate static void		m_report(void);
2147c478bd9Sstevel@tonic-gate static void		dhcp_report(char *);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate static	uint64_t	kstat_named_value(kstat_t *, char *);
2177c478bd9Sstevel@tonic-gate static	kid_t		safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
2187c478bd9Sstevel@tonic-gate static int		isnum(char *);
2197c478bd9Sstevel@tonic-gate static char		*plural(int n);
2207c478bd9Sstevel@tonic-gate static char		*pluraly(int n);
2217c478bd9Sstevel@tonic-gate static char		*plurales(int n);
2227c478bd9Sstevel@tonic-gate static void		process_filter(char *arg);
223e11c3f44Smeem static char		*ifindex2str(uint_t, char *);
2247c478bd9Sstevel@tonic-gate static boolean_t	family_selected(int family);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate static void		usage(char *);
22778a2e113SAndy Fiddaman static char		*get_username(uid_t);
22878a2e113SAndy Fiddaman 
22978a2e113SAndy Fiddaman static void		process_hash_build(void);
23078a2e113SAndy Fiddaman static void		process_hash_free(void);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate #define	PLURAL(n) plural((int)n)
2337c478bd9Sstevel@tonic-gate #define	PLURALY(n) pluraly((int)n)
2347c478bd9Sstevel@tonic-gate #define	PLURALES(n) plurales((int)n)
2357c478bd9Sstevel@tonic-gate #define	IFLAGMOD(flg, val1, val2)	if (flg == val1) flg = val2
2367c478bd9Sstevel@tonic-gate #define	MDIFF(diff, elem2, elem1, member)	(diff)->member = \
2377c478bd9Sstevel@tonic-gate 	(elem2)->member - (elem1)->member
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate static	boolean_t	Aflag = B_FALSE;	/* All sockets/ifs/rtng-tbls */
240d38b7101SDan McDonald static	boolean_t	CIDRflag = B_FALSE;	/* CIDR for IPv4 -i/-r addrs */
241bd670b35SErik Nordmark static	boolean_t	Dflag = B_FALSE;	/* DCE info */
2427c478bd9Sstevel@tonic-gate static	boolean_t	Iflag = B_FALSE;	/* IP Traffic Interfaces */
2437c478bd9Sstevel@tonic-gate static	boolean_t	Mflag = B_FALSE;	/* STREAMS Memory Statistics */
2447c478bd9Sstevel@tonic-gate static	boolean_t	Nflag = B_FALSE;	/* Numeric Network Addresses */
2457c478bd9Sstevel@tonic-gate static	boolean_t	Rflag = B_FALSE;	/* Routing Tables */
24645916cd2Sjpk static	boolean_t	RSECflag = B_FALSE;	/* Security attributes */
2477c478bd9Sstevel@tonic-gate static	boolean_t	Sflag = B_FALSE;	/* Per-protocol Statistics */
2487c478bd9Sstevel@tonic-gate static	boolean_t	Vflag = B_FALSE;	/* Verbose */
24978a2e113SAndy Fiddaman static	boolean_t	Uflag = B_FALSE;	/* Show PID and UID info. */
2507c478bd9Sstevel@tonic-gate static	boolean_t	Pflag = B_FALSE;	/* Net to Media Tables */
2517c478bd9Sstevel@tonic-gate static	boolean_t	Gflag = B_FALSE;	/* Multicast group membership */
2527c478bd9Sstevel@tonic-gate static	boolean_t	MMflag = B_FALSE;	/* Multicast routing table */
2537c478bd9Sstevel@tonic-gate static	boolean_t	DHCPflag = B_FALSE;	/* DHCP statistics */
254bd670b35SErik Nordmark static	boolean_t	Xflag = B_FALSE;	/* Debug Info */
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate static	int	v4compat = 0;	/* Compatible printing format for status */
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate static int	proto = IPPROTO_MAX;	/* all protocols */
2597c478bd9Sstevel@tonic-gate kstat_ctl_t	*kc = NULL;
2607c478bd9Sstevel@tonic-gate 
261afee3dc6SRobert Mustacchi /*
262afee3dc6SRobert Mustacchi  * Name service timeout detection constants.
263afee3dc6SRobert Mustacchi  */
264afee3dc6SRobert Mustacchi static mutex_t ns_lock = ERRORCHECKMUTEX;
265afee3dc6SRobert Mustacchi static boolean_t ns_active = B_FALSE;	/* Is a lookup ongoing? */
266afee3dc6SRobert Mustacchi static hrtime_t ns_starttime;		/* Time the lookup started */
267afee3dc6SRobert Mustacchi static int ns_sleeptime = 2;		/* Time in seconds between checks */
268afee3dc6SRobert Mustacchi static int ns_warntime = 2;		/* Time in seconds before warning */
269afee3dc6SRobert Mustacchi 
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate  * Sizes of data structures extracted from the base mib.
2727c478bd9Sstevel@tonic-gate  * This allows the size of the tables entries to grow while preserving
2737c478bd9Sstevel@tonic-gate  * binary compatibility.
2747c478bd9Sstevel@tonic-gate  */
2757c478bd9Sstevel@tonic-gate static int ipAddrEntrySize;
2767c478bd9Sstevel@tonic-gate static int ipRouteEntrySize;
2777c478bd9Sstevel@tonic-gate static int ipNetToMediaEntrySize;
2787c478bd9Sstevel@tonic-gate static int ipMemberEntrySize;
2797c478bd9Sstevel@tonic-gate static int ipGroupSourceEntrySize;
28045916cd2Sjpk static int ipRouteAttributeSize;
2817c478bd9Sstevel@tonic-gate static int vifctlSize;
2827c478bd9Sstevel@tonic-gate static int mfcctlSize;
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate static int ipv6IfStatsEntrySize;
2857c478bd9Sstevel@tonic-gate static int ipv6IfIcmpEntrySize;
2867c478bd9Sstevel@tonic-gate static int ipv6AddrEntrySize;
2877c478bd9Sstevel@tonic-gate static int ipv6RouteEntrySize;
2887c478bd9Sstevel@tonic-gate static int ipv6NetToMediaEntrySize;
2897c478bd9Sstevel@tonic-gate static int ipv6MemberEntrySize;
2907c478bd9Sstevel@tonic-gate static int ipv6GroupSourceEntrySize;
2917c478bd9Sstevel@tonic-gate 
292bd670b35SErik Nordmark static int ipDestEntrySize;
293bd670b35SErik Nordmark 
29445916cd2Sjpk static int transportMLPSize;
2957c478bd9Sstevel@tonic-gate static int tcpConnEntrySize;
2967c478bd9Sstevel@tonic-gate static int tcp6ConnEntrySize;
2977c478bd9Sstevel@tonic-gate static int udpEntrySize;
2987c478bd9Sstevel@tonic-gate static int udp6EntrySize;
2997c478bd9Sstevel@tonic-gate static int sctpEntrySize;
3007c478bd9Sstevel@tonic-gate static int sctpLocalEntrySize;
3017c478bd9Sstevel@tonic-gate static int sctpRemoteEntrySize;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #define	protocol_selected(p)	(proto == IPPROTO_MAX || proto == (p))
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate /* Machinery used for -f (filter) option */
3065c0b7edeSseb enum { FK_AF = 0, FK_OUTIF, FK_DST, FK_FLAGS, NFILTERKEYS };
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate static const char *filter_keys[NFILTERKEYS] = {
3095c0b7edeSseb 	"af", "outif", "dst", "flags"
3107c478bd9Sstevel@tonic-gate };
3117c478bd9Sstevel@tonic-gate 
3125f9878b0Sken Powell - Sun Microsystem static m_label_t *zone_security_label = NULL;
3135f9878b0Sken Powell - Sun Microsystem 
3147c478bd9Sstevel@tonic-gate /* Flags on routes */
3157c478bd9Sstevel@tonic-gate #define	FLF_A		0x00000001
316bd670b35SErik Nordmark #define	FLF_b		0x00000002
3177c478bd9Sstevel@tonic-gate #define	FLF_D		0x00000004
3187c478bd9Sstevel@tonic-gate #define	FLF_G		0x00000008
3197c478bd9Sstevel@tonic-gate #define	FLF_H		0x00000010
3207c478bd9Sstevel@tonic-gate #define	FLF_L		0x00000020
3217c478bd9Sstevel@tonic-gate #define	FLF_U		0x00000040
3227c478bd9Sstevel@tonic-gate #define	FLF_M		0x00000080
3237c478bd9Sstevel@tonic-gate #define	FLF_S		0x00000100
324bd670b35SErik Nordmark #define	FLF_C		0x00000200	/* IRE_IF_CLONE */
325bd670b35SErik Nordmark #define	FLF_I		0x00000400	/* RTF_INDIRECT */
326bd670b35SErik Nordmark #define	FLF_R		0x00000800	/* RTF_REJECT */
327bd670b35SErik Nordmark #define	FLF_B		0x00001000	/* RTF_BLACKHOLE */
328550b6e40SSowmini Varadhan #define	FLF_Z		0x00100000	/* RTF_ZONE */
329bd670b35SErik Nordmark 
330550b6e40SSowmini Varadhan static const char flag_list[] = "AbDGHLUMSCIRBZ";
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate typedef struct filter_rule filter_t;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate struct filter_rule {
3357c478bd9Sstevel@tonic-gate 	filter_t *f_next;
3367c478bd9Sstevel@tonic-gate 	union {
3377c478bd9Sstevel@tonic-gate 		int f_family;
3387c478bd9Sstevel@tonic-gate 		const char *f_ifname;
3397c478bd9Sstevel@tonic-gate 		struct {
3407c478bd9Sstevel@tonic-gate 			struct hostent *f_address;
3417c478bd9Sstevel@tonic-gate 			in6_addr_t f_mask;
3427c478bd9Sstevel@tonic-gate 		} a;
3437c478bd9Sstevel@tonic-gate 		struct {
3447c478bd9Sstevel@tonic-gate 			uint_t f_flagset;
3457c478bd9Sstevel@tonic-gate 			uint_t f_flagclear;
3467c478bd9Sstevel@tonic-gate 		} f;
3477c478bd9Sstevel@tonic-gate 	} u;
3487c478bd9Sstevel@tonic-gate };
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate  * The user-specified filters are linked into lists separated by
3527c478bd9Sstevel@tonic-gate  * keyword (type of filter).  Thus, the matching algorithm is:
3537c478bd9Sstevel@tonic-gate  *	For each non-empty filter list
3547c478bd9Sstevel@tonic-gate  *		If no filters in the list match
3557c478bd9Sstevel@tonic-gate  *			then stop here; route doesn't match
3567c478bd9Sstevel@tonic-gate  *	If loop above completes, then route does match and will be
3577c478bd9Sstevel@tonic-gate  *	displayed.
3587c478bd9Sstevel@tonic-gate  */
3597c478bd9Sstevel@tonic-gate static filter_t *filters[NFILTERKEYS];
3607c478bd9Sstevel@tonic-gate 
36126fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE;
36226fd7700SKrishnendu Sadhukhan - Sun Microsystems 
36326fd7700SKrishnendu Sadhukhan - Sun Microsystems #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
36426fd7700SKrishnendu Sadhukhan - Sun Microsystems #define	TEXT_DOMAIN "SYS_TEST"		/* Use this only if it isn't */
36526fd7700SKrishnendu Sadhukhan - Sun Microsystems #endif
36626fd7700SKrishnendu Sadhukhan - Sun Microsystems 
367afee3dc6SRobert Mustacchi static void
ns_lookup_start(void)368afee3dc6SRobert Mustacchi ns_lookup_start(void)
369afee3dc6SRobert Mustacchi {
370afee3dc6SRobert Mustacchi 	mutex_enter(&ns_lock);
371afee3dc6SRobert Mustacchi 	ns_active = B_TRUE;
372afee3dc6SRobert Mustacchi 	ns_starttime = gethrtime();
373afee3dc6SRobert Mustacchi 	mutex_exit(&ns_lock);
374afee3dc6SRobert Mustacchi }
375afee3dc6SRobert Mustacchi 
376afee3dc6SRobert Mustacchi static void
ns_lookup_end(void)377afee3dc6SRobert Mustacchi ns_lookup_end(void)
378afee3dc6SRobert Mustacchi {
379afee3dc6SRobert Mustacchi 	mutex_enter(&ns_lock);
380afee3dc6SRobert Mustacchi 	ns_active = B_FALSE;
381afee3dc6SRobert Mustacchi 	mutex_exit(&ns_lock);
382afee3dc6SRobert Mustacchi }
383afee3dc6SRobert Mustacchi 
384afee3dc6SRobert Mustacchi /*
385afee3dc6SRobert Mustacchi  * When name services are not functioning, this program appears to hang to the
386afee3dc6SRobert Mustacchi  * user. To try and give the user a chance of figuring out that this might be
387afee3dc6SRobert Mustacchi  * the case, we end up warning them and suggest that they may want to use the -n
388afee3dc6SRobert Mustacchi  * flag.
389afee3dc6SRobert Mustacchi  */
390afee3dc6SRobert Mustacchi /* ARGSUSED */
391afee3dc6SRobert Mustacchi static void *
ns_warning_thr(void * unsued)392afee3dc6SRobert Mustacchi ns_warning_thr(void *unsued)
393afee3dc6SRobert Mustacchi {
394afee3dc6SRobert Mustacchi 	for (;;) {
395afee3dc6SRobert Mustacchi 		hrtime_t now;
396afee3dc6SRobert Mustacchi 
397afee3dc6SRobert Mustacchi 		(void) sleep(ns_sleeptime);
398afee3dc6SRobert Mustacchi 		now = gethrtime();
399afee3dc6SRobert Mustacchi 		mutex_enter(&ns_lock);
400afee3dc6SRobert Mustacchi 		if (ns_active && now - ns_starttime >= ns_warntime * NANOSEC) {
401afee3dc6SRobert Mustacchi 			(void) fprintf(stderr, "warning: data "
402afee3dc6SRobert Mustacchi 			    "available, but name service lookups are "
403afee3dc6SRobert Mustacchi 			    "taking a while. Use the -n option to "
404afee3dc6SRobert Mustacchi 			    "disable name service lookups.\n");
405afee3dc6SRobert Mustacchi 			mutex_exit(&ns_lock);
406afee3dc6SRobert Mustacchi 			return (NULL);
407afee3dc6SRobert Mustacchi 		}
408afee3dc6SRobert Mustacchi 		mutex_exit(&ns_lock);
409afee3dc6SRobert Mustacchi 	}
410afee3dc6SRobert Mustacchi 
411afee3dc6SRobert Mustacchi 	return (NULL);
412afee3dc6SRobert Mustacchi }
413afee3dc6SRobert Mustacchi 
4147c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)4157c478bd9Sstevel@tonic-gate main(int argc, char **argv)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate 	char		*name;
4187c478bd9Sstevel@tonic-gate 	mib_item_t	*item = NULL;
4197c478bd9Sstevel@tonic-gate 	mib_item_t	*previtem = NULL;
4207c478bd9Sstevel@tonic-gate 	int		sd = -1;
4217c478bd9Sstevel@tonic-gate 	char	*ifname = NULL;
4227c478bd9Sstevel@tonic-gate 	int	interval = 0;	/* Single time by default */
4237c478bd9Sstevel@tonic-gate 	int	count = -1;	/* Forever */
4247c478bd9Sstevel@tonic-gate 	int	c;
4257c478bd9Sstevel@tonic-gate 	int	d;
4267c478bd9Sstevel@tonic-gate 	/*
4277c478bd9Sstevel@tonic-gate 	 * Possible values of 'Iflag_only':
4287c478bd9Sstevel@tonic-gate 	 * -1, no feature-flags;
4297c478bd9Sstevel@tonic-gate 	 *  0, IFlag and other feature-flags enabled
4307c478bd9Sstevel@tonic-gate 	 *  1, IFlag is the only feature-flag enabled
4317c478bd9Sstevel@tonic-gate 	 * : trinary variable, modified using IFLAGMOD()
4327c478bd9Sstevel@tonic-gate 	 */
4337c478bd9Sstevel@tonic-gate 	int Iflag_only = -1;
4347c478bd9Sstevel@tonic-gate 	boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
4357c478bd9Sstevel@tonic-gate 	extern char	*optarg;
4367c478bd9Sstevel@tonic-gate 	extern int	optind;
4377c478bd9Sstevel@tonic-gate 	char *default_ip_str = NULL;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	name = argv[0];
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	v4compat = get_compat_flag(&default_ip_str);
4427c478bd9Sstevel@tonic-gate 	if (v4compat == DEFAULT_PROT_BAD_VALUE)
4437c478bd9Sstevel@tonic-gate 		fatal(2, "%s: %s: Bad value for %s in %s\n", name,
4447c478bd9Sstevel@tonic-gate 		    default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
4457c478bd9Sstevel@tonic-gate 	free(default_ip_str);
4467c478bd9Sstevel@tonic-gate 
44726fd7700SKrishnendu Sadhukhan - Sun Microsystems 	(void) setlocale(LC_ALL, "");
44826fd7700SKrishnendu Sadhukhan - Sun Microsystems 	(void) textdomain(TEXT_DOMAIN);
44926fd7700SKrishnendu Sadhukhan - Sun Microsystems 
45078a2e113SAndy Fiddaman 	while ((c = getopt(argc, argv, "acdimnrspMguvxf:P:I:DRT:")) != -1) {
4517c478bd9Sstevel@tonic-gate 		switch ((char)c) {
4527c478bd9Sstevel@tonic-gate 		case 'a':		/* all connections */
4537c478bd9Sstevel@tonic-gate 			Aflag = B_TRUE;
4547c478bd9Sstevel@tonic-gate 			break;
4557c478bd9Sstevel@tonic-gate 
456d38b7101SDan McDonald 		case 'c':
457d38b7101SDan McDonald 			CIDRflag = B_TRUE;
458d38b7101SDan McDonald 			break;
459d38b7101SDan McDonald 
460bd670b35SErik Nordmark 		case 'd':		/* DCE info */
4617c478bd9Sstevel@tonic-gate 			Dflag = B_TRUE;
462bd670b35SErik Nordmark 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
4637c478bd9Sstevel@tonic-gate 			break;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		case 'i':		/* interface (ill/ipif report) */
4667c478bd9Sstevel@tonic-gate 			Iflag = B_TRUE;
4677c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
4687c478bd9Sstevel@tonic-gate 			break;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		case 'm':		/* streams msg report */
4717c478bd9Sstevel@tonic-gate 			Mflag = B_TRUE;
4727c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
4737c478bd9Sstevel@tonic-gate 			break;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		case 'n':		/* numeric format */
4767c478bd9Sstevel@tonic-gate 			Nflag = B_TRUE;
4777c478bd9Sstevel@tonic-gate 			break;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 		case 'r':		/* route tables */
4807c478bd9Sstevel@tonic-gate 			Rflag = B_TRUE;
4817c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
4827c478bd9Sstevel@tonic-gate 			break;
4837c478bd9Sstevel@tonic-gate 
48445916cd2Sjpk 		case 'R':		/* security attributes */
48545916cd2Sjpk 			RSECflag = B_TRUE;
48645916cd2Sjpk 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
48745916cd2Sjpk 			break;
48845916cd2Sjpk 
4897c478bd9Sstevel@tonic-gate 		case 's':		/* per-protocol statistics */
4907c478bd9Sstevel@tonic-gate 			Sflag = B_TRUE;
4917c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
4927c478bd9Sstevel@tonic-gate 			break;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 		case 'p':		/* arp/ndp table */
4957c478bd9Sstevel@tonic-gate 			Pflag = B_TRUE;
4967c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
4977c478bd9Sstevel@tonic-gate 			break;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 		case 'M':		/* multicast routing tables */
5007c478bd9Sstevel@tonic-gate 			MMflag = B_TRUE;
5017c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
5027c478bd9Sstevel@tonic-gate 			break;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 		case 'g':		/* multicast group membership */
5057c478bd9Sstevel@tonic-gate 			Gflag = B_TRUE;
5067c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
5077c478bd9Sstevel@tonic-gate 			break;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 		case 'v':		/* verbose output format */
5107c478bd9Sstevel@tonic-gate 			Vflag = B_TRUE;
5117c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
5127c478bd9Sstevel@tonic-gate 			break;
5137c478bd9Sstevel@tonic-gate 
51478a2e113SAndy Fiddaman 		case 'u':		/* show pid and uid information */
51578a2e113SAndy Fiddaman 			Uflag = B_TRUE;
51678a2e113SAndy Fiddaman 			break;
51778a2e113SAndy Fiddaman 
518bd670b35SErik Nordmark 		case 'x':		/* turn on debugging */
519bd670b35SErik Nordmark 			Xflag = B_TRUE;
520bd670b35SErik Nordmark 			break;
521bd670b35SErik Nordmark 
5227c478bd9Sstevel@tonic-gate 		case 'f':
5237c478bd9Sstevel@tonic-gate 			process_filter(optarg);
5247c478bd9Sstevel@tonic-gate 			break;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		case 'P':
5277c478bd9Sstevel@tonic-gate 			if (strcmp(optarg, "ip") == 0) {
5287c478bd9Sstevel@tonic-gate 				proto = IPPROTO_IP;
5297c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "ipv6") == 0 ||
5307c478bd9Sstevel@tonic-gate 			    strcmp(optarg, "ip6") == 0) {
5317c478bd9Sstevel@tonic-gate 				v4compat = 0;	/* Overridden */
5327c478bd9Sstevel@tonic-gate 				proto = IPPROTO_IPV6;
5337c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "icmp") == 0) {
5347c478bd9Sstevel@tonic-gate 				proto = IPPROTO_ICMP;
5357c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "icmpv6") == 0 ||
5367c478bd9Sstevel@tonic-gate 			    strcmp(optarg, "icmp6") == 0) {
5377c478bd9Sstevel@tonic-gate 				v4compat = 0;	/* Overridden */
5387c478bd9Sstevel@tonic-gate 				proto = IPPROTO_ICMPV6;
5397c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "igmp") == 0) {
5407c478bd9Sstevel@tonic-gate 				proto = IPPROTO_IGMP;
5417c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "udp") == 0) {
5427c478bd9Sstevel@tonic-gate 				proto = IPPROTO_UDP;
5437c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "tcp") == 0) {
5447c478bd9Sstevel@tonic-gate 				proto = IPPROTO_TCP;
5457c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "sctp") == 0) {
5467c478bd9Sstevel@tonic-gate 				proto = IPPROTO_SCTP;
5477c478bd9Sstevel@tonic-gate 			} else if (strcmp(optarg, "raw") == 0 ||
5487c478bd9Sstevel@tonic-gate 			    strcmp(optarg, "rawip") == 0) {
5497c478bd9Sstevel@tonic-gate 				proto = IPPROTO_RAW;
5507c478bd9Sstevel@tonic-gate 			} else {
5517c478bd9Sstevel@tonic-gate 				fatal(1, "%s: unknown protocol.\n", optarg);
5527c478bd9Sstevel@tonic-gate 			}
5537c478bd9Sstevel@tonic-gate 			break;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 		case 'I':
5567c478bd9Sstevel@tonic-gate 			ifname = optarg;
5577c478bd9Sstevel@tonic-gate 			Iflag = B_TRUE;
5587c478bd9Sstevel@tonic-gate 			IFLAGMOD(Iflag_only, -1, 1); /* see macro def'n */
5597c478bd9Sstevel@tonic-gate 			break;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		case 'D':
5627c478bd9Sstevel@tonic-gate 			DHCPflag = B_TRUE;
5637c478bd9Sstevel@tonic-gate 			Iflag_only = 0;
5647c478bd9Sstevel@tonic-gate 			break;
5657c478bd9Sstevel@tonic-gate 
56626fd7700SKrishnendu Sadhukhan - Sun Microsystems 		case 'T':
56726fd7700SKrishnendu Sadhukhan - Sun Microsystems 			if (optarg) {
56826fd7700SKrishnendu Sadhukhan - Sun Microsystems 				if (*optarg == 'u')
56926fd7700SKrishnendu Sadhukhan - Sun Microsystems 					timestamp_fmt = UDATE;
57026fd7700SKrishnendu Sadhukhan - Sun Microsystems 				else if (*optarg == 'd')
57126fd7700SKrishnendu Sadhukhan - Sun Microsystems 					timestamp_fmt = DDATE;
57226fd7700SKrishnendu Sadhukhan - Sun Microsystems 				else
57326fd7700SKrishnendu Sadhukhan - Sun Microsystems 					usage(name);
57426fd7700SKrishnendu Sadhukhan - Sun Microsystems 			} else {
57526fd7700SKrishnendu Sadhukhan - Sun Microsystems 				usage(name);
57626fd7700SKrishnendu Sadhukhan - Sun Microsystems 			}
57726fd7700SKrishnendu Sadhukhan - Sun Microsystems 			break;
57826fd7700SKrishnendu Sadhukhan - Sun Microsystems 
5797c478bd9Sstevel@tonic-gate 		case '?':
5807c478bd9Sstevel@tonic-gate 		default:
5817c478bd9Sstevel@tonic-gate 			usage(name);
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 
58545916cd2Sjpk 	/*
58645916cd2Sjpk 	 * Make sure -R option is set only on a labeled system.
58745916cd2Sjpk 	 */
58845916cd2Sjpk 	if (RSECflag && !is_system_labeled()) {
58945916cd2Sjpk 		(void) fprintf(stderr, "-R set but labeling is not enabled\n");
59045916cd2Sjpk 		usage(name);
59145916cd2Sjpk 	}
59245916cd2Sjpk 
5937c478bd9Sstevel@tonic-gate 	/*
5947c478bd9Sstevel@tonic-gate 	 * Handle other arguments: find interval, count; the
5957c478bd9Sstevel@tonic-gate 	 * flags that accept 'interval' and 'count' are OR'd
5967c478bd9Sstevel@tonic-gate 	 * in the outermost 'if'; more flags may be added as
5977c478bd9Sstevel@tonic-gate 	 * required
5987c478bd9Sstevel@tonic-gate 	 */
5997c478bd9Sstevel@tonic-gate 	if (Iflag || Sflag || Mflag) {
6007c478bd9Sstevel@tonic-gate 		for (d = optind; d < argc; d++) {
6017c478bd9Sstevel@tonic-gate 			if (isnum(argv[d])) {
6027c478bd9Sstevel@tonic-gate 				interval = atoi(argv[d]);
6037c478bd9Sstevel@tonic-gate 				if (d + 1 < argc &&
6047c478bd9Sstevel@tonic-gate 				    isnum(argv[d + 1])) {
6057c478bd9Sstevel@tonic-gate 					count = atoi(argv[d + 1]);
6067c478bd9Sstevel@tonic-gate 					optind++;
607