17c478bd9Sstevel@tonic-gate /*
236b41818SGirish Moodalbail  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
360b43c45SDan McDonald  * Copyright 2012, Daniil Lunev. All rights reserved.
460b43c45SDan McDonald  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
57c478bd9Sstevel@tonic-gate  */
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
97c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #include "defs.h"
137c478bd9Sstevel@tonic-gate #include "strings.h"
147c478bd9Sstevel@tonic-gate #include "ifconfig.h"
157c478bd9Sstevel@tonic-gate #include <compat.h>
167c478bd9Sstevel@tonic-gate #include <libdlpi.h>
17da14cebeSEric Cheng #include <libdllink.h>
182b24ab6bSSebastien Roy #include <libdliptun.h>
192b24ab6bSSebastien Roy #include <libdllink.h>
20ff550d0eSmasputra #include <inet/ip.h>
21d2f8a3dfSpwernau #include <inet/ipsec_impl.h>
226e91bba0SGirish Moodalbail #include <libipadm.h>
236e91bba0SGirish Moodalbail #include <ifaddrs.h>
246e91bba0SGirish Moodalbail #include <libsocket_priv.h>
25ff550d0eSmasputra 
267c478bd9Sstevel@tonic-gate #define	LOOPBACK_IF	"lo0"
277c478bd9Sstevel@tonic-gate #define	NONE_STR	"none"
287c478bd9Sstevel@tonic-gate #define	ARP_MOD_NAME	"arp"
296e91bba0SGirish Moodalbail #define	LIFC_DEFAULT	(LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
306e91bba0SGirish Moodalbail 			LIFC_UNDER_IPMP)
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate typedef struct if_flags {
337c478bd9Sstevel@tonic-gate 	uint64_t iff_value;
347c478bd9Sstevel@tonic-gate 	char	*iff_name;
357c478bd9Sstevel@tonic-gate } if_flags_t;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate static if_flags_t	if_flags_tbl[] = {
387c478bd9Sstevel@tonic-gate 	{ IFF_UP,		"UP" },
397c478bd9Sstevel@tonic-gate 	{ IFF_BROADCAST,	"BROADCAST" },
407c478bd9Sstevel@tonic-gate 	{ IFF_DEBUG,		"DEBUG" },
417c478bd9Sstevel@tonic-gate 	{ IFF_LOOPBACK,		"LOOPBACK" },
427c478bd9Sstevel@tonic-gate 	{ IFF_POINTOPOINT,	"POINTOPOINT" },
437c478bd9Sstevel@tonic-gate 	{ IFF_NOTRAILERS,	"NOTRAILERS" },
447c478bd9Sstevel@tonic-gate 	{ IFF_RUNNING,		"RUNNING" },
457c478bd9Sstevel@tonic-gate 	{ IFF_NOARP,		"NOARP" },
467c478bd9Sstevel@tonic-gate 	{ IFF_PROMISC,		"PROMISC" },
477c478bd9Sstevel@tonic-gate 	{ IFF_ALLMULTI,		"ALLMULTI" },
487c478bd9Sstevel@tonic-gate 	{ IFF_INTELLIGENT,	"INTELLIGENT" },
497c478bd9Sstevel@tonic-gate 	{ IFF_MULTICAST,	"MULTICAST" },
507c478bd9Sstevel@tonic-gate 	{ IFF_MULTI_BCAST,	"MULTI_BCAST" },
517c478bd9Sstevel@tonic-gate 	{ IFF_UNNUMBERED,	"UNNUMBERED" },
527c478bd9Sstevel@tonic-gate 	{ IFF_DHCPRUNNING,	"DHCP" },
537c478bd9Sstevel@tonic-gate 	{ IFF_PRIVATE,		"PRIVATE" },
547c478bd9Sstevel@tonic-gate 	{ IFF_NOXMIT,		"NOXMIT" },
557c478bd9Sstevel@tonic-gate 	{ IFF_NOLOCAL,		"NOLOCAL" },
567c478bd9Sstevel@tonic-gate 	{ IFF_DEPRECATED,	"DEPRECATED" },
577c478bd9Sstevel@tonic-gate 	{ IFF_ADDRCONF,		"ADDRCONF" },
587c478bd9Sstevel@tonic-gate 	{ IFF_ROUTER,		"ROUTER" },
597c478bd9Sstevel@tonic-gate 	{ IFF_NONUD,		"NONUD" },
607c478bd9Sstevel@tonic-gate 	{ IFF_ANYCAST,		"ANYCAST" },
617c478bd9Sstevel@tonic-gate 	{ IFF_NORTEXCH,		"NORTEXCH" },
627c478bd9Sstevel@tonic-gate 	{ IFF_IPV4,		"IPv4" },
637c478bd9Sstevel@tonic-gate 	{ IFF_IPV6,		"IPv6" },
647c478bd9Sstevel@tonic-gate 	{ IFF_NOFAILOVER,	"NOFAILOVER" },
657c478bd9Sstevel@tonic-gate 	{ IFF_FAILED,		"FAILED" },
667c478bd9Sstevel@tonic-gate 	{ IFF_STANDBY,		"STANDBY" },
677c478bd9Sstevel@tonic-gate 	{ IFF_INACTIVE,		"INACTIVE" },
687c478bd9Sstevel@tonic-gate 	{ IFF_OFFLINE,		"OFFLINE" },
697c478bd9Sstevel@tonic-gate 	{ IFF_XRESOLV,		"XRESOLV" },
707c478bd9Sstevel@tonic-gate 	{ IFF_COS_ENABLED,	"CoS" },
717c478bd9Sstevel@tonic-gate 	{ IFF_PREFERRED,	"PREFERRED" },
727c478bd9Sstevel@tonic-gate 	{ IFF_TEMPORARY,	"TEMPORARY" },
737c478bd9Sstevel@tonic-gate 	{ IFF_FIXEDMTU,		"FIXEDMTU" },
7469bb4bb4Scarlsonj 	{ IFF_VIRTUAL,		"VIRTUAL" },
75e11c3f44Smeem 	{ IFF_DUPLICATE,	"DUPLICATE" },
761cb875aeSCathy Zhou 	{ IFF_IPMP,		"IPMP"},
771cb875aeSCathy Zhou 	{ IFF_VRRP,		"VRRP"},
78550b6e40SSowmini Varadhan 	{ IFF_NOACCEPT,		"NOACCEPT"},
79550b6e40SSowmini Varadhan 	{ IFF_L3PROTECT,	"L3PROTECT"}
80e11c3f44Smeem };
81e11c3f44Smeem 
82e11c3f44Smeem typedef struct {
83e11c3f44Smeem 	const char		*ia_app;
84e11c3f44Smeem 	uint64_t		ia_flag;
85e11c3f44Smeem 	uint_t			ia_tries;
86e11c3f44Smeem } if_appflags_t;
87e11c3f44Smeem 
88e11c3f44Smeem static const if_appflags_t if_appflags_tbl[] = {
89e11c3f44Smeem 	{ "dhcpagent(1M)",	IFF_DHCPRUNNING,	1 },
90e11c3f44Smeem 	{ "in.ndpd(1M)",	IFF_ADDRCONF,		3 },
91e11c3f44Smeem 	{  NULL,		0,			0 }
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate 
942b24ab6bSSebastien Roy static dladm_handle_t	dlh;
952b24ab6bSSebastien Roy boolean_t		dlh_opened;
962b24ab6bSSebastien Roy static struct		lifreq lifr;
977906a3e0Smeem /* current interface name a particular function is accessing */
982b24ab6bSSebastien Roy static char		name[LIFNAMSIZ];
997c478bd9Sstevel@tonic-gate /* foreach interface saved name */
1002b24ab6bSSebastien Roy static char		origname[LIFNAMSIZ];
1012b24ab6bSSebastien Roy static int		setaddr;
1026e91bba0SGirish Moodalbail static boolean_t	setaddr_done = _B_FALSE;
1032b24ab6bSSebastien Roy static boolean_t	ipsec_policy_set;
1042b24ab6bSSebastien Roy static boolean_t	ipsec_auth_covered;
1056e91bba0SGirish Moodalbail static ipadm_handle_t	iph;
1066e91bba0SGirish Moodalbail static ipadm_addrobj_t	ipaddr;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * Make sure the algorithm variables hold more than the sizeof an algorithm
1107c478bd9Sstevel@tonic-gate  * in PF_KEY.  (For now, more than a uint8_t.)  The NO_***_?ALG indicates that
1117c478bd9Sstevel@tonic-gate  * there was no algorithm requested, and in the ipsec_req that service should
1127c478bd9Sstevel@tonic-gate  * be disabled.  (E.g. if ah_aalg remains NO_AH_AALG, then AH will be
1137c478bd9Sstevel@tonic-gate  * disabled on that tunnel.)
1147c478bd9Sstevel@tonic-gate  */
1157c478bd9Sstevel@tonic-gate #define	NO_AH_AALG 256
1167c478bd9Sstevel@tonic-gate #define	NO_ESP_AALG 256
1177c478bd9Sstevel@tonic-gate #define	NO_ESP_EALG 256
1187c478bd9Sstevel@tonic-gate 
119e11c3f44Smeem int	s, s4, s6;
1207c478bd9Sstevel@tonic-gate int	af = AF_INET;	/* default address family */
1217c478bd9Sstevel@tonic-gate int	debug = 0;
1227c478bd9Sstevel@tonic-gate int	all = 0;	/* setifdhcp() needs to know this */
1237c478bd9Sstevel@tonic-gate int	verbose = 0;
1247c478bd9Sstevel@tonic-gate int	v4compat = 0;	/* Compatible printing format */
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate  * Function prototypes for command functions.
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate static int	addif(char *arg, int64_t param);
130e11c3f44Smeem static int	inetipmp(char *arg, int64_t param);
1317c478bd9Sstevel@tonic-gate static int	inetplumb(char *arg, int64_t param);
1327c478bd9Sstevel@tonic-gate static int	inetunplumb(char *arg, int64_t param);
1337c478bd9Sstevel@tonic-gate static int	removeif(char *arg, int64_t param);
1347c478bd9Sstevel@tonic-gate static int	setdebugflag(char *arg, int64_t param);
1357c478bd9Sstevel@tonic-gate static int	setifaddr(char *arg, int64_t param);
1367c478bd9Sstevel@tonic-gate static int	setifbroadaddr(char *arg, int64_t param);
1377c478bd9Sstevel@tonic-gate static int	setifdstaddr(char *arg, int64_t param);
1387c478bd9Sstevel@tonic-gate static int	setifether(char *arg, int64_t param);
1397c478bd9Sstevel@tonic-gate static int	setifflags(char *arg, int64_t param);
1407c478bd9Sstevel@tonic-gate static int	setifindex(char *arg, int64_t param);
1417c478bd9Sstevel@tonic-gate static int	setifmetric(char *arg, int64_t param);
1427c478bd9Sstevel@tonic-gate static int	setifmtu(char *arg, int64_t param);
1437c478bd9Sstevel@tonic-gate static int	setifnetmask(char *arg, int64_t param);
1447c478bd9Sstevel@tonic-gate static int	setifprefixlen(char *arg, int64_t param);
1457c478bd9Sstevel@tonic-gate static int	setifrevarp(char *arg, int64_t param);
1467c478bd9Sstevel@tonic-gate static int	setifsubnet(char *arg, int64_t param);
1477c478bd9Sstevel@tonic-gate static int	setiftdst(char *arg, int64_t param);
1487c478bd9Sstevel@tonic-gate static int	setiftoken(char *arg, int64_t param);
1497c478bd9Sstevel@tonic-gate static int	setiftsrc(char *arg, int64_t param);
1507c478bd9Sstevel@tonic-gate static int	setverboseflag(char *arg, int64_t param);
1517c478bd9Sstevel@tonic-gate static int	set_tun_ah_alg(char *arg, int64_t param);
1527c478bd9Sstevel@tonic-gate static int	set_tun_esp_auth_alg(char *arg, int64_t param);
1537c478bd9Sstevel@tonic-gate static int	set_tun_esp_encr_alg(char *arg, int64_t param);
1547c478bd9Sstevel@tonic-gate static int	modlist(char *arg, int64_t param);
1557c478bd9Sstevel@tonic-gate static int	modinsert(char *arg, int64_t param);
1567c478bd9Sstevel@tonic-gate static int	modremove(char *arg, int64_t param);
1577c478bd9Sstevel@tonic-gate static int	setifgroupname(char *arg, int64_t param);
1587c478bd9Sstevel@tonic-gate static int	configinfo(char *arg, int64_t param);
159e11c3f44Smeem static void	print_config_flags(int af, uint64_t flags);
1607c478bd9Sstevel@tonic-gate static void	print_flags(uint64_t flags);
1616e91bba0SGirish Moodalbail static void	print_ifether(const char *ifname);
1627c478bd9Sstevel@tonic-gate static int	set_tun_encap_limit(char *arg, int64_t param);
1637c478bd9Sstevel@tonic-gate static int	clr_tun_encap_limit(char *arg, int64_t param);
1647c478bd9Sstevel@tonic-gate static int	set_tun_hop_limit(char *arg, int64_t param);
1657c478bd9Sstevel@tonic-gate static int	setzone(char *arg, int64_t param);
16645916cd2Sjpk static int	setallzones(char *arg, int64_t param);
1677c478bd9Sstevel@tonic-gate static int	setifsrc(char *arg, int64_t param);
168e11c3f44Smeem static int	lifnum(const char *ifname);
1696e91bba0SGirish Moodalbail static void	plumball(int, char **, int64_t, int64_t, int64_t);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Address family specific function prototypes.
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate static void	in_getaddr(char *s, struct sockaddr *saddr, int *plenp);
1757c478bd9Sstevel@tonic-gate static void	in_status(int force, uint64_t flags);
1767c478bd9Sstevel@tonic-gate static void	in_configinfo(int force, uint64_t flags);
1777c478bd9Sstevel@tonic-gate static void	in6_getaddr(char *s, struct sockaddr *saddr, int *plenp);
1787c478bd9Sstevel@tonic-gate static void	in6_status(int force, uint64_t flags);
1797c478bd9Sstevel@tonic-gate static void	in6_configinfo(int force, uint64_t flags);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate  * Misc support functions
1837c478bd9Sstevel@tonic-gate  */
184d62bc4baSyz static boolean_t	ni_entry(const char *, void *);
1856e91bba0SGirish Moodalbail static void		foreachinterface(int argc, char *argv[],
1866e91bba0SGirish Moodalbail 			    int af, int64_t onflags, int64_t offflags,
1876e91bba0SGirish Moodalbail 			    int64_t lifc_flags);
1886e91bba0SGirish Moodalbail static void		ifconfig(int argc, char *argv[], int af,
1896e91bba0SGirish Moodalbail 			    struct ifaddrs *ifa);
190dd7a6f5fSkcpoon static boolean_t	in_getmask(struct sockaddr_in *saddr,
191dd7a6f5fSkcpoon 			    boolean_t addr_set);
1926e91bba0SGirish Moodalbail static int		in_getprefixlen(char *addr, boolean_t slash, int plen);
1937c478bd9Sstevel@tonic-gate static boolean_t	in_prefixlentomask(int prefixlen, int maxlen,
1947c478bd9Sstevel@tonic-gate 			    uchar_t *mask);
1956e91bba0SGirish Moodalbail static void		status(void);
1966e91bba0SGirish Moodalbail static void		ifstatus(const char *ifname);
1976e91bba0SGirish Moodalbail static void		tun_status(datalink_id_t);
1986e91bba0SGirish Moodalbail static void		usage(void);
1996e91bba0SGirish Moodalbail static int		setifdhcp(const char *caller, const char *ifname,
2006e91bba0SGirish Moodalbail 			    int argc, char *argv[]);
2016e91bba0SGirish Moodalbail static int		ip_domux2fd(int *, int *, int *, int *, int *);
2026e91bba0SGirish Moodalbail static int		ip_plink(int, int, int, int, int);
2036e91bba0SGirish Moodalbail static int		modop(char *arg, char op);
2046e91bba0SGirish Moodalbail static int		find_all_interfaces(struct lifconf *lifcp, char **buf,
2056e91bba0SGirish Moodalbail 			    int64_t lifc_flags);
2066e91bba0SGirish Moodalbail static int		create_ipmp(const char *grname, int af,
2076e91bba0SGirish Moodalbail 			    const char *ifname, boolean_t implicit);
2086e91bba0SGirish Moodalbail static void		start_ipmp_daemon(void);
2096e91bba0SGirish Moodalbail static boolean_t 	ifaddr_up(ifaddrlistx_t *ifaddrp);
2106e91bba0SGirish Moodalbail static boolean_t 	ifaddr_down(ifaddrlistx_t *ifaddrp);
2112b24ab6bSSebastien Roy static dladm_status_t	ifconfig_dladm_open(const char *, datalink_class_t,
2126e91bba0SGirish Moodalbail 			    datalink_id_t *);
2136e91bba0SGirish Moodalbail static void		dladmerr_exit(dladm_status_t status, const char *str);
2146e91bba0SGirish Moodalbail static void		ipadmerr_exit(ipadm_status_t status, const char *str);
2156e91bba0SGirish Moodalbail static boolean_t	ifconfig_use_libipadm(int, const char *);
216*f13c98b8SToomas Soome void			Perror0_exit(const char *cmd) __NORETURN;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate #define	max(a, b)	((a) < (b) ? (b) : (a))
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate  * DHCP_EXIT_IF_FAILURE indicates that the operation failed, but if there
2227c478bd9Sstevel@tonic-gate  * are more interfaces to act on (i.e., ifconfig was invoked with -a), keep
2237c478bd9Sstevel@tonic-gate  * on going rather than exit with an error.
2247c478bd9Sstevel@tonic-gate  */
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate #define	DHCP_EXIT_IF_FAILURE	-1
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate #define	NEXTARG		0xffffff	/* command takes an argument */
2297c478bd9Sstevel@tonic-gate #define	OPTARG		0xfffffe 	/* command takes an optional argument */
2307c478bd9Sstevel@tonic-gate #define	AF_ANY		(-1)
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate /* Refer to the comments in ifconfig() on the netmask "hack" */
2337c478bd9Sstevel@tonic-gate #define	NETMASK_CMD	"netmask"
2347c478bd9Sstevel@tonic-gate struct sockaddr_storage	g_netmask;
235dd7a6f5fSkcpoon enum { G_NETMASK_NIL, G_NETMASK_PENDING, G_NETMASK_SET }
236dd7a6f5fSkcpoon     g_netmask_set = G_NETMASK_NIL;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate struct	cmd {
2397c478bd9Sstevel@tonic-gate 	char		*c_name;
2407c478bd9Sstevel@tonic-gate 	int64_t		c_parameter;	/* NEXTARG means next argv */
2417c478bd9Sstevel@tonic-gate 	int		(*c_func)(char *, int64_t);
2427c478bd9Sstevel@tonic-gate 	int		c_abortonfail;	/* don't continue parsing args */
2437c478bd9Sstevel@tonic-gate 					/* for the current interface */
2447c478bd9Sstevel@tonic-gate 	int	c_af;			/* address family restrictions */
2457c478bd9Sstevel@tonic-gate } cmds[] = {
2467c478bd9Sstevel@tonic-gate 	{ "up",		IFF_UP,		setifflags,	0,	AF_ANY },
2477c478bd9Sstevel@tonic-gate 	{ "down",	-IFF_UP,	setifflags,	0,	AF_ANY },
2487c478bd9Sstevel@tonic-gate 	{ "trailers",	-IFF_NOTRAILERS, setifflags,	0,	AF_ANY },
2497c478bd9Sstevel@tonic-gate 	{ "-trailers",	IFF_NOTRAILERS,	setifflags,	0,	AF_ANY },
2507c478bd9Sstevel@tonic-gate 	{ "arp",	-IFF_NOARP,	setifflags,	0,	AF_INET },
2517c478bd9Sstevel@tonic-gate 	{ "-arp",	IFF_NOARP,	setifflags,	0,	AF_INET },
2527c478bd9Sstevel@tonic-gate 	{ "router",	IFF_ROUTER,	setifflags,	0,	AF_ANY },
2537c478bd9Sstevel@tonic-gate 	{ "-router",	-IFF_ROUTER,	setifflags,	0,	AF_ANY },
2547c478bd9Sstevel@tonic-gate 	{ "private",	IFF_PRIVATE,	setifflags,	0,	AF_ANY },
2557c478bd9Sstevel@tonic-gate 	{ "-private",	-IFF_PRIVATE,	setifflags,	0,	AF_ANY },
2567c478bd9Sstevel@tonic-gate 	{ "xmit",	-IFF_NOXMIT,	setifflags,	0,	AF_ANY },
2577c478bd9Sstevel@tonic-gate 	{ "-xmit",	IFF_NOXMIT,	setifflags,	0,	AF_ANY },
2587c478bd9Sstevel@tonic-gate 	{ "-nud",	IFF_NONUD,	setifflags,	0,	AF_INET6 },
2597c478bd9Sstevel@tonic-gate 	{ "nud",	-IFF_NONUD,	setifflags,	0,	AF_INET6 },
2607c478bd9Sstevel@tonic-gate 	{ "anycast",	IFF_ANYCAST,	setifflags,	0,	AF_ANY },
2617c478bd9Sstevel@tonic-gate 	{ "-anycast",	-IFF_ANYCAST,	setifflags,	0,	AF_ANY },
2627c478bd9Sstevel@tonic-gate 	{ "local",	-IFF_NOLOCAL,	setifflags,	0,	AF_ANY },
2637c478bd9Sstevel@tonic-gate 	{ "-local",	IFF_NOLOCAL,	setifflags,	0,	AF_ANY },
2647c478bd9Sstevel@tonic-gate 	{ "deprecated",	IFF_DEPRECATED,	setifflags,	0,	AF_ANY },
2657c478bd9Sstevel@tonic-gate 	{ "-deprecated", -IFF_DEPRECATED, setifflags,	0,	AF_ANY },
2667c478bd9Sstevel@tonic-gate 	{ "preferred",	IFF_PREFERRED,	setifflags,	0,	AF_INET6 },
2677c478bd9Sstevel@tonic-gate 	{ "-preferred",	-IFF_PREFERRED,	setifflags,	0,	AF_INET6 },
2687c478bd9Sstevel@tonic-gate 	{ "debug",	0,		setdebugflag,	0,	AF_ANY },
2697c478bd9Sstevel@tonic-gate 	{ "verbose",	0,		setverboseflag,	0,	AF_ANY },
2707c478bd9Sstevel@tonic-gate 	{ NETMASK_CMD,	NEXTARG,	setifnetmask,	0,	AF_INET },
2717c478bd9Sstevel@tonic-gate 	{ "metric",	NEXTARG,	setifmetric,	0,	AF_ANY },
2727c478bd9Sstevel@tonic-gate 	{ "mtu",	NEXTARG,	setifmtu,	0,	AF_ANY },
2737c478bd9Sstevel@tonic-gate 	{ "index",	NEXTARG,	setifindex,	0,	AF_ANY },
2747c478bd9Sstevel@tonic-gate 	{ "broadcast",	NEXTARG,	setifbroadaddr,	0,	AF_INET },
2757c478bd9Sstevel@tonic-gate 	{ "auto-revarp", 0,		setifrevarp,	1,	AF_INET },
276e11c3f44Smeem 	{ "ipmp",	0,		inetipmp,	1,	AF_ANY },
2777c478bd9Sstevel@tonic-gate 	{ "plumb",	0,		inetplumb,	1,	AF_ANY },
2787c478bd9Sstevel@tonic-gate 	{ "unplumb",	0,		inetunplumb,	0,	AF_ANY },
2797c478bd9Sstevel@tonic-gate 	{ "subnet",	NEXTARG,	setifsubnet,	0,	AF_ANY },
2807c478bd9Sstevel@tonic-gate 	{ "token",	NEXTARG,	setiftoken,	0,	AF_INET6 },
2817c478bd9Sstevel@tonic-gate 	{ "tsrc",	NEXTARG,	setiftsrc,	0,	AF_ANY },
2827c478bd9Sstevel@tonic-gate 	{ "tdst",	NEXTARG,	setiftdst,	0,	AF_ANY },
2837c478bd9Sstevel@tonic-gate 	{ "encr_auth_algs", NEXTARG,	set_tun_esp_auth_alg, 0, AF_ANY },
2847c478bd9Sstevel@tonic-gate 	{ "encr_algs",	NEXTARG,	set_tun_esp_encr_alg, 0, AF_ANY },
2857c478bd9Sstevel@tonic-gate 	{ "auth_algs",	NEXTARG,	set_tun_ah_alg,	0,	AF_ANY },
2867c478bd9Sstevel@tonic-gate 	{ "addif",	NEXTARG,	addif,		1,	AF_ANY },
2877c478bd9Sstevel@tonic-gate 	{ "removeif",	NEXTARG,	removeif,	1,	AF_ANY },
2887c478bd9Sstevel@tonic-gate 	{ "modlist",	0,		modlist,	1,	AF_ANY },
2897c478bd9Sstevel@tonic-gate 	{ "modinsert",	NEXTARG,	modinsert,	1,	AF_ANY },
2907c478bd9Sstevel@tonic-gate 	{ "modremove",	NEXTARG,	modremove,	1,	AF_ANY },
2917c478bd9Sstevel@tonic-gate 	{ "failover",	-IFF_NOFAILOVER, setifflags,	1,	AF_ANY },
2927c478bd9Sstevel@tonic-gate 	{ "-failover",	IFF_NOFAILOVER, setifflags,	1,	AF_ANY },
2937c478bd9Sstevel@tonic-gate 	{ "standby",	IFF_STANDBY,	setifflags,	1,	AF_ANY },
2947c478bd9Sstevel@tonic-gate 	{ "-standby",	-IFF_STANDBY,	setifflags,	1,	AF_ANY },
2957c478bd9Sstevel@tonic-gate 	{ "failed",	IFF_FAILED,	setifflags,	1,	AF_ANY },
2967c478bd9Sstevel@tonic-gate 	{ "-failed",	-IFF_FAILED,	setifflags,	1,	AF_ANY },
2977c478bd9Sstevel@tonic-gate 	{ "group",	NEXTARG,	setifgroupname,	1,	AF_ANY },
2987c478bd9Sstevel@tonic-gate 	{ "configinfo",	0,		configinfo,	1,	AF_ANY },
2997906a3e0Smeem 	{ "encaplimit",	NEXTARG,	set_tun_encap_limit,	0, AF_ANY },
3007906a3e0Smeem 	{ "-encaplimit", 0,		clr_tun_encap_limit,	0, AF_ANY },
3017906a3e0Smeem 	{ "thoplimit",	NEXTARG,	set_tun_hop_limit,	0, AF_ANY },
3027c478bd9Sstevel@tonic-gate 	{ "set",	NEXTARG,	setifaddr,	0,	AF_ANY },
3037c478bd9Sstevel@tonic-gate 	{ "destination", NEXTARG,	setifdstaddr,	0,	AF_ANY },
3047c478bd9Sstevel@tonic-gate 	{ "zone",	NEXTARG,	setzone,	0,	AF_ANY },
3057c478bd9Sstevel@tonic-gate 	{ "-zone",	0,		setzone,	0,	AF_ANY },
30645916cd2Sjpk 	{ "all-zones",	0,		setallzones,	0,	AF_ANY },
3077c478bd9Sstevel@tonic-gate 	{ "ether",	OPTARG,		setifether,	0,	AF_ANY },
3087c478bd9Sstevel@tonic-gate 	{ "usesrc",	NEXTARG,	setifsrc,	0,	AF_ANY },
309f7d61273Smeem 
310f7d61273Smeem 	/*
311f7d61273Smeem 	 * NOTE: any additions to this table must also be applied to ifparse
312f7d61273Smeem 	 *	(usr/src/cmd/cmd-inet/sbin/ifparse/ifparse.c)
313f7d61273Smeem 	 */
314f7d61273Smeem 
3157c478bd9Sstevel@tonic-gate 	{ 0,		0,		setifaddr,	0,	AF_ANY },
3167c478bd9Sstevel@tonic-gate 	{ 0,		0,		setifdstaddr,	0,	AF_ANY },
3177c478bd9Sstevel@tonic-gate 	{ 0,		0,		0,		0,	0 },
3187c478bd9Sstevel@tonic-gate };
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate typedef struct if_config_cmd {
3227c478bd9Sstevel@tonic-gate 	uint64_t	iff_flag;
323e11c3f44Smeem 	int		iff_af;
3247c478bd9Sstevel@tonic-gate 	char		*iff_name;
3257c478bd9Sstevel@tonic-gate } if_config_cmd_t;
3267c478bd9Sstevel@tonic-gate 
327e11c3f44Smeem /*
328e11c3f44Smeem  * NOTE: print_config_flags() processes this table in order, so we put "up"
329e11c3f44Smeem  * last so that we can be sure "-failover" will take effect first.  Otherwise,
330e11c3f44Smeem  * IPMP test addresses will erroneously migrate to the IPMP interface.
331e11c3f44Smeem  */
3327c478bd9Sstevel@tonic-gate static if_config_cmd_t	if_config_cmd_tbl[] = {
333e11c3f44Smeem 	{ IFF_NOTRAILERS,	AF_UNSPEC,	"-trailers"	},
334e11c3f44Smeem 	{ IFF_PRIVATE,		AF_UNSPEC,	"private"	},
335e11c3f44Smeem 	{ IFF_NOXMIT,		AF_UNSPEC,	"-xmit"		},
336e11c3f44Smeem 	{ IFF_ANYCAST,		AF_INET6,	"anycast"	},
337e11c3f44Smeem 	{ IFF_NOLOCAL,		AF_UNSPEC,	"-local"	},
338e11c3f44Smeem 	{ IFF_DEPRECATED,	AF_UNSPEC,	"deprecated"	},
339e11c3f44Smeem 	{ IFF_NOFAILOVER,	AF_UNSPEC,	"-failover"	},
340e11c3f44Smeem 	{ IFF_STANDBY,		AF_UNSPEC,	"standby"	},
341e11c3f44Smeem 	{ IFF_FAILED,		AF_UNSPEC,	"failed"	},
342e11c3f44Smeem 	{ IFF_PREFERRED,	AF_UNSPEC,	"preferred"	},
343e11c3f44Smeem 	{ IFF_NONUD,		AF_INET6,	"-nud"		},
344e11c3f44Smeem 	{ IFF_NOARP,		AF_INET,	"-arp"		},
345e11c3f44Smeem 	{ IFF_UP,		AF_UNSPEC, 	"up" 		},
346e11c3f44Smeem 	{ 0,			0,		NULL		},
3477c478bd9Sstevel@tonic-gate };
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate typedef struct ni {
3507c478bd9Sstevel@tonic-gate 	char		ni_name[LIFNAMSIZ];
3517c478bd9Sstevel@tonic-gate 	struct ni	*ni_next;
3527c478bd9Sstevel@tonic-gate } ni_t;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate static ni_t	*ni_list = NULL;
3557c478bd9Sstevel@tonic-gate static int	num_ni = 0;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate /* End defines and structure definitions for ifconfig -a plumb */
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /* Known address families */
3607c478bd9Sstevel@tonic-gate struct afswtch {
3617c478bd9Sstevel@tonic-gate 	char *af_name;
3627c478bd9Sstevel@tonic-gate 	short af_af;
3637c478bd9Sstevel@tonic-gate 	void (*af_status)();
3647c478bd9Sstevel@tonic-gate 	void (*af_getaddr)();
3657c478bd9Sstevel@tonic-gate 	void (*af_configinfo)();
3667c478bd9Sstevel@tonic-gate } afs[] = {
3677c478bd9Sstevel@tonic-gate 	{ "inet", AF_INET, in_status, in_getaddr, in_configinfo },
3687c478bd9Sstevel@tonic-gate 	{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_configinfo },
3697c478bd9Sstevel@tonic-gate 	{ 0, 0,	0, 0, 0 }
3707c478bd9Sstevel@tonic-gate };
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate #define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate struct afswtch *afp;	/* the address family being set or asked about */
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])3777c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
3787c478bd9Sstevel@tonic-gate {
3792b24ab6bSSebastien Roy 	int64_t		lifc_flags;
3802b24ab6bSSebastien Roy 	char		*default_ip_str;
3816e91bba0SGirish Moodalbail 	ipadm_status_t	istatus;
3827c478bd9Sstevel@tonic-gate 
3836e91bba0SGirish Moodalbail 	lifc_flags = LIFC_DEFAULT;
384e11c3f44Smeem 
3857c478bd9Sstevel@tonic-gate 	if (argc < 2) {
386f7c14501SDaniil Lunev 		(void) strncpy(name, "-a", sizeof (name));
387f7c14501SDaniil Lunev 	} else {
388f7c14501SDaniil Lunev 		argc--, argv++;
389f7c14501SDaniil Lunev 		if (strlen(*argv) > sizeof (name) - 1) {
390f7c14501SDaniil Lunev 			(void) fprintf(stderr, "%s: interface name too long\n",
391f7c14501SDaniil Lunev 			    *argv);
392f7c14501SDaniil Lunev 			exit(1);
393f7c14501SDaniil Lunev 		}
394f7c14501SDaniil Lunev 		(void) strncpy(name, *argv, sizeof (name));
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 	name[sizeof (name) - 1] = '\0';
3977c478bd9Sstevel@tonic-gate 	(void) strncpy(origname, name, sizeof (origname));	/* For addif */
3987c478bd9Sstevel@tonic-gate 	default_ip_str = NULL;
3997c478bd9Sstevel@tonic-gate 	v4compat = get_compat_flag(&default_ip_str);
4007c478bd9Sstevel@tonic-gate 	if (v4compat == DEFAULT_PROT_BAD_VALUE) {
4017c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
4027c478bd9Sstevel@tonic-gate 		    "ifconfig: %s: Bad value for %s in %s\n", default_ip_str,
4037c478bd9Sstevel@tonic-gate 		    DEFAULT_IP, INET_DEFAULT_FILE);
4047c478bd9Sstevel@tonic-gate 		free(default_ip_str);
4057c478bd9Sstevel@tonic-gate 		exit(2);
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	free(default_ip_str);
4087c478bd9Sstevel@tonic-gate 	argc--, argv++;
4097c478bd9Sstevel@tonic-gate 	if (argc > 0) {
4107c478bd9Sstevel@tonic-gate 		struct afswtch *myafp;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 		for (myafp = afp = afs; myafp->af_name; myafp++) {
4137c478bd9Sstevel@tonic-gate 			if (strcmp(myafp->af_name, *argv) == 0) {
4147c478bd9Sstevel@tonic-gate 				afp = myafp; argc--; argv++;
4157c478bd9Sstevel@tonic-gate 				break;
4167c478bd9Sstevel@tonic-gate 			}
4177c478bd9Sstevel@tonic-gate 		}
4187c478bd9Sstevel@tonic-gate 		af = lifr.lifr_addr.ss_family = afp->af_af;
4197c478bd9Sstevel@tonic-gate 		if (af == AF_INET6) {
4207c478bd9Sstevel@tonic-gate 			v4compat = 0;
4217c478bd9Sstevel@tonic-gate 		}
4227c478bd9Sstevel@tonic-gate 	}
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	s = socket(SOCKET_AF(af), SOCK_DGRAM, 0);
425e11c3f44Smeem 	s4 = socket(AF_INET, SOCK_DGRAM, 0);
426e11c3f44Smeem 	s6 = socket(AF_INET6, SOCK_DGRAM, 0);
427e11c3f44Smeem 	if (s == -1 || s4 == -1 || s6 == -1)
4287c478bd9Sstevel@tonic-gate 		Perror0_exit("socket");
4296e91bba0SGirish Moodalbail 	/*
4306e91bba0SGirish Moodalbail 	 * Open the global libipadm handle. The flag IPH_LEGACY has to
4316e91bba0SGirish Moodalbail 	 * be specified to indicate that logical interface names will
4326e91bba0SGirish Moodalbail 	 * be used during interface creation and address creation.
4336e91bba0SGirish Moodalbail 	 */
4346e91bba0SGirish Moodalbail 	if ((istatus = ipadm_open(&iph, IPH_LEGACY)) != IPADM_SUCCESS)
4356e91bba0SGirish Moodalbail 		ipadmerr_exit(istatus, "unable to open handle to libipadm");
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	/*
4387c478bd9Sstevel@tonic-gate 	 * Special interface names is any combination of these flags.
4397c478bd9Sstevel@tonic-gate 	 * Note that due to the ifconfig syntax they have to be combined
4407c478bd9Sstevel@tonic-gate 	 * as a single '-' option.
4417c478bd9Sstevel@tonic-gate 	 *	-a	All interfaces
4427c478bd9Sstevel@tonic-gate 	 *	-u	"up" interfaces
4437c478bd9Sstevel@tonic-gate 	 *	-d	"down" interfaces
4447c478bd9Sstevel@tonic-gate 	 *	-D	Interfaces not controlled by DHCP
4457c478bd9Sstevel@tonic-gate 	 *	-4	IPv4 interfaces
4467c478bd9Sstevel@tonic-gate 	 *	-6	IPv6 interfaces
4477c478bd9Sstevel@tonic-gate 	 *	-X	Turn on debug (not documented)
4487c478bd9Sstevel@tonic-gate 	 *	-v	Turn on verbose
4497c478bd9Sstevel@tonic-gate 	 *	-Z	Only interfaces in caller's zone
4507c478bd9Sstevel@tonic-gate 	 */
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (name[0] == '-') {
4537c478bd9Sstevel@tonic-gate 		/* One or more options */
4547c478bd9Sstevel@tonic-gate 		int64_t onflags = 0;
4557c478bd9Sstevel@tonic-gate 		int64_t offflags = 0;
4567c478bd9Sstevel@tonic-gate 		int c;
4577c478bd9Sstevel@tonic-gate 		char *av[2] = { "ifconfig", name };
4587c478bd9Sstevel@tonic-gate 
459f7c14501SDaniil Lunev 		while ((c = getopt(2, av, "audhDXZ46v")) != -1) {
4607c478bd9Sstevel@tonic-gate 			switch ((char)c) {
4617c478bd9Sstevel@tonic-gate 			case 'a':
4627c478bd9Sstevel@tonic-gate 				all = 1;
4637c478bd9Sstevel@tonic-gate 				break;
4647c478bd9Sstevel@tonic-gate 			case 'u':
4657c478bd9Sstevel@tonic-gate 				onflags |= IFF_UP;
4667c478bd9Sstevel@tonic-gate 				break;
4677c478bd9Sstevel@tonic-gate 			case 'd':
4687c478bd9Sstevel@tonic-gate 				offflags |= IFF_UP;
4697c478bd9Sstevel@tonic-gate 				break;
4707c478bd9Sstevel@tonic-gate 			case 'D':
4717c478bd9Sstevel@tonic-gate 				offflags |= IFF_DHCPRUNNING;
4727c478bd9Sstevel@tonic-gate 				break;
4737c478bd9Sstevel@tonic-gate 			case 'X':
4747c478bd9Sstevel@tonic-gate 				debug += 3;
4757c478bd9Sstevel@tonic-gate 				break;
4767c478bd9Sstevel@tonic-gate 			case 'Z':
4777c478bd9Sstevel@tonic-gate 				lifc_flags &= ~LIFC_ALLZONES;
4787c478bd9Sstevel@tonic-gate 				break;
4797c478bd9Sstevel@tonic-gate 			case '4':
4807c478bd9Sstevel@tonic-gate 				/*
4817c478bd9Sstevel@tonic-gate 				 * -4 is not a compatable flag, therefore
4827c478bd9Sstevel@tonic-gate 				 * we assume they want v4compat turned off
4837c478bd9Sstevel@tonic-gate 				 */
4847c478bd9Sstevel@tonic-gate 				v4compat = 0;
4857c478bd9Sstevel@tonic-gate 				onflags |= IFF_IPV4;
4867c478bd9Sstevel@tonic-gate 				break;
4877c478bd9Sstevel@tonic-gate 			case '6':
4887c478bd9Sstevel@tonic-gate 				/*
4897c478bd9Sstevel@tonic-gate 				 * If they want IPv6, well then we'll assume
4907c478bd9Sstevel@tonic-gate 				 * they don't want IPv4 compat
4917c478bd9Sstevel@tonic-gate 				 */
4927c478bd9Sstevel@tonic-gate 				v4compat = 0;
4937c478bd9Sstevel@tonic-gate 				onflags |= IFF_IPV6;
4947c478bd9Sstevel@tonic-gate 				break;
4957c478bd9Sstevel@tonic-gate 			case 'v':
4967c478bd9Sstevel@tonic-gate 				verbose = 1;
4977c478bd9Sstevel@tonic-gate 				break;
498f7c14501SDaniil Lunev 			case 'h':
4997c478bd9Sstevel@tonic-gate 			case '?':
5007c478bd9Sstevel@tonic-gate 				usage();
5017c478bd9Sstevel@tonic-gate 				exit(1);
5027c478bd9Sstevel@tonic-gate 			}
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 		if (!all) {
5057c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
506c7e4935fSss 			    "ifconfig: %s: no such interface\n", name);
5077c478bd9Sstevel@tonic-gate 			exit(1);
5087c478bd9Sstevel@tonic-gate 		}
5096e91bba0SGirish Moodalbail 		foreachinterface(argc, argv, af, onflags, offflags,
5107c478bd9Sstevel@tonic-gate 		    lifc_flags);
5117c478bd9Sstevel@tonic-gate 	} else {
5126e91bba0SGirish Moodalbail 		ifconfig(argc, argv, af, NULL);
5137c478bd9Sstevel@tonic-gate 	}
5146e91bba0SGirish Moodalbail 	ipadm_close(iph);
5157c478bd9Sstevel@tonic-gate 	return (0);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate /*
5196e91bba0SGirish Moodalbail  * For each interface, call ifconfig(argc, argv, af, ifa).
5207c478bd9Sstevel@tonic-gate  * Only call function if onflags and offflags are set or clear, respectively,
5217c478bd9Sstevel@tonic-gate  * in the interfaces flags field.
5227c478bd9Sstevel@tonic-gate  */
5237c478bd9Sstevel@tonic-gate static void
foreachinterface(int argc,char * argv[],int af,int64_t onflags,int64_t offflags,int64_t lifc_flags)5246e91bba0SGirish Moodalbail foreachinterface(int argc, char *argv[], int af,
5257c478bd9Sstevel@tonic-gate     int64_t onflags, int64_t offflags, int64_t lifc_flags)
5267c478bd9Sstevel@tonic-gate {
5276e91bba0SGirish Moodalbail 	ipadm_addr_info_t *ainfo, *ainfop;
5286e91bba0SGirish Moodalbail 	struct ifaddrs *ifa;
5296e91bba0SGirish Moodalbail 	ipadm_status_t istatus;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	/*
5327c478bd9Sstevel@tonic-gate 	 * Special case:
5332b24ab6bSSebastien Roy 	 * ifconfig -a plumb should find all network interfaces in the current
534