xref: /titanic_51/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c (revision 7bc878958fba2b44705c85efbc07b747ef0eeed1)
16e91bba0SGirish Moodalbail /*
26e91bba0SGirish Moodalbail  * CDDL HEADER START
36e91bba0SGirish Moodalbail  *
46e91bba0SGirish Moodalbail  * The contents of this file are subject to the terms of the
56e91bba0SGirish Moodalbail  * Common Development and Distribution License (the "License").
66e91bba0SGirish Moodalbail  * You may not use this file except in compliance with the License.
76e91bba0SGirish Moodalbail  *
86e91bba0SGirish Moodalbail  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96e91bba0SGirish Moodalbail  * or http://www.opensolaris.org/os/licensing.
106e91bba0SGirish Moodalbail  * See the License for the specific language governing permissions
116e91bba0SGirish Moodalbail  * and limitations under the License.
126e91bba0SGirish Moodalbail  *
136e91bba0SGirish Moodalbail  * When distributing Covered Code, include this CDDL HEADER in each
146e91bba0SGirish Moodalbail  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156e91bba0SGirish Moodalbail  * If applicable, add the following below this CDDL HEADER, with the
166e91bba0SGirish Moodalbail  * fields enclosed by brackets "[]" replaced with your own identifying
176e91bba0SGirish Moodalbail  * information: Portions Copyright [yyyy] [name of copyright owner]
186e91bba0SGirish Moodalbail  *
196e91bba0SGirish Moodalbail  * CDDL HEADER END
206e91bba0SGirish Moodalbail  */
216e91bba0SGirish Moodalbail /*
228b88711aSGirish Moodalbail  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*7bc87895SYuri Pankov  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
246e91bba0SGirish Moodalbail  */
256e91bba0SGirish Moodalbail #include <arpa/inet.h>
266e91bba0SGirish Moodalbail #include <errno.h>
276e91bba0SGirish Moodalbail #include <getopt.h>
286e91bba0SGirish Moodalbail #include <inet/ip.h>
296e91bba0SGirish Moodalbail #include <inet/iptun.h>
306e91bba0SGirish Moodalbail #include <inet/tunables.h>
316e91bba0SGirish Moodalbail #include <libdladm.h>
326e91bba0SGirish Moodalbail #include <libdliptun.h>
336e91bba0SGirish Moodalbail #include <libdllink.h>
346e91bba0SGirish Moodalbail #include <libinetutil.h>
356e91bba0SGirish Moodalbail #include <libipadm.h>
366e91bba0SGirish Moodalbail #include <locale.h>
376e91bba0SGirish Moodalbail #include <netdb.h>
386e91bba0SGirish Moodalbail #include <netinet/in.h>
396e91bba0SGirish Moodalbail #include <ofmt.h>
406e91bba0SGirish Moodalbail #include <stdarg.h>
416e91bba0SGirish Moodalbail #include <stddef.h>
426e91bba0SGirish Moodalbail #include <stdio.h>
436e91bba0SGirish Moodalbail #include <stdlib.h>
446e91bba0SGirish Moodalbail #include <string.h>
456e91bba0SGirish Moodalbail #include <strings.h>
466e91bba0SGirish Moodalbail #include <sys/stat.h>
476e91bba0SGirish Moodalbail #include <sys/types.h>
486e91bba0SGirish Moodalbail #include <zone.h>
496e91bba0SGirish Moodalbail 
506e91bba0SGirish Moodalbail #define	STR_UNKNOWN_VAL	"?"
516e91bba0SGirish Moodalbail #define	LIFC_DEFAULT	(LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
526e91bba0SGirish Moodalbail 			LIFC_UNDER_IPMP)
536e91bba0SGirish Moodalbail 
546e91bba0SGirish Moodalbail typedef void cmdfunc_t(int, char **, const char *);
556e91bba0SGirish Moodalbail static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
566e91bba0SGirish Moodalbail static cmdfunc_t do_show_if;
578887b57dSGirish Moodalbail static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
586e91bba0SGirish Moodalbail static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
596e91bba0SGirish Moodalbail static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
606e91bba0SGirish Moodalbail static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
616e91bba0SGirish Moodalbail static cmdfunc_t do_enable_addr, do_disable_addr;
626e91bba0SGirish Moodalbail static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
636e91bba0SGirish Moodalbail 
646e91bba0SGirish Moodalbail typedef struct	cmd {
656e91bba0SGirish Moodalbail 	char		*c_name;
666e91bba0SGirish Moodalbail 	cmdfunc_t	*c_fn;
676e91bba0SGirish Moodalbail 	const char	*c_usage;
686e91bba0SGirish Moodalbail } cmd_t;
696e91bba0SGirish Moodalbail 
706e91bba0SGirish Moodalbail static cmd_t	cmds[] = {
716e91bba0SGirish Moodalbail 	/* interface management related sub-commands */
726e91bba0SGirish Moodalbail 	{ "create-if",	do_create_if,	"\tcreate-if\t[-t] <interface>"	},
736e91bba0SGirish Moodalbail 	{ "disable-if",	do_disable_if,	"\tdisable-if\t-t <interface>"	},
746e91bba0SGirish Moodalbail 	{ "enable-if",	do_enable_if,	"\tenable-if\t-t <interface>"	},
756e91bba0SGirish Moodalbail 	{ "delete-if",	do_delete_if,	"\tdelete-if\t<interface>"	},
766e91bba0SGirish Moodalbail 	{ "show-if",	do_show_if,
776e91bba0SGirish Moodalbail 	    "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"	},
786e91bba0SGirish Moodalbail 	{ "set-ifprop",	do_set_ifprop,
796e91bba0SGirish Moodalbail 	    "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
806e91bba0SGirish Moodalbail 	    "<interface>" 						},
816e91bba0SGirish Moodalbail 	{ "reset-ifprop", do_reset_ifprop,
826e91bba0SGirish Moodalbail 	    "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>"	},
836e91bba0SGirish Moodalbail 	{ "show-ifprop", do_show_ifprop,
846e91bba0SGirish Moodalbail 	    "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
856e91bba0SGirish Moodalbail 	    "\t\t\t[-m <protocol>] [interface]\n" 			},
866e91bba0SGirish Moodalbail 
876e91bba0SGirish Moodalbail 	/* address management related sub-commands */
886e91bba0SGirish Moodalbail 	{ "create-addr", do_create_addr,
89*7bc87895SYuri Pankov 	    "\tcreate-addr\t[-t] -T static [-d] "
90*7bc87895SYuri Pankov 	    "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
91*7bc87895SYuri Pankov 	    "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"
92*7bc87895SYuri Pankov 	    "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
93*7bc87895SYuri Pankov 	    "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
946e91bba0SGirish Moodalbail 	{ "down-addr",	do_down_addr,	"\tdown-addr\t[-t] <addrobj>"	},
956e91bba0SGirish Moodalbail 	{ "up-addr",	do_up_addr,	"\tup-addr\t\t[-t] <addrobj>"	},
966e91bba0SGirish Moodalbail 	{ "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
976e91bba0SGirish Moodalbail 	{ "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>"	},
986e91bba0SGirish Moodalbail 	{ "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
996e91bba0SGirish Moodalbail 	{ "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
1006e91bba0SGirish Moodalbail 	{ "show-addr",	do_show_addr,
1016e91bba0SGirish Moodalbail 	    "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n"		},
1026e91bba0SGirish Moodalbail 	{ "set-addrprop", do_set_addrprop,
1036e91bba0SGirish Moodalbail 	    "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>"	},
1046e91bba0SGirish Moodalbail 	{ "reset-addrprop", do_reset_addrprop,
1056e91bba0SGirish Moodalbail 	    "\treset-addrprop\t[-t] -p <prop> <addrobj>"		},
1066e91bba0SGirish Moodalbail 	{ "show-addrprop", do_show_addrprop,
1076e91bba0SGirish Moodalbail 	    "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
1086e91bba0SGirish Moodalbail 	    "<addrobj>\n" 						},
1096e91bba0SGirish Moodalbail 
1106e91bba0SGirish Moodalbail 	/* protocol properties related sub-commands */
1116e91bba0SGirish Moodalbail 	{ "set-prop",	do_set_prop,
1126e91bba0SGirish Moodalbail 	    "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>"	},
1136e91bba0SGirish Moodalbail 	{ "reset-prop",	do_reset_prop,
1146e91bba0SGirish Moodalbail 	    "\treset-prop\t[-t] -p <prop> <protocol>"			},
1156e91bba0SGirish Moodalbail 	{ "show-prop",	do_show_prop,
1166e91bba0SGirish Moodalbail 	    "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
1178887b57dSGirish Moodalbail 	    " [protocol]"						}
1186e91bba0SGirish Moodalbail };
1196e91bba0SGirish Moodalbail 
1206e91bba0SGirish Moodalbail static const struct option if_longopts[] = {
1216e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1226e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1236e91bba0SGirish Moodalbail };
1246e91bba0SGirish Moodalbail 
1256e91bba0SGirish Moodalbail static const struct option show_prop_longopts[] = {
1266e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'c'	},
1276e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1286e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1296e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1306e91bba0SGirish Moodalbail };
1316e91bba0SGirish Moodalbail 
1326e91bba0SGirish Moodalbail static const struct option show_ifprop_longopts[] = {
1336e91bba0SGirish Moodalbail 	{"module",	required_argument,	0, 'm'	},
1346e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'c'	},
1356e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1366e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1376e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1386e91bba0SGirish Moodalbail };
1396e91bba0SGirish Moodalbail 
1406e91bba0SGirish Moodalbail static const struct option set_prop_longopts[] = {
1416e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1426e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1436e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1446e91bba0SGirish Moodalbail };
1456e91bba0SGirish Moodalbail 
1466e91bba0SGirish Moodalbail static const struct option set_ifprop_longopts[] = {
1476e91bba0SGirish Moodalbail 	{"module",	required_argument,	0, 'm'	},
1486e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1496e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1506e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1516e91bba0SGirish Moodalbail };
1526e91bba0SGirish Moodalbail 
1536e91bba0SGirish Moodalbail static const struct option addr_misc_longopts[] = {
1546e91bba0SGirish Moodalbail 	{"inform",	no_argument,		0, 'i'	},
1556e91bba0SGirish Moodalbail 	{"release",	no_argument,		0, 'r'	},
1566e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1576e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1586e91bba0SGirish Moodalbail };
1596e91bba0SGirish Moodalbail 
1606e91bba0SGirish Moodalbail static const struct option addr_longopts[] = {
1616e91bba0SGirish Moodalbail 	{"address",	required_argument,	0, 'a'	},
1626e91bba0SGirish Moodalbail 	{"down",	no_argument,		0, 'd'	},
1636e91bba0SGirish Moodalbail 	{"interface-id", required_argument,	0, 'i'	},
1646e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1656e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1666e91bba0SGirish Moodalbail 	{"type",	required_argument,	0, 'T'	},
1676e91bba0SGirish Moodalbail 	{"wait",	required_argument,	0, 'w'	},
1686e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1696e91bba0SGirish Moodalbail };
1706e91bba0SGirish Moodalbail 
1716e91bba0SGirish Moodalbail static const struct option show_addr_longopts[] = {
1726e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'p'	},
1736e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1746e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1756e91bba0SGirish Moodalbail };
1766e91bba0SGirish Moodalbail 
1776e91bba0SGirish Moodalbail static const struct option show_if_longopts[] = {
1786e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'p'	},
1796e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1806e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1816e91bba0SGirish Moodalbail };
1826e91bba0SGirish Moodalbail 
1836e91bba0SGirish Moodalbail /* callback functions to print show-* subcommands output */
1846e91bba0SGirish Moodalbail static ofmt_cb_t print_prop_cb;
1856e91bba0SGirish Moodalbail static ofmt_cb_t print_sa_cb;
1866e91bba0SGirish Moodalbail static ofmt_cb_t print_si_cb;
1876e91bba0SGirish Moodalbail 
1886e91bba0SGirish Moodalbail /* structures for 'ipadm show-*' subcommands */
1896e91bba0SGirish Moodalbail typedef enum {
1906e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_IFNAME,
1916e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PROTO,
1926e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_ADDROBJ,
1936e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PROPERTY,
1946e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PERM,
1956e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_CURRENT,
1966e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PERSISTENT,
1976e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_DEFAULT,
1986e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_POSSIBLE
1996e91bba0SGirish Moodalbail } ipadm_propfield_index_t;
2006e91bba0SGirish Moodalbail 
2016e91bba0SGirish Moodalbail static ofmt_field_t intfprop_fields[] = {
2026e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2036e91bba0SGirish Moodalbail { "IFNAME",	12,	IPADM_PROPFIELD_IFNAME,		print_prop_cb},
2046e91bba0SGirish Moodalbail { "PROPERTY",	16,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2056e91bba0SGirish Moodalbail { "PROTO",	6,	IPADM_PROPFIELD_PROTO,		print_prop_cb},
2066e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2076e91bba0SGirish Moodalbail { "CURRENT",	11,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2086e91bba0SGirish Moodalbail { "PERSISTENT",	11,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2096e91bba0SGirish Moodalbail { "DEFAULT",	11,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2106e91bba0SGirish Moodalbail { "POSSIBLE",	16,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2116e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2126e91bba0SGirish Moodalbail };
2136e91bba0SGirish Moodalbail 
2146e91bba0SGirish Moodalbail 
2156e91bba0SGirish Moodalbail static ofmt_field_t modprop_fields[] = {
2166e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2176e91bba0SGirish Moodalbail { "PROTO",	6,	IPADM_PROPFIELD_PROTO,		print_prop_cb},
2186e91bba0SGirish Moodalbail { "PROPERTY",	22,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2196e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2206e91bba0SGirish Moodalbail { "CURRENT",	13,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2216e91bba0SGirish Moodalbail { "PERSISTENT",	13,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2226e91bba0SGirish Moodalbail { "DEFAULT",	13,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2236e91bba0SGirish Moodalbail { "POSSIBLE",	15,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2246e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2256e91bba0SGirish Moodalbail };
2266e91bba0SGirish Moodalbail 
2276e91bba0SGirish Moodalbail static ofmt_field_t addrprop_fields[] = {
2286e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2296e91bba0SGirish Moodalbail { "ADDROBJ",	18,	IPADM_PROPFIELD_ADDROBJ,	print_prop_cb},
2306e91bba0SGirish Moodalbail { "PROPERTY",	11,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2316e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2326e91bba0SGirish Moodalbail { "CURRENT",	16,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2336e91bba0SGirish Moodalbail { "PERSISTENT",	16,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2346e91bba0SGirish Moodalbail { "DEFAULT",	16,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2356e91bba0SGirish Moodalbail { "POSSIBLE",	15,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2366e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2376e91bba0SGirish Moodalbail };
2386e91bba0SGirish Moodalbail 
2396e91bba0SGirish Moodalbail typedef struct show_prop_state {
2406e91bba0SGirish Moodalbail 	char		sps_ifname[LIFNAMSIZ];
2416e91bba0SGirish Moodalbail 	char		sps_aobjname[IPADM_AOBJSIZ];
2426e91bba0SGirish Moodalbail 	const char	*sps_pname;
2436e91bba0SGirish Moodalbail 	uint_t		sps_proto;
2446e91bba0SGirish Moodalbail 	char		*sps_propval;
2456e91bba0SGirish Moodalbail 	nvlist_t	*sps_proplist;
2466e91bba0SGirish Moodalbail 	boolean_t	sps_parsable;
2476e91bba0SGirish Moodalbail 	boolean_t	sps_addrprop;
2486e91bba0SGirish Moodalbail 	boolean_t	sps_ifprop;
2496e91bba0SGirish Moodalbail 	boolean_t	sps_modprop;
2506e91bba0SGirish Moodalbail 	ipadm_status_t	sps_status;
2516e91bba0SGirish Moodalbail 	ipadm_status_t	sps_retstatus;
2526e91bba0SGirish Moodalbail 	ofmt_handle_t	sps_ofmt;
2536e91bba0SGirish Moodalbail } show_prop_state_t;
2546e91bba0SGirish Moodalbail 
2556e91bba0SGirish Moodalbail typedef struct show_addr_state {
2566e91bba0SGirish Moodalbail 	boolean_t	sa_parsable;
2576e91bba0SGirish Moodalbail 	boolean_t	sa_persist;
2586e91bba0SGirish Moodalbail 	ofmt_handle_t	sa_ofmt;
2596e91bba0SGirish Moodalbail } show_addr_state_t;
2606e91bba0SGirish Moodalbail 
2616e91bba0SGirish Moodalbail typedef struct show_if_state {
2626e91bba0SGirish Moodalbail 	boolean_t	si_parsable;
2636e91bba0SGirish Moodalbail 	ofmt_handle_t	si_ofmt;
2646e91bba0SGirish Moodalbail } show_if_state_t;
2656e91bba0SGirish Moodalbail 
2666e91bba0SGirish Moodalbail typedef struct show_addr_args_s {
2676e91bba0SGirish Moodalbail 	show_addr_state_t	*sa_state;
2686e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*sa_info;
2696e91bba0SGirish Moodalbail } show_addr_args_t;
2706e91bba0SGirish Moodalbail 
2716e91bba0SGirish Moodalbail typedef struct show_if_args_s {
2726e91bba0SGirish Moodalbail 	show_if_state_t *si_state;
2736e91bba0SGirish Moodalbail 	ipadm_if_info_t *si_info;
2746e91bba0SGirish Moodalbail } show_if_args_t;
2756e91bba0SGirish Moodalbail 
2766e91bba0SGirish Moodalbail typedef enum {
2776e91bba0SGirish Moodalbail 	SA_ADDROBJ,
2786e91bba0SGirish Moodalbail 	SA_TYPE,
2796e91bba0SGirish Moodalbail 	SA_STATE,
2806e91bba0SGirish Moodalbail 	SA_CURRENT,
2816e91bba0SGirish Moodalbail 	SA_PERSISTENT,
2826e91bba0SGirish Moodalbail 	SA_ADDR
2836e91bba0SGirish Moodalbail } sa_field_index_t;
2846e91bba0SGirish Moodalbail 
2856e91bba0SGirish Moodalbail typedef enum {
2866e91bba0SGirish Moodalbail 	SI_IFNAME,
2876e91bba0SGirish Moodalbail 	SI_STATE,
2886e91bba0SGirish Moodalbail 	SI_CURRENT,
2896e91bba0SGirish Moodalbail 	SI_PERSISTENT
2906e91bba0SGirish Moodalbail } si_field_index_t;
2916e91bba0SGirish Moodalbail 
2926e91bba0SGirish Moodalbail static ofmt_field_t show_addr_fields[] = {
2936e91bba0SGirish Moodalbail /* name,	field width,	id,		callback */
2946e91bba0SGirish Moodalbail { "ADDROBJ",	18,		SA_ADDROBJ,	print_sa_cb},
2956e91bba0SGirish Moodalbail { "TYPE",	9,		SA_TYPE,	print_sa_cb},
2966e91bba0SGirish Moodalbail { "STATE",	13,		SA_STATE,	print_sa_cb},
2976e91bba0SGirish Moodalbail { "CURRENT",	8,		SA_CURRENT,	print_sa_cb},
2986e91bba0SGirish Moodalbail { "PERSISTENT",	11,		SA_PERSISTENT,	print_sa_cb},
2996e91bba0SGirish Moodalbail { "ADDR",	46,		SA_ADDR,	print_sa_cb},
3006e91bba0SGirish Moodalbail { NULL,		0,		0,		NULL}
3016e91bba0SGirish Moodalbail };
3026e91bba0SGirish Moodalbail 
3036e91bba0SGirish Moodalbail static ofmt_field_t show_if_fields[] = {
3046e91bba0SGirish Moodalbail /* name,	field width,	id,		callback */
3056e91bba0SGirish Moodalbail { "IFNAME",	11,		SI_IFNAME,	print_si_cb},
3066e91bba0SGirish Moodalbail { "STATE",	9,		SI_STATE,	print_si_cb},
307550b6e40SSowmini Varadhan { "CURRENT",	13,		SI_CURRENT,	print_si_cb},
3086e91bba0SGirish Moodalbail { "PERSISTENT",	11,		SI_PERSISTENT,	print_si_cb},
3096e91bba0SGirish Moodalbail { NULL,		0,		0,		NULL}
3106e91bba0SGirish Moodalbail };
3116e91bba0SGirish Moodalbail 
3126e91bba0SGirish Moodalbail #define	IPADM_ALL_BITS	((uint_t)-1)
3136e91bba0SGirish Moodalbail typedef struct intf_mask {
3146e91bba0SGirish Moodalbail 	char		*name;
3156e91bba0SGirish Moodalbail 	uint64_t	bits;
3166e91bba0SGirish Moodalbail 	uint64_t	mask;
3176e91bba0SGirish Moodalbail } fmask_t;
3186e91bba0SGirish Moodalbail 
3196e91bba0SGirish Moodalbail /*
3206e91bba0SGirish Moodalbail  * Handle to libipadm. Opened in main() before the sub-command specific
3216e91bba0SGirish Moodalbail  * function is called and is closed before the program exits.
3226e91bba0SGirish Moodalbail  */
3236e91bba0SGirish Moodalbail ipadm_handle_t	iph = NULL;
3246e91bba0SGirish Moodalbail 
3256e91bba0SGirish Moodalbail /*
3266e91bba0SGirish Moodalbail  * Opaque ipadm address object. Used by all the address management subcommands.
3276e91bba0SGirish Moodalbail  */
3286e91bba0SGirish Moodalbail ipadm_addrobj_t	ipaddr = NULL;
3296e91bba0SGirish Moodalbail 
3306e91bba0SGirish Moodalbail static char *progname;
3316e91bba0SGirish Moodalbail 
3326e91bba0SGirish Moodalbail static void	die(const char *, ...);
3336e91bba0SGirish Moodalbail static void	die_opterr(int, int, const char *);
3346e91bba0SGirish Moodalbail static void	warn_ipadmerr(ipadm_status_t, const char *, ...);
3356e91bba0SGirish Moodalbail static void 	ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
3366e91bba0SGirish Moodalbail static void 	ipadm_check_propstr(const char *, boolean_t, const char *);
3376e91bba0SGirish Moodalbail static void 	process_misc_addrargs(int, char **, const char *, int *,
3386e91bba0SGirish Moodalbail 		    uint32_t *);
3396e91bba0SGirish Moodalbail 
3406e91bba0SGirish Moodalbail static void
3416e91bba0SGirish Moodalbail usage(void)
3426e91bba0SGirish Moodalbail {
3436e91bba0SGirish Moodalbail 	int	i;
3446e91bba0SGirish Moodalbail 	cmd_t	*cmdp;
3456e91bba0SGirish Moodalbail 
3466e91bba0SGirish Moodalbail 	(void) fprintf(stderr,
3476e91bba0SGirish Moodalbail 	    gettext("usage:  ipadm <subcommand> <args> ...\n"));
3486e91bba0SGirish Moodalbail 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3496e91bba0SGirish Moodalbail 		cmdp = &cmds[i];
3506e91bba0SGirish Moodalbail 		if (cmdp->c_usage != NULL)
3516e91bba0SGirish Moodalbail 			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
3526e91bba0SGirish Moodalbail 	}
3536e91bba0SGirish Moodalbail 
3546e91bba0SGirish Moodalbail 	ipadm_destroy_addrobj(ipaddr);
3556e91bba0SGirish Moodalbail 	ipadm_close(iph);
3566e91bba0SGirish Moodalbail 	exit(1);
3576e91bba0SGirish Moodalbail }
3586e91bba0SGirish Moodalbail 
3596e91bba0SGirish Moodalbail int
3606e91bba0SGirish Moodalbail main(int argc, char *argv[])
3616e91bba0SGirish Moodalbail {
3626e91bba0SGirish Moodalbail 	int	i;
3636e91bba0SGirish Moodalbail 	cmd_t	*cmdp;
3646e91bba0SGirish Moodalbail 	ipadm_status_t status;
3656e91bba0SGirish Moodalbail 
3666e91bba0SGirish Moodalbail 	(void) setlocale(LC_ALL, "");
3676e91bba0SGirish Moodalbail 	(void) textdomain(TEXT_DOMAIN);
3686e91bba0SGirish Moodalbail 
3696e91bba0SGirish Moodalbail 	if ((progname = strrchr(argv[0], '/')) == NULL)
3706e91bba0SGirish Moodalbail 		progname = argv[0];
3716e91bba0SGirish Moodalbail 	else
3726e91bba0SGirish Moodalbail 		progname++;
3736e91bba0SGirish Moodalbail 
3746e91bba0SGirish Moodalbail 	if (argc < 2)
3756e91bba0SGirish Moodalbail 		usage();
3766e91bba0SGirish Moodalbail 
3776e91bba0SGirish Moodalbail 	status = ipadm_open(&iph, 0);
3786e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
3796e91bba0SGirish Moodalbail 		die("Could not open handle to library - %s",
3806e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
3816e91bba0SGirish Moodalbail 	}
3826e91bba0SGirish Moodalbail 
3836e91bba0SGirish Moodalbail 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3846e91bba0SGirish Moodalbail 		cmdp = &cmds[i];
3856e91bba0SGirish Moodalbail 		if (strcmp(argv[1], cmdp->c_name) == 0) {
3866e91bba0SGirish Moodalbail 			cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
3876e91bba0SGirish Moodalbail 			ipadm_destroy_addrobj(ipaddr);
3886e91bba0SGirish Moodalbail 			ipadm_close(iph);
3896e91bba0SGirish Moodalbail 			exit(0);
3906e91bba0SGirish Moodalbail 		}
3916e91bba0SGirish Moodalbail 	}
3926e91bba0SGirish Moodalbail 
3936e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
3946e91bba0SGirish Moodalbail 	    progname, argv[1]);
3956e91bba0SGirish Moodalbail 	usage();
3966e91bba0SGirish Moodalbail 
3976e91bba0SGirish Moodalbail 	return (0);
3986e91bba0SGirish Moodalbail }
3996e91bba0SGirish Moodalbail 
4006e91bba0SGirish Moodalbail /*
4016e91bba0SGirish Moodalbail  * Create an IP interface for which no saved configuration exists in the
4026e91bba0SGirish Moodalbail  * persistent store.
4036e91bba0SGirish Moodalbail  */
4046e91bba0SGirish Moodalbail static void
4056e91bba0SGirish Moodalbail do_create_if(int argc, char *argv[], const char *use)
4066e91bba0SGirish Moodalbail {
4076e91bba0SGirish Moodalbail 	ipadm_status_t	status;
4086e91bba0SGirish Moodalbail 	int		option;
4096e91bba0SGirish Moodalbail 	uint32_t	flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
4106e91bba0SGirish Moodalbail 
4116e91bba0SGirish Moodalbail 	opterr = 0;
4126e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":t", if_longopts,
4136e91bba0SGirish Moodalbail 	    NULL)) != -1) {
4146e91bba0SGirish Moodalbail 		switch (option) {
4156e91bba0SGirish Moodalbail 		case 't':
4166e91bba0SGirish Moodalbail 			/*
4176e91bba0SGirish Moodalbail 			 * "ifconfig" mode - plumb interface, but do not
4186e91bba0SGirish Moodalbail 			 * restore settings that may exist in db.
4196e91bba0SGirish Moodalbail 			 */
4206e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
4216e91bba0SGirish Moodalbail 			break;
4226e91bba0SGirish Moodalbail 		default:
4236e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
4246e91bba0SGirish Moodalbail 		}
4256e91bba0SGirish Moodalbail 	}
4266e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
4276e91bba0SGirish Moodalbail 		die("Usage: %s", use);
4286e91bba0SGirish Moodalbail 	status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
4296e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
4306e91bba0SGirish Moodalbail 		die("Could not create %s : %s",
4316e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
4326e91bba0SGirish Moodalbail 	}
4336e91bba0SGirish Moodalbail }
4346e91bba0SGirish Moodalbail 
4356e91bba0SGirish Moodalbail /*
4366e91bba0SGirish Moodalbail  * Enable an IP interface based on the persistent configuration for
4376e91bba0SGirish Moodalbail  * that interface.
4386e91bba0SGirish Moodalbail  */
4396e91bba0SGirish Moodalbail static void
4406e91bba0SGirish Moodalbail do_enable_if(int argc, char *argv[], const char *use)
4416e91bba0SGirish Moodalbail {
4426e91bba0SGirish Moodalbail 	ipadm_status_t	status;
4436e91bba0SGirish Moodalbail 	int		index;
4446e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4456e91bba0SGirish Moodalbail 
4466e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
4476e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
4486e91bba0SGirish Moodalbail 		die("persistent operation not supported for enable-if");
4496e91bba0SGirish Moodalbail 	status = ipadm_enable_if(iph, argv[index], flags);
4506e91bba0SGirish Moodalbail 	if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
4516e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
4526e91bba0SGirish Moodalbail 	} else if (status != IPADM_SUCCESS) {
4536e91bba0SGirish Moodalbail 		die("Could not enable %s : %s",
4546e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
4556e91bba0SGirish Moodalbail 	}
4566e91bba0SGirish Moodalbail }
4576e91bba0SGirish Moodalbail 
4586e91bba0SGirish Moodalbail /*
4596e91bba0SGirish Moodalbail  * Remove an IP interface from both active and persistent configuration.
4606e91bba0SGirish Moodalbail  */
4616e91bba0SGirish Moodalbail static void
4626e91bba0SGirish Moodalbail do_delete_if(int argc, char *argv[], const char *use)
4636e91bba0SGirish Moodalbail {
4646e91bba0SGirish Moodalbail 	ipadm_status_t	status;
4656e91bba0SGirish Moodalbail 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4666e91bba0SGirish Moodalbail 
4676e91bba0SGirish Moodalbail 	if (argc != 2)
4686e91bba0SGirish Moodalbail 		die("Usage: %s", use);
4696e91bba0SGirish Moodalbail 
4706e91bba0SGirish Moodalbail 	status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
4716e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
4726e91bba0SGirish Moodalbail 		die("Could not delete %s: %s",
4736e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
4746e91bba0SGirish Moodalbail 	}
4756e91bba0SGirish Moodalbail }
4766e91bba0SGirish Moodalbail 
4776e91bba0SGirish Moodalbail /*
4786e91bba0SGirish Moodalbail  * Disable an IP interface by removing it from active configuration.
4796e91bba0SGirish Moodalbail  */
4806e91bba0SGirish Moodalbail static void
4816e91bba0SGirish Moodalbail do_disable_if(int argc, char *argv[], const char *use)
4826e91bba0SGirish Moodalbail {
4836e91bba0SGirish Moodalbail 	ipadm_status_t	status;
4846e91bba0SGirish Moodalbail 	int		index;
4856e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
4866e91bba0SGirish Moodalbail 
4876e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
4886e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
4896e91bba0SGirish Moodalbail 		die("persistent operation not supported for disable-if");
4906e91bba0SGirish Moodalbail 	status = ipadm_disable_if(iph, argv[index], flags);
4916e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
4926e91bba0SGirish Moodalbail 		die("Could not disable %s: %s",
4936e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
4946e91bba0SGirish Moodalbail 	}
4956e91bba0SGirish Moodalbail }
4966e91bba0SGirish Moodalbail 
4976e91bba0SGirish Moodalbail /*
4986e91bba0SGirish Moodalbail  * called in from print_prop_cb() and does the job of printing each
4996e91bba0SGirish Moodalbail  * individual column in the 'ipadm show-*prop' output.
5006e91bba0SGirish Moodalbail  */
5016e91bba0SGirish Moodalbail static void
5026e91bba0SGirish Moodalbail print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
5036e91bba0SGirish Moodalbail {
5046e91bba0SGirish Moodalbail 	const char		*prop_name = statep->sps_pname;
5056e91bba0SGirish Moodalbail 	char			*ifname = statep->sps_ifname;
5066e91bba0SGirish Moodalbail 	char			*propval = statep->sps_propval;
5076e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
5086e91bba0SGirish Moodalbail 	size_t			propsize = MAXPROPVALLEN;
5096e91bba0SGirish Moodalbail 	char			*object;
5106e91bba0SGirish Moodalbail 	ipadm_status_t		status;
5116e91bba0SGirish Moodalbail 
5126e91bba0SGirish Moodalbail 	if (statep->sps_ifprop) {
5136e91bba0SGirish Moodalbail 		status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
5146e91bba0SGirish Moodalbail 		    &propsize, proto, flags);
5156e91bba0SGirish Moodalbail 		object = ifname;
5166e91bba0SGirish Moodalbail 	} else if (statep->sps_modprop) {
5176e91bba0SGirish Moodalbail 		status = ipadm_get_prop(iph, prop_name, propval, &propsize,
5186e91bba0SGirish Moodalbail 		    proto, flags);
5196e91bba0SGirish Moodalbail 		object = ipadm_proto2str(proto);
5206e91bba0SGirish Moodalbail 	} else {
5216e91bba0SGirish Moodalbail 		status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
5226e91bba0SGirish Moodalbail 		    statep->sps_aobjname, flags);
5236e91bba0SGirish Moodalbail 		object = statep->sps_aobjname;
5246e91bba0SGirish Moodalbail 	}
5256e91bba0SGirish Moodalbail 
5266e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
5276e91bba0SGirish Moodalbail 		if (status == IPADM_PROP_UNKNOWN ||
5286e91bba0SGirish Moodalbail 		    status == IPADM_INVALID_ARG) {
5296e91bba0SGirish Moodalbail 			warn_ipadmerr(status, "cannot get property '%s' for "
5306e91bba0SGirish Moodalbail 			    "'%s'", prop_name, object);
5316e91bba0SGirish Moodalbail 		} else if (status == IPADM_NOTSUP) {
5326e91bba0SGirish Moodalbail 			warn_ipadmerr(status, "'%s'", object);
5336e91bba0SGirish Moodalbail 		} else if (status == IPADM_NOTFOUND) {
5346e91bba0SGirish Moodalbail 			if (flags & IPADM_OPT_PERSIST) {
5356e91bba0SGirish Moodalbail 				propval[0] = '\0';
5366e91bba0SGirish Moodalbail 				goto cont;
5376e91bba0SGirish Moodalbail 			} else {
5386e91bba0SGirish Moodalbail 				warn_ipadmerr(status, "no such object '%s'",
5396e91bba0SGirish Moodalbail 				    object);
5406e91bba0SGirish Moodalbail 			}
5416e91bba0SGirish Moodalbail 		} else if (status == IPADM_ENXIO) {
5426e91bba0SGirish Moodalbail 			/* the interface is probably disabled */
5436e91bba0SGirish Moodalbail 			propval[0] = '\0';
5446e91bba0SGirish Moodalbail 			goto cont;
5456e91bba0SGirish Moodalbail 		}
5466e91bba0SGirish Moodalbail 		statep->sps_status = status;
5476e91bba0SGirish Moodalbail 		statep->sps_retstatus = status;
5486e91bba0SGirish Moodalbail 		return;
5496e91bba0SGirish Moodalbail 	}
5506e91bba0SGirish Moodalbail cont:
5516e91bba0SGirish Moodalbail 	statep->sps_status = IPADM_SUCCESS;
5526e91bba0SGirish Moodalbail 	(void) snprintf(buf, bufsize, "%s", propval);
5536e91bba0SGirish Moodalbail }
5546e91bba0SGirish Moodalbail 
5556e91bba0SGirish Moodalbail /*
5566e91bba0SGirish Moodalbail  * callback function which displays output for set-prop, set-ifprop and
5576e91bba0SGirish Moodalbail  * set-addrprop subcommands.
5586e91bba0SGirish Moodalbail  */
5596e91bba0SGirish Moodalbail static boolean_t
5606e91bba0SGirish Moodalbail print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
5616e91bba0SGirish Moodalbail {
5626e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = ofarg->ofmt_cbarg;
5636e91bba0SGirish Moodalbail 	const char		*propname = statep->sps_pname;
5646e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
5656e91bba0SGirish Moodalbail 	boolean_t		cont = _B_TRUE;
5666e91bba0SGirish Moodalbail 
5676e91bba0SGirish Moodalbail 	/*
5686e91bba0SGirish Moodalbail 	 * Fail retrieving remaining fields, if you fail
5696e91bba0SGirish Moodalbail 	 * to retrieve a field.
5706e91bba0SGirish Moodalbail 	 */
5716e91bba0SGirish Moodalbail 	if (statep->sps_status != IPADM_SUCCESS)
5726e91bba0SGirish Moodalbail 		return (_B_FALSE);
5736e91bba0SGirish Moodalbail 
5746e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
5756e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_IFNAME:
5766e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
5776e91bba0SGirish Moodalbail 		break;
5786e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PROTO:
5796e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
5806e91bba0SGirish Moodalbail 		break;
5816e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_ADDROBJ:
5826e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
5836e91bba0SGirish Moodalbail 		break;
5846e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PROPERTY:
5856e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", propname);
5866e91bba0SGirish Moodalbail 		break;
5876e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PERM:
5886e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
5896e91bba0SGirish Moodalbail 		break;
5906e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_CURRENT:
5916e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
5926e91bba0SGirish Moodalbail 		break;
5936e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PERSISTENT:
5946e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
5956e91bba0SGirish Moodalbail 		break;
5966e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_DEFAULT:
5976e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
5986e91bba0SGirish Moodalbail 		break;
5996e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_POSSIBLE:
6006e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
6016e91bba0SGirish Moodalbail 		break;
6026e91bba0SGirish Moodalbail 	}
6036e91bba0SGirish Moodalbail 	if (statep->sps_status != IPADM_SUCCESS)
6046e91bba0SGirish Moodalbail 		cont = _B_FALSE;
6056e91bba0SGirish Moodalbail 	return (cont);
6066e91bba0SGirish Moodalbail }
6076e91bba0SGirish Moodalbail 
6086e91bba0SGirish Moodalbail /*
6096e91bba0SGirish Moodalbail  * Callback function called by the property walker (ipadm_walk_prop() or
6106e91bba0SGirish Moodalbail  * ipadm_walk_proptbl()), for every matched property. This function in turn
6116e91bba0SGirish Moodalbail  * calls ofmt_print() to print property information.
6126e91bba0SGirish Moodalbail  */
6136e91bba0SGirish Moodalbail boolean_t
6146e91bba0SGirish Moodalbail show_property(void *arg, const char *pname, uint_t proto)
6156e91bba0SGirish Moodalbail {
6166e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = arg;
6176e91bba0SGirish Moodalbail 
6186e91bba0SGirish Moodalbail 	statep->sps_pname = pname;
6196e91bba0SGirish Moodalbail 	statep->sps_proto = proto;
6206e91bba0SGirish Moodalbail 	statep->sps_status = IPADM_SUCCESS;
6216e91bba0SGirish Moodalbail 	ofmt_print(statep->sps_ofmt, arg);
6226e91bba0SGirish Moodalbail 
6236e91bba0SGirish Moodalbail 	/*
6246e91bba0SGirish Moodalbail 	 * if an object is not found or operation is not supported then
6256e91bba0SGirish Moodalbail 	 * stop the walker.
6266e91bba0SGirish Moodalbail 	 */
6276e91bba0SGirish Moodalbail 	if (statep->sps_status == IPADM_NOTFOUND ||
6286e91bba0SGirish Moodalbail 	    statep->sps_status == IPADM_NOTSUP)
6296e91bba0SGirish Moodalbail 		return (_B_FALSE);
6306e91bba0SGirish Moodalbail 	return (_B_TRUE);
6316e91bba0SGirish Moodalbail }
6326e91bba0SGirish Moodalbail 
6336e91bba0SGirish Moodalbail /*
6346e91bba0SGirish Moodalbail  * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
6356e91bba0SGirish Moodalbail  * for all the properties for the specified object, relavant information, will
6366e91bba0SGirish Moodalbail  * be displayed. Otherwise, for the selected property set, display relevant
6376e91bba0SGirish Moodalbail  * information
6386e91bba0SGirish Moodalbail  */
6396e91bba0SGirish Moodalbail static void
6406e91bba0SGirish Moodalbail show_properties(void *arg, int prop_class)
6416e91bba0SGirish Moodalbail {
6426e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = arg;
6436e91bba0SGirish Moodalbail 	nvlist_t 		*nvl = statep->sps_proplist;
6446e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
6456e91bba0SGirish Moodalbail 	nvpair_t		*curr_nvp;
6466e91bba0SGirish Moodalbail 	char 			*buf, *name;
6476e91bba0SGirish Moodalbail 	ipadm_status_t		status;
6486e91bba0SGirish Moodalbail 
6496e91bba0SGirish Moodalbail 	/* allocate sufficient buffer to hold a property value */
6506e91bba0SGirish Moodalbail 	if ((buf = malloc(MAXPROPVALLEN)) == NULL)
6516e91bba0SGirish Moodalbail 		die("insufficient memory");
6526e91bba0SGirish Moodalbail 	statep->sps_propval = buf;
6536e91bba0SGirish Moodalbail 
6546e91bba0SGirish Moodalbail 	/* if no properties were specified, display all the properties */
6556e91bba0SGirish Moodalbail 	if (nvl == NULL) {
6566e91bba0SGirish Moodalbail 		(void) ipadm_walk_proptbl(proto, prop_class, show_property,
6576e91bba0SGirish Moodalbail 		    statep);
6586e91bba0SGirish Moodalbail 	} else {
6596e91bba0SGirish Moodalbail 		for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
6606e91bba0SGirish Moodalbail 		    curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
6616e91bba0SGirish Moodalbail 			name = nvpair_name(curr_nvp);
6626e91bba0SGirish Moodalbail 			status = ipadm_walk_prop(name, proto, prop_class,
6636e91bba0SGirish Moodalbail 			    show_property, statep);
6646e91bba0SGirish Moodalbail 			if (status == IPADM_PROP_UNKNOWN)
6656e91bba0SGirish Moodalbail 				(void) show_property(statep, name, proto);
6666e91bba0SGirish Moodalbail 		}
6676e91bba0SGirish Moodalbail 	}
6686e91bba0SGirish Moodalbail 
6696e91bba0SGirish Moodalbail 	free(buf);
6706e91bba0SGirish Moodalbail }
6716e91bba0SGirish Moodalbail 
6726e91bba0SGirish Moodalbail /*
6736e91bba0SGirish Moodalbail  * Display information for all or specific interface properties, either for a
6746e91bba0SGirish Moodalbail  * given interface or for all the interfaces in the system.
6756e91bba0SGirish Moodalbail  */
6766e91bba0SGirish Moodalbail static void
6776e91bba0SGirish Moodalbail do_show_ifprop(int argc, char **argv, const char *use)
6786e91bba0SGirish Moodalbail {
6796e91bba0SGirish Moodalbail 	int 		option;
6806e91bba0SGirish Moodalbail 	nvlist_t 	*proplist = NULL;
6816e91bba0SGirish Moodalbail 	char		*fields_str = NULL;
6826e91bba0SGirish Moodalbail 	char 		*ifname;
6836e91bba0SGirish Moodalbail 	ofmt_handle_t	ofmt;
6846e91bba0SGirish Moodalbail 	ofmt_status_t	oferr;
6856e91bba0SGirish Moodalbail 	uint_t		ofmtflags = 0;
6866e91bba0SGirish Moodalbail 	uint_t		proto;
6876e91bba0SGirish Moodalbail 	boolean_t	m_arg = _B_FALSE;
6886e91bba0SGirish Moodalbail 	char		*protostr;
6896e91bba0SGirish Moodalbail 	ipadm_if_info_t	*ifinfo, *ifp;
6906e91bba0SGirish Moodalbail 	ipadm_status_t	status;
6916e91bba0SGirish Moodalbail 	show_prop_state_t state;
6926e91bba0SGirish Moodalbail 
6936e91bba0SGirish Moodalbail 	opterr = 0;
6946e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
6956e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
6966e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
6976e91bba0SGirish Moodalbail 	state.sps_ifprop = _B_TRUE;
6986e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
6996e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:m:co:",
7006e91bba0SGirish Moodalbail 	    show_ifprop_longopts, NULL)) != -1) {
7016e91bba0SGirish Moodalbail 		switch (option) {
7026e91bba0SGirish Moodalbail 		case 'p':
7036e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
7046e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
7056e91bba0SGirish Moodalbail 				die("invalid interface properties specified");
7066e91bba0SGirish Moodalbail 			break;
7076e91bba0SGirish Moodalbail 		case 'c':
7086e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
7096e91bba0SGirish Moodalbail 			break;
7106e91bba0SGirish Moodalbail 		case 'o':
7116e91bba0SGirish Moodalbail 			fields_str = optarg;
7126e91bba0SGirish Moodalbail 			break;
7136e91bba0SGirish Moodalbail 		case 'm':
7146e91bba0SGirish Moodalbail 			if (m_arg)
7156e91bba0SGirish Moodalbail 				die("cannot specify more than one -m");
7166e91bba0SGirish Moodalbail 			m_arg = _B_TRUE;
7176e91bba0SGirish Moodalbail 			protostr = optarg;
7186e91bba0SGirish Moodalbail 			break;
7196e91bba0SGirish Moodalbail 		default:
7206e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
7216e91bba0SGirish Moodalbail 			break;
7226e91bba0SGirish Moodalbail 		}
7236e91bba0SGirish Moodalbail 	}
7246e91bba0SGirish Moodalbail 
7256e91bba0SGirish Moodalbail 	if (optind == argc - 1)
7266e91bba0SGirish Moodalbail 		ifname = argv[optind];
7276e91bba0SGirish Moodalbail 	else if (optind != argc)
7286e91bba0SGirish Moodalbail 		die("Usage: %s", use);
7296e91bba0SGirish Moodalbail 	else
7306e91bba0SGirish Moodalbail 		ifname = NULL;
7316e91bba0SGirish Moodalbail 
7326e91bba0SGirish Moodalbail 	if (!m_arg)
7336e91bba0SGirish Moodalbail 		protostr = "ip";
7346e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
7356e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
7366e91bba0SGirish Moodalbail 
7376e91bba0SGirish Moodalbail 	state.sps_proto = proto;
7386e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
7396e91bba0SGirish Moodalbail 
7406e91bba0SGirish Moodalbail 	if (state.sps_parsable)
7416e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
7426e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
7436e91bba0SGirish Moodalbail 	ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
7446e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
7456e91bba0SGirish Moodalbail 
7466e91bba0SGirish Moodalbail 	/* retrieve interface(s) and print the properties */
7476e91bba0SGirish Moodalbail 	status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
7486e91bba0SGirish Moodalbail 	if (ifname != NULL && status == IPADM_ENXIO)
7496e91bba0SGirish Moodalbail 		die("no such object '%s': %s", ifname,
7506e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
7516e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
7526e91bba0SGirish Moodalbail 		die("Error retrieving interface(s): %s",
7536e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
7546e91bba0SGirish Moodalbail 	for (ifp = ifinfo; ifp; ifp = ifp->ifi_next) {
7556e91bba0SGirish Moodalbail 		(void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
7566e91bba0SGirish Moodalbail 		state.sps_proto = proto;
7576e91bba0SGirish Moodalbail 		show_properties(&state, IPADMPROP_CLASS_IF);
7586e91bba0SGirish Moodalbail 	}
7596e91bba0SGirish Moodalbail 	if (ifinfo)
7606e91bba0SGirish Moodalbail 		ipadm_free_if_info(ifinfo);
7616e91bba0SGirish Moodalbail 
7626e91bba0SGirish Moodalbail 	nvlist_free(proplist);
7636e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
7646e91bba0SGirish Moodalbail 
7656e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
7666e91bba0SGirish Moodalbail 		ipadm_close(iph);
7676e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
7686e91bba0SGirish Moodalbail 	}
7696e91bba0SGirish Moodalbail }
7706e91bba0SGirish Moodalbail 
7716e91bba0SGirish Moodalbail /*
7726e91bba0SGirish Moodalbail  * set/reset the interface property for a given interface.
7736e91bba0SGirish Moodalbail  */
7746e91bba0SGirish Moodalbail static void
7756e91bba0SGirish Moodalbail set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
7766e91bba0SGirish Moodalbail {
7776e91bba0SGirish Moodalbail 	int 			option;
7786e91bba0SGirish Moodalbail 	ipadm_status_t 		status = IPADM_SUCCESS;
7796e91bba0SGirish Moodalbail 	boolean_t 		p_arg = _B_FALSE;
7806e91bba0SGirish Moodalbail 	boolean_t		m_arg = _B_FALSE;
7816e91bba0SGirish Moodalbail 	char 			*ifname, *nv, *protostr;
7826e91bba0SGirish Moodalbail 	char			*prop_name, *prop_val;
7836e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_PERSIST;
7846e91bba0SGirish Moodalbail 	uint_t			proto;
7856e91bba0SGirish Moodalbail 
7866e91bba0SGirish Moodalbail 	opterr = 0;
7876e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":m:p:t",
7886e91bba0SGirish Moodalbail 	    set_ifprop_longopts, NULL)) != -1) {
7896e91bba0SGirish Moodalbail 		switch (option) {
7906e91bba0SGirish Moodalbail 		case 'p':
7916e91bba0SGirish Moodalbail 			if (p_arg)
7926e91bba0SGirish Moodalbail 				die("-p must be specified once only");
7936e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
7946e91bba0SGirish Moodalbail 
7956e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
7966e91bba0SGirish Moodalbail 			nv = optarg;
7976e91bba0SGirish Moodalbail 			break;
7986e91bba0SGirish Moodalbail 		case 'm':
7996e91bba0SGirish Moodalbail 			if (m_arg)
8006e91bba0SGirish Moodalbail 				die("-m must be specified once only");
8016e91bba0SGirish Moodalbail 			m_arg = _B_TRUE;
8026e91bba0SGirish Moodalbail 			protostr = optarg;
8036e91bba0SGirish Moodalbail 			break;
8046e91bba0SGirish Moodalbail 		case 't':
8056e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
8066e91bba0SGirish Moodalbail 			break;
8076e91bba0SGirish Moodalbail 		default:
8086e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
8096e91bba0SGirish Moodalbail 		}
8106e91bba0SGirish Moodalbail 	}
8116e91bba0SGirish Moodalbail 
8126e91bba0SGirish Moodalbail 	if (!m_arg || !p_arg || optind != argc - 1)
8136e91bba0SGirish Moodalbail 		die("Usage: %s", use);
8146e91bba0SGirish Moodalbail 
8156e91bba0SGirish Moodalbail 	ifname = argv[optind];
8166e91bba0SGirish Moodalbail 
8176e91bba0SGirish Moodalbail 	prop_name = nv;
8186e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
8196e91bba0SGirish Moodalbail 	if (prop_val != NULL)
8206e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
8216e91bba0SGirish Moodalbail 
8226e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
8236e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
8246e91bba0SGirish Moodalbail 
8256e91bba0SGirish Moodalbail 	if (reset)
8266e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
8276e91bba0SGirish Moodalbail 	else
8286e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_ACTIVE;
8296e91bba0SGirish Moodalbail 	status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
8306e91bba0SGirish Moodalbail 	    flags);
8316e91bba0SGirish Moodalbail 
8326e91bba0SGirish Moodalbail done:
8336e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
8346e91bba0SGirish Moodalbail 		if (reset)
8356e91bba0SGirish Moodalbail 			die("reset-ifprop: %s: %s",
8366e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
8376e91bba0SGirish Moodalbail 		else
8386e91bba0SGirish Moodalbail 			die("set-ifprop: %s: %s",
8396e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
8406e91bba0SGirish Moodalbail 	}
8416e91bba0SGirish Moodalbail }
8426e91bba0SGirish Moodalbail 
8436e91bba0SGirish Moodalbail static void
8446e91bba0SGirish Moodalbail do_set_ifprop(int argc, char **argv, const char *use)
8456e91bba0SGirish Moodalbail {
8466e91bba0SGirish Moodalbail 	set_ifprop(argc, argv, _B_FALSE, use);
8476e91bba0SGirish Moodalbail }
8486e91bba0SGirish Moodalbail 
8496e91bba0SGirish Moodalbail static void
8506e91bba0SGirish Moodalbail do_reset_ifprop(int argc, char **argv, const char *use)
8516e91bba0SGirish Moodalbail {
8526e91bba0SGirish Moodalbail 	set_ifprop(argc, argv, _B_TRUE, use);
8536e91bba0SGirish Moodalbail }
8546e91bba0SGirish Moodalbail 
8556e91bba0SGirish Moodalbail /*
8566e91bba0SGirish Moodalbail  * Display information for all or specific protocol properties, either for a
8576e91bba0SGirish Moodalbail  * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
8586e91bba0SGirish Moodalbail  */
8596e91bba0SGirish Moodalbail static void
8606e91bba0SGirish Moodalbail do_show_prop(int argc, char **argv, const char *use)
8616e91bba0SGirish Moodalbail {
8626e91bba0SGirish Moodalbail 	char 			option;
8636e91bba0SGirish Moodalbail 	nvlist_t 		*proplist = NULL;
8646e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
8656e91bba0SGirish Moodalbail 	char 			*protostr;
8666e91bba0SGirish Moodalbail 	show_prop_state_t 	state;
8676e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
8686e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
8696e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
8706e91bba0SGirish Moodalbail 	uint_t			proto;
8716e91bba0SGirish Moodalbail 	boolean_t		p_arg = _B_FALSE;
8726e91bba0SGirish Moodalbail 
8736e91bba0SGirish Moodalbail 	opterr = 0;
8746e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
8756e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
8766e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
8776e91bba0SGirish Moodalbail 	state.sps_modprop = _B_TRUE;
8786e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
8796e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
8806e91bba0SGirish Moodalbail 	    NULL)) != -1) {
8816e91bba0SGirish Moodalbail 		switch (option) {
8826e91bba0SGirish Moodalbail 		case 'p':
8836e91bba0SGirish Moodalbail 			if (p_arg)
8846e91bba0SGirish Moodalbail 				die("-p must be specified once only");
8856e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
8866e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
8876e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
8886e91bba0SGirish Moodalbail 				die("invalid protocol properties specified");
8896e91bba0SGirish Moodalbail 			break;
8906e91bba0SGirish Moodalbail 		case 'c':
8916e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
8926e91bba0SGirish Moodalbail 			break;
8936e91bba0SGirish Moodalbail 		case 'o':
8946e91bba0SGirish Moodalbail 			fields_str = optarg;
8956e91bba0SGirish Moodalbail 			break;
8966e91bba0SGirish Moodalbail 		default:
8976e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
8986e91bba0SGirish Moodalbail 			break;
8996e91bba0SGirish Moodalbail 		}
9006e91bba0SGirish Moodalbail 	}
9016e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
9026e91bba0SGirish Moodalbail 		protostr =  argv[optind];
9036e91bba0SGirish Moodalbail 		if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
9046e91bba0SGirish Moodalbail 			die("invalid protocol '%s' specified", protostr);
9056e91bba0SGirish Moodalbail 		state.sps_proto = proto;
9066e91bba0SGirish Moodalbail 	} else if (optind != argc) {
9076e91bba0SGirish Moodalbail 		die("Usage: %s", use);
9086e91bba0SGirish Moodalbail 	} else {
9096e91bba0SGirish Moodalbail 		if (p_arg)
9106e91bba0SGirish Moodalbail 			die("protocol must be specified when "
9116e91bba0SGirish Moodalbail 			    "property name is used");
9126e91bba0SGirish Moodalbail 		state.sps_proto = MOD_PROTO_NONE;
9136e91bba0SGirish Moodalbail 	}
9146e91bba0SGirish Moodalbail 
9156e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
9166e91bba0SGirish Moodalbail 
9176e91bba0SGirish Moodalbail 	if (state.sps_parsable)
9186e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
9196e91bba0SGirish Moodalbail 	else
9206e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_WRAP;
9216e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
9226e91bba0SGirish Moodalbail 	ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
9236e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
9246e91bba0SGirish Moodalbail 
9256e91bba0SGirish Moodalbail 	/* handles all the errors */
9266e91bba0SGirish Moodalbail 	show_properties(&state, IPADMPROP_CLASS_MODULE);
9276e91bba0SGirish Moodalbail 
9286e91bba0SGirish Moodalbail 	nvlist_free(proplist);
9296e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
9306e91bba0SGirish Moodalbail 
9316e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
9326e91bba0SGirish Moodalbail 		ipadm_close(iph);
9336e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
9346e91bba0SGirish Moodalbail 	}
9356e91bba0SGirish Moodalbail }
9366e91bba0SGirish Moodalbail 
9376e91bba0SGirish Moodalbail /*
9386e91bba0SGirish Moodalbail  * Checks to see if there are any modifiers, + or -. If there are modifiers
9396e91bba0SGirish Moodalbail  * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
9406e91bba0SGirish Moodalbail  */
9416e91bba0SGirish Moodalbail static void
9428b88711aSGirish Moodalbail parse_modifiers(const char *pstr, uint_t *flags, const char *use)
9436e91bba0SGirish Moodalbail {
9446e91bba0SGirish Moodalbail 	char *p;
9456e91bba0SGirish Moodalbail 
9468b88711aSGirish Moodalbail 	if ((p = strchr(pstr, '=')) == NULL)
9478b88711aSGirish Moodalbail 		return;
9486e91bba0SGirish Moodalbail 
9498b88711aSGirish Moodalbail 	if (p == pstr)
9508b88711aSGirish Moodalbail 		die("Invalid prop=val specified\n%s", use);
9516e91bba0SGirish Moodalbail 
9528b88711aSGirish Moodalbail 	--p;
9538b88711aSGirish Moodalbail 	if (*p == '+')
9546e91bba0SGirish Moodalbail 		*flags |= IPADM_OPT_APPEND;
9558b88711aSGirish Moodalbail 	else if (*p == '-')
9566e91bba0SGirish Moodalbail 		*flags |= IPADM_OPT_REMOVE;
9576e91bba0SGirish Moodalbail }
9586e91bba0SGirish Moodalbail 
9596e91bba0SGirish Moodalbail /*
9606e91bba0SGirish Moodalbail  * set/reset the protocol property for a given protocol.
9616e91bba0SGirish Moodalbail  */
9626e91bba0SGirish Moodalbail static void
9636e91bba0SGirish Moodalbail set_prop(int argc, char **argv, boolean_t reset, const char *use)
9646e91bba0SGirish Moodalbail {
9656e91bba0SGirish Moodalbail 	int 			option;
9666e91bba0SGirish Moodalbail 	ipadm_status_t 		status = IPADM_SUCCESS;
9676e91bba0SGirish Moodalbail 	char 			*protostr, *nv, *prop_name, *prop_val;
9686e91bba0SGirish Moodalbail 	boolean_t 		p_arg = _B_FALSE;
9696e91bba0SGirish Moodalbail 	uint_t 			proto;
9706e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_PERSIST;
9716e91bba0SGirish Moodalbail 
9726e91bba0SGirish Moodalbail 	opterr = 0;
9736e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
9746e91bba0SGirish Moodalbail 	    NULL)) != -1) {
9756e91bba0SGirish Moodalbail 		switch (option) {
9766e91bba0SGirish Moodalbail 		case 'p':
9776e91bba0SGirish Moodalbail 			if (p_arg)
9786e91bba0SGirish Moodalbail 				die("-p must be specified once only");
9796e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
9806e91bba0SGirish Moodalbail 
9816e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
9826e91bba0SGirish Moodalbail 			nv = optarg;
9836e91bba0SGirish Moodalbail 			break;
9846e91bba0SGirish Moodalbail 		case 't':
9856e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
9866e91bba0SGirish Moodalbail 			break;
9876e91bba0SGirish Moodalbail 		default:
9886e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
9896e91bba0SGirish Moodalbail 		}
9906e91bba0SGirish Moodalbail 	}
9916e91bba0SGirish Moodalbail 
9926e91bba0SGirish Moodalbail 	if (!p_arg || optind != argc - 1)
9936e91bba0SGirish Moodalbail 		die("Usage: %s", use);
9946e91bba0SGirish Moodalbail 
9956e91bba0SGirish Moodalbail 	parse_modifiers(nv, &flags, use);
9966e91bba0SGirish Moodalbail 	prop_name = nv;
9976e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
9986e91bba0SGirish Moodalbail 	if (prop_val != NULL) {
9996e91bba0SGirish Moodalbail 		if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
10006e91bba0SGirish Moodalbail 			*(prop_val - 1) = '\0';
10016e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
10026e91bba0SGirish Moodalbail 	}
10036e91bba0SGirish Moodalbail 	protostr = argv[optind];
10046e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
10056e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
10066e91bba0SGirish Moodalbail 
10076e91bba0SGirish Moodalbail 	if (reset)
10086e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
10096e91bba0SGirish Moodalbail 	else
10106e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_ACTIVE;
10116e91bba0SGirish Moodalbail 	status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
10126e91bba0SGirish Moodalbail done:
10136e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
10146e91bba0SGirish Moodalbail 		if (reset)
10156e91bba0SGirish Moodalbail 			die("reset-prop: %s: %s",
10166e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
10176e91bba0SGirish Moodalbail 		else
10186e91bba0SGirish Moodalbail 			die("set-prop: %s: %s",
10196e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
10206e91bba0SGirish Moodalbail 	}
10216e91bba0SGirish Moodalbail }
10226e91bba0SGirish Moodalbail 
10236e91bba0SGirish Moodalbail static void
10246e91bba0SGirish Moodalbail do_set_prop(int argc, char **argv, const char *use)
10256e91bba0SGirish Moodalbail {
10266e91bba0SGirish Moodalbail 	set_prop(argc, argv, _B_FALSE, use);
10276e91bba0SGirish Moodalbail }
10286e91bba0SGirish Moodalbail 
10296e91bba0SGirish Moodalbail static void
10306e91bba0SGirish Moodalbail do_reset_prop(int argc, char **argv, const char *use)
10316e91bba0SGirish Moodalbail {
10326e91bba0SGirish Moodalbail 	set_prop(argc, argv,  _B_TRUE, use);
10336e91bba0SGirish Moodalbail }
10346e91bba0SGirish Moodalbail 
10356e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
10366e91bba0SGirish Moodalbail static void
10376e91bba0SGirish Moodalbail warn(const char *format, ...)
10386e91bba0SGirish Moodalbail {
10396e91bba0SGirish Moodalbail 	va_list alist;
10406e91bba0SGirish Moodalbail 
10416e91bba0SGirish Moodalbail 	format = gettext(format);
10426e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: warning: "), progname);
10436e91bba0SGirish Moodalbail 
10446e91bba0SGirish Moodalbail 	va_start(alist, format);
10456e91bba0SGirish Moodalbail 	(void) vfprintf(stderr, format, alist);
10466e91bba0SGirish Moodalbail 	va_end(alist);
10476e91bba0SGirish Moodalbail 
10486e91bba0SGirish Moodalbail 	(void) fprintf(stderr, "\n");
10496e91bba0SGirish Moodalbail }
10506e91bba0SGirish Moodalbail 
10516e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
10526e91bba0SGirish Moodalbail static void
10536e91bba0SGirish Moodalbail die(const char *format, ...)
10546e91bba0SGirish Moodalbail {
10556e91bba0SGirish Moodalbail 	va_list alist;
10566e91bba0SGirish Moodalbail 
10576e91bba0SGirish Moodalbail 	format = gettext(format);
10586e91bba0SGirish Moodalbail 	(void) fprintf(stderr, "%s: ", progname);
10596e91bba0SGirish Moodalbail 
10606e91bba0SGirish Moodalbail 	va_start(alist, format);
10616e91bba0SGirish Moodalbail 	(void) vfprintf(stderr, format, alist);
10626e91bba0SGirish Moodalbail 	va_end(alist);
10636e91bba0SGirish Moodalbail 
10646e91bba0SGirish Moodalbail 	(void) putchar('\n');
10656e91bba0SGirish Moodalbail 
10666e91bba0SGirish Moodalbail 	ipadm_destroy_addrobj(ipaddr);
10676e91bba0SGirish Moodalbail 	ipadm_close(iph);
10686e91bba0SGirish Moodalbail 	exit(EXIT_FAILURE);
10696e91bba0SGirish Moodalbail }
10706e91bba0SGirish Moodalbail 
10716e91bba0SGirish Moodalbail static void
10726e91bba0SGirish Moodalbail die_opterr(int opt, int opterr, const char *usage)
10736e91bba0SGirish Moodalbail {
10746e91bba0SGirish Moodalbail 	switch (opterr) {
10756e91bba0SGirish Moodalbail 	case ':':
10766e91bba0SGirish Moodalbail 		die("option '-%c' requires a value\nusage: %s", opt,
10776e91bba0SGirish Moodalbail 		    gettext(usage));
10786e91bba0SGirish Moodalbail 		break;
10796e91bba0SGirish Moodalbail 	case '?':
10806e91bba0SGirish Moodalbail 	default:
10816e91bba0SGirish Moodalbail 		die("unrecognized option '-%c'\nusage: %s", opt,
10826e91bba0SGirish Moodalbail 		    gettext(usage));
10836e91bba0SGirish Moodalbail 		break;
10846e91bba0SGirish Moodalbail 	}
10856e91bba0SGirish Moodalbail }
10866e91bba0SGirish Moodalbail 
10876e91bba0SGirish Moodalbail /* PRINTFLIKE2 */
10886e91bba0SGirish Moodalbail static void
10896e91bba0SGirish Moodalbail warn_ipadmerr(ipadm_status_t err, const char *format, ...)
10906e91bba0SGirish Moodalbail {
10916e91bba0SGirish Moodalbail 	va_list alist;
10926e91bba0SGirish Moodalbail 
10936e91bba0SGirish Moodalbail 	format = gettext(format);
10946e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: warning: "), progname);
10956e91bba0SGirish Moodalbail 
10966e91bba0SGirish Moodalbail 	va_start(alist, format);
10976e91bba0SGirish Moodalbail 	(void) vfprintf(stderr, format, alist);
10986e91bba0SGirish Moodalbail 	va_end(alist);
10996e91bba0SGirish Moodalbail 
11006e91bba0SGirish Moodalbail 	(void) fprintf(stderr, "%s\n", ipadm_status2str(err));
11016e91bba0SGirish Moodalbail }
11026e91bba0SGirish Moodalbail 
11036e91bba0SGirish Moodalbail static void
11046e91bba0SGirish Moodalbail process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
11056e91bba0SGirish Moodalbail {
11066e91bba0SGirish Moodalbail 	int		option;
11076e91bba0SGirish Moodalbail 	char		*val;
11086e91bba0SGirish Moodalbail 	char		*laddr = NULL;
11096e91bba0SGirish Moodalbail 	char		*raddr = NULL;
11106e91bba0SGirish Moodalbail 	char		*save_input_arg = addrarg;
11116e91bba0SGirish Moodalbail 	boolean_t	found_mismatch = _B_FALSE;
11126e91bba0SGirish Moodalbail 	ipadm_status_t	status;
11136e91bba0SGirish Moodalbail 	enum		{ A_LOCAL, A_REMOTE };
11146e91bba0SGirish Moodalbail 	static char	*addr_optstr[] = {
11156e91bba0SGirish Moodalbail 		"local",
11166e91bba0SGirish Moodalbail 		"remote",
11176e91bba0SGirish Moodalbail 		NULL,
11186e91bba0SGirish Moodalbail 	};
11196e91bba0SGirish Moodalbail 
11206e91bba0SGirish Moodalbail 	while (*addrarg != '\0') {
11216e91bba0SGirish Moodalbail 		option = getsubopt(&addrarg, addr_optstr, &val);
11226e91bba0SGirish Moodalbail 		switch (option) {
11236e91bba0SGirish Moodalbail 		case A_LOCAL:
11246e91bba0SGirish Moodalbail 			if (laddr != NULL)
11256e91bba0SGirish Moodalbail 				die("Multiple local addresses provided");
11266e91bba0SGirish Moodalbail 			laddr = val;
11276e91bba0SGirish Moodalbail 			break;
11286e91bba0SGirish Moodalbail 		case A_REMOTE:
11296e91bba0SGirish Moodalbail 			if (raddr != NULL)
11306e91bba0SGirish Moodalbail 				die("Multiple remote addresses provided");
11316e91bba0SGirish Moodalbail 			raddr = val;
11326e91bba0SGirish Moodalbail 			break;
11336e91bba0SGirish Moodalbail 		default:
11346e91bba0SGirish Moodalbail 			if (found_mismatch)
11356e91bba0SGirish Moodalbail 				die("Invalid address provided\nusage: %s", use);
11366e91bba0SGirish Moodalbail 			found_mismatch = _B_TRUE;
11376e91bba0SGirish Moodalbail 			break;
11386e91bba0SGirish Moodalbail 		}
11396e91bba0SGirish Moodalbail 	}
11406e91bba0SGirish Moodalbail 	if (raddr != NULL && laddr == NULL)
11416e91bba0SGirish Moodalbail 		die("Missing local address\nusage: %s", use);
11426e91bba0SGirish Moodalbail 
11436e91bba0SGirish Moodalbail 	/* If only one address is provided, it is assumed a local address. */
11446e91bba0SGirish Moodalbail 	if (laddr == NULL) {
11456e91bba0SGirish Moodalbail 		if (found_mismatch)
11466e91bba0SGirish Moodalbail 			laddr = save_input_arg;
11476e91bba0SGirish Moodalbail 		else
11486e91bba0SGirish Moodalbail 			die("Missing local address\nusage: %s", use);
11496e91bba0SGirish Moodalbail 	}
11506e91bba0SGirish Moodalbail 
11516e91bba0SGirish Moodalbail 	/* Initialize the addrobj for static addresses. */
11526e91bba0SGirish Moodalbail 	status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
11536e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
11546e91bba0SGirish Moodalbail 		die("Error in creating address object: %s",
11556e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
11566e91bba0SGirish Moodalbail 	}
11576e91bba0SGirish Moodalbail 
11586e91bba0SGirish Moodalbail 	/* Set the local and remote addresses */
11596e91bba0SGirish Moodalbail 	status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
11606e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
11616e91bba0SGirish Moodalbail 		die("Error in setting local address: %s",
11626e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
11636e91bba0SGirish Moodalbail 	}
11646e91bba0SGirish Moodalbail 	if (raddr != NULL) {
11656e91bba0SGirish Moodalbail 		status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
11666e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
11676e91bba0SGirish Moodalbail 			die("Error in setting remote address: %s",
11686e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
11696e91bba0SGirish Moodalbail 		}
11706e91bba0SGirish Moodalbail 	}
11716e91bba0SGirish Moodalbail }
11726e91bba0SGirish Moodalbail 
11736e91bba0SGirish Moodalbail static void
11746e91bba0SGirish Moodalbail process_addrconf_addrargs(const char *use, char *addrarg)
11756e91bba0SGirish Moodalbail {
11766e91bba0SGirish Moodalbail 	int		option;
11776e91bba0SGirish Moodalbail 	char		*val;
11786e91bba0SGirish Moodalbail 	enum		{ P_STATELESS, P_STATEFUL };
11796e91bba0SGirish Moodalbail 	static char	*addr_optstr[] = {
11806e91bba0SGirish Moodalbail 		"stateless",
11816e91bba0SGirish Moodalbail 		"stateful",
11826e91bba0SGirish Moodalbail 		NULL,
11836e91bba0SGirish Moodalbail 	};
11846e91bba0SGirish Moodalbail 	boolean_t	stateless;
11856e91bba0SGirish Moodalbail 	boolean_t	stateless_arg = _B_FALSE;
11866e91bba0SGirish Moodalbail 	boolean_t	stateful;
11876e91bba0SGirish Moodalbail 	boolean_t	stateful_arg = _B_FALSE;
11886e91bba0SGirish Moodalbail 	ipadm_status_t	status;
11896e91bba0SGirish Moodalbail 
11906e91bba0SGirish Moodalbail 	while (*addrarg != '\0') {
11916e91bba0SGirish Moodalbail 		option = getsubopt(&addrarg, addr_optstr, &val);
11926e91bba0SGirish Moodalbail 		switch (option) {
11936e91bba0SGirish Moodalbail 		case P_STATELESS:
11946e91bba0SGirish Moodalbail 			if (stateless_arg)
11956e91bba0SGirish Moodalbail 				die("Duplicate option");
1196*7bc87895SYuri Pankov 			if (val == NULL)
1197*7bc87895SYuri Pankov 				die("Invalid argument");
11986e91bba0SGirish Moodalbail 			if (strcmp(val, "yes") == 0)
11996e91bba0SGirish Moodalbail 				stateless = _B_TRUE;
12006e91bba0SGirish Moodalbail 			else if (strcmp(val, "no") == 0)
12016e91bba0SGirish Moodalbail 				stateless = _B_FALSE;
12026e91bba0SGirish Moodalbail 			else
12036e91bba0SGirish Moodalbail 				die("Invalid argument");
12046e91bba0SGirish Moodalbail 			stateless_arg = _B_TRUE;
12056e91bba0SGirish Moodalbail 			break;
12066e91bba0SGirish Moodalbail 		case P_STATEFUL:
12076e91bba0SGirish Moodalbail 			if (stateful_arg)
12086e91bba0SGirish Moodalbail 				die("Duplicate option");
1209*7bc87895SYuri Pankov 			if (val == NULL)
1210*7bc87895SYuri Pankov 				die("Invalid argument");
12116e91bba0SGirish Moodalbail 			if (strcmp(val, "yes") == 0)
12126e91bba0SGirish Moodalbail 				stateful = _B_TRUE;
12136e91bba0SGirish Moodalbail 			else if (strcmp(val, "no") == 0)
12146e91bba0SGirish Moodalbail 				stateful = _B_FALSE;
12156e91bba0SGirish Moodalbail 			else
12166e91bba0SGirish Moodalbail 				die("Invalid argument");
12176e91bba0SGirish Moodalbail 			stateful_arg = _B_TRUE;
12186e91bba0SGirish Moodalbail 			break;
12196e91bba0SGirish Moodalbail 		default:
12206e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
12216e91bba0SGirish Moodalbail 		}
12226e91bba0SGirish Moodalbail 	}
12236e91bba0SGirish Moodalbail 
12246e91bba0SGirish Moodalbail 	if (!stateless_arg && !stateful_arg)
12256e91bba0SGirish Moodalbail 		die("Invalid arguments for option -p");
12266e91bba0SGirish Moodalbail 
12276e91bba0SGirish Moodalbail 	/* Set the addrobj fields for addrconf */
12286e91bba0SGirish Moodalbail 	if (stateless_arg) {
12296e91bba0SGirish Moodalbail 		status = ipadm_set_stateless(ipaddr, stateless);
12306e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
12316e91bba0SGirish Moodalbail 			die("Error in setting stateless option: %s",
12326e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
12336e91bba0SGirish Moodalbail 		}
12346e91bba0SGirish Moodalbail 	}
12356e91bba0SGirish Moodalbail 	if (stateful_arg) {
12366e91bba0SGirish Moodalbail 		status = ipadm_set_stateful(ipaddr, stateful);
12376e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
12386e91bba0SGirish Moodalbail 			die("Error in setting stateful option: %s",
12396e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
12406e91bba0SGirish Moodalbail 		}
12416e91bba0SGirish Moodalbail 	}
12426e91bba0SGirish Moodalbail }
12436e91bba0SGirish Moodalbail 
12446e91bba0SGirish Moodalbail /*
12456e91bba0SGirish Moodalbail  * Creates static, dhcp or addrconf addresses and associates the created
12466e91bba0SGirish Moodalbail  * addresses with the specified address object name.
12476e91bba0SGirish Moodalbail  */
12486e91bba0SGirish Moodalbail static void
12496e91bba0SGirish Moodalbail do_create_addr(int argc, char *argv[], const char *use)
12506e91bba0SGirish Moodalbail {
12516e91bba0SGirish Moodalbail 	ipadm_status_t	status;
12526e91bba0SGirish Moodalbail 	int		option;
12536e91bba0SGirish Moodalbail 	uint32_t	flags =
1254f6da83d4SAnurag S. Maskey 	    IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
12556e91bba0SGirish Moodalbail 	char		*cp;
12566e91bba0SGirish Moodalbail 	char		*atype = NULL;
12576e91bba0SGirish Moodalbail 	char		*static_arg = NULL;
12586e91bba0SGirish Moodalbail 	char		*addrconf_arg = NULL;
12596e91bba0SGirish Moodalbail 	char		*interface_id = NULL;
12606e91bba0SGirish Moodalbail 	char		*wait = NULL;
12616e91bba0SGirish Moodalbail 	boolean_t	s_opt = _B_FALSE;	/* static addr options */
12626e91bba0SGirish Moodalbail 	boolean_t	auto_opt = _B_FALSE;	/* Addrconf options */
12636e91bba0SGirish Moodalbail 	boolean_t	dhcp_opt = _B_FALSE;	/* dhcp options */
12646e91bba0SGirish Moodalbail 
12656e91bba0SGirish Moodalbail 	opterr = 0;
12666e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":T:a:di:p:w:t",
12676e91bba0SGirish Moodalbail 	    addr_longopts, NULL)) != -1) {
12686e91bba0SGirish Moodalbail 		switch (option) {
12696e91bba0SGirish Moodalbail 		case 'T':
12706e91bba0SGirish Moodalbail 			atype = optarg;
12716e91bba0SGirish Moodalbail 			break;
12726e91bba0SGirish Moodalbail 		case 'a':
12736e91bba0SGirish Moodalbail 			static_arg = optarg;
12746e91bba0SGirish Moodalbail 			s_opt = _B_TRUE;
12756e91bba0SGirish Moodalbail 			break;
12766e91bba0SGirish Moodalbail 		case 'd':
12776e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_UP;
12786e91bba0SGirish Moodalbail 			s_opt = _B_TRUE;
12796e91bba0SGirish Moodalbail 			break;
12806e91bba0SGirish Moodalbail 		case 'i':
12816e91bba0SGirish Moodalbail 			interface_id = optarg;
12826e91bba0SGirish Moodalbail 			auto_opt = _B_TRUE;
12836e91bba0SGirish Moodalbail 			break;
12846e91bba0SGirish Moodalbail 		case 'p':
12856e91bba0SGirish Moodalbail 			addrconf_arg = optarg;
12866e91bba0SGirish Moodalbail 			auto_opt = _B_TRUE;
12876e91bba0SGirish Moodalbail 			break;
12886e91bba0SGirish Moodalbail 		case 'w':
12896e91bba0SGirish Moodalbail 			wait = optarg;
12906e91bba0SGirish Moodalbail 			dhcp_opt = _B_TRUE;
12916e91bba0SGirish Moodalbail 			break;
12926e91bba0SGirish Moodalbail 		case 't':
12936e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
12946e91bba0SGirish Moodalbail 			break;
12956e91bba0SGirish Moodalbail 		default:
12966e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
12976e91bba0SGirish Moodalbail 		}
12986e91bba0SGirish Moodalbail 	}
12996e91bba0SGirish Moodalbail 	if (atype == NULL || optind != (argc - 1)) {
13006e91bba0SGirish Moodalbail 		die("Invalid arguments\nusage: %s", use);
13016e91bba0SGirish Moodalbail 	} else if ((cp = strchr(argv[optind], '/')) == NULL ||
13026e91bba0SGirish Moodalbail 	    strlen(++cp) == 0) {
13036e91bba0SGirish Moodalbail 		die("invalid address object name: %s\nusage: %s",
13046e91bba0SGirish Moodalbail 		    argv[optind], use);
13056e91bba0SGirish Moodalbail 	}
13066e91bba0SGirish Moodalbail 
13076e91bba0SGirish Moodalbail 	/*
13086e91bba0SGirish Moodalbail 	 * Allocate and initialize the addrobj based on the address type.
13096e91bba0SGirish Moodalbail 	 */
13106e91bba0SGirish Moodalbail 	if (strcmp(atype, "static") == 0) {
13116e91bba0SGirish Moodalbail 		if (static_arg == NULL || auto_opt || dhcp_opt) {
13126e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
13136e91bba0SGirish Moodalbail 			    atype, use);
13146e91bba0SGirish Moodalbail 		}
13156e91bba0SGirish Moodalbail 		process_static_addrargs(use, static_arg, argv[optind]);
13166e91bba0SGirish Moodalbail 	} else if (strcmp(atype, "dhcp") == 0) {
13176e91bba0SGirish Moodalbail 		if (auto_opt || s_opt) {
13186e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
13196e91bba0SGirish Moodalbail 			    atype, use);
13206e91bba0SGirish Moodalbail 		}
13216e91bba0SGirish Moodalbail 
13226e91bba0SGirish Moodalbail 		/* Initialize the addrobj for dhcp addresses. */
13236e91bba0SGirish Moodalbail 		status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
13246e91bba0SGirish Moodalbail 		    &ipaddr);
13256e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
13266e91bba0SGirish Moodalbail 			die("Error in creating address object: %s",
13276e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
13286e91bba0SGirish Moodalbail 		}
13296e91bba0SGirish Moodalbail 		if (wait != NULL) {
13306e91bba0SGirish Moodalbail 			int32_t ipadm_wait;
13316e91bba0SGirish Moodalbail 
13326e91bba0SGirish Moodalbail 			if (strcmp(wait, "forever") == 0) {
13336e91bba0SGirish Moodalbail 				ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
13346e91bba0SGirish Moodalbail 			} else {
13356e91bba0SGirish Moodalbail 				char *end;
13366e91bba0SGirish Moodalbail 				long timeout = strtol(wait, &end, 10);
13376e91bba0SGirish Moodalbail 
13386e91bba0SGirish Moodalbail 				if (*end != '\0' || timeout < 0)
13396e91bba0SGirish Moodalbail 					die("Invalid argument");
13406e91bba0SGirish Moodalbail 				ipadm_wait = (int32_t)timeout;
13416e91bba0SGirish Moodalbail 			}
13426e91bba0SGirish Moodalbail 			status = ipadm_set_wait_time(ipaddr, ipadm_wait);
13436e91bba0SGirish Moodalbail 			if (status != IPADM_SUCCESS) {
13446e91bba0SGirish Moodalbail 				die("Error in setting wait time: %s",
13456e91bba0SGirish Moodalbail 				    ipadm_status2str(status));
13466e91bba0SGirish Moodalbail 			}
13476e91bba0SGirish Moodalbail 		}
13486e91bba0SGirish Moodalbail 	} else if (strcmp(atype, "addrconf") == 0) {
13496e91bba0SGirish Moodalbail 		if (dhcp_opt || s_opt) {
13506e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
13516e91bba0SGirish Moodalbail 			    atype, use);
13526e91bba0SGirish Moodalbail 		}
13536e91bba0SGirish Moodalbail 
13546e91bba0SGirish Moodalbail 		/* Initialize the addrobj for dhcp addresses. */
13556e91bba0SGirish Moodalbail 		status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
13566e91bba0SGirish Moodalbail 		    argv[optind], &ipaddr);
13576e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
13586e91bba0SGirish Moodalbail 			die("Error in creating address object: %s",
13596e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
13606e91bba0SGirish Moodalbail 		}
13616e91bba0SGirish Moodalbail 		if (interface_id != NULL) {
13626e91bba0SGirish Moodalbail 			status = ipadm_set_interface_id(ipaddr, interface_id);
13636e91bba0SGirish Moodalbail 			if (status != IPADM_SUCCESS) {
13646e91bba0SGirish Moodalbail 				die("Error in setting interface ID: %s",
13656e91bba0SGirish Moodalbail 				    ipadm_status2str(status));
13666e91bba0SGirish Moodalbail 			}
13676e91bba0SGirish Moodalbail 		}
13686e91bba0SGirish Moodalbail 		if (addrconf_arg)
13696e91bba0SGirish Moodalbail 			process_addrconf_addrargs(use, addrconf_arg);
13706e91bba0SGirish Moodalbail 	} else {
13716e91bba0SGirish Moodalbail 		die("Invalid address type %s", atype);
13726e91bba0SGirish Moodalbail 	}
13736e91bba0SGirish Moodalbail 
13746e91bba0SGirish Moodalbail 	status = ipadm_create_addr(iph, ipaddr, flags);
13756e91bba0SGirish Moodalbail 	if (status == IPADM_DHCP_IPC_TIMEOUT)
13766e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
13776e91bba0SGirish Moodalbail 	else if (status != IPADM_SUCCESS)
13786e91bba0SGirish Moodalbail 		die("Could not create address: %s", ipadm_status2str(status));
13796e91bba0SGirish Moodalbail }
13806e91bba0SGirish Moodalbail 
13816e91bba0SGirish Moodalbail /*
13826e91bba0SGirish Moodalbail  * Used by some address management functions to parse the command line
13836e91bba0SGirish Moodalbail  * arguments and create `ipaddr' address object.
13846e91bba0SGirish Moodalbail  */
13856e91bba0SGirish Moodalbail static void
13866e91bba0SGirish Moodalbail process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
13876e91bba0SGirish Moodalbail     uint32_t *flags)
13886e91bba0SGirish Moodalbail {
13896e91bba0SGirish Moodalbail 	int		option;
13906e91bba0SGirish Moodalbail 
13916e91bba0SGirish Moodalbail 	opterr = 0;
13926e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
13936e91bba0SGirish Moodalbail 	    NULL)) != -1) {
13946e91bba0SGirish Moodalbail 		switch (option) {
13956e91bba0SGirish Moodalbail 		case 't':
13966e91bba0SGirish Moodalbail 			*flags &= ~IPADM_OPT_PERSIST;
13976e91bba0SGirish Moodalbail 			break;
13986e91bba0SGirish Moodalbail 		default:
13996e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
14006e91bba0SGirish Moodalbail 		}
14016e91bba0SGirish Moodalbail 	}
14026e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
14036e91bba0SGirish Moodalbail 		die("Usage: %s", use);
14046e91bba0SGirish Moodalbail 
14056e91bba0SGirish Moodalbail 	*index = optind;
14066e91bba0SGirish Moodalbail }
14076e91bba0SGirish Moodalbail 
14086e91bba0SGirish Moodalbail /*
14096e91bba0SGirish Moodalbail  * Remove an addrobj from both active and persistent configuration.
14106e91bba0SGirish Moodalbail  */
14116e91bba0SGirish Moodalbail static void
14126e91bba0SGirish Moodalbail do_delete_addr(int argc, char *argv[], const char *use)
14136e91bba0SGirish Moodalbail {
14146e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14156e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14166e91bba0SGirish Moodalbail 	int		option;
14176e91bba0SGirish Moodalbail 
14186e91bba0SGirish Moodalbail 	opterr = 0;
14196e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
14206e91bba0SGirish Moodalbail 	    NULL)) != -1) {
14216e91bba0SGirish Moodalbail 		switch (option) {
14226e91bba0SGirish Moodalbail 		case 'r':
14236e91bba0SGirish Moodalbail 			flags |= IPADM_OPT_RELEASE;
14246e91bba0SGirish Moodalbail 			break;
14256e91bba0SGirish Moodalbail 		default:
14266e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
14276e91bba0SGirish Moodalbail 		}
14286e91bba0SGirish Moodalbail 	}
14296e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
14306e91bba0SGirish Moodalbail 		die("Usage: %s", use);
14316e91bba0SGirish Moodalbail 
14326e91bba0SGirish Moodalbail 	status = ipadm_delete_addr(iph, argv[optind], flags);
14336e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
14346e91bba0SGirish Moodalbail 		die("could not delete address: %s",
14356e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
14366e91bba0SGirish Moodalbail 	}
14376e91bba0SGirish Moodalbail }
14386e91bba0SGirish Moodalbail 
14396e91bba0SGirish Moodalbail /*
14406e91bba0SGirish Moodalbail  * Enable an IP address based on the persistent configuration for that
14416e91bba0SGirish Moodalbail  * IP address
14426e91bba0SGirish Moodalbail  */
14436e91bba0SGirish Moodalbail static void
14446e91bba0SGirish Moodalbail do_enable_addr(int argc, char *argv[], const char *use)
14456e91bba0SGirish Moodalbail {
14466e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14476e91bba0SGirish Moodalbail 	int		index;
14486e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14496e91bba0SGirish Moodalbail 
14506e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
14516e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
14526e91bba0SGirish Moodalbail 		die("persistent operation not supported for enable-addr");
14536e91bba0SGirish Moodalbail 
14546e91bba0SGirish Moodalbail 	status = ipadm_enable_addr(iph, argv[index], flags);
14556e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
14566e91bba0SGirish Moodalbail 		die("could not enable address: %s", ipadm_status2str(status));
14576e91bba0SGirish Moodalbail }
14586e91bba0SGirish Moodalbail 
14596e91bba0SGirish Moodalbail /*
14606e91bba0SGirish Moodalbail  * Mark the address identified by addrobj 'up'
14616e91bba0SGirish Moodalbail  */
14626e91bba0SGirish Moodalbail static void
14636e91bba0SGirish Moodalbail do_up_addr(int argc, char *argv[], const char *use)
14646e91bba0SGirish Moodalbail {
14656e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14666e91bba0SGirish Moodalbail 	int		index;
14676e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14686e91bba0SGirish Moodalbail 
14696e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
14706e91bba0SGirish Moodalbail 	status = ipadm_up_addr(iph, argv[index], flags);
14716e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
14726e91bba0SGirish Moodalbail 		die("Could not mark the address up: %s",
14736e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
14746e91bba0SGirish Moodalbail 	}
14756e91bba0SGirish Moodalbail }
14766e91bba0SGirish Moodalbail 
14776e91bba0SGirish Moodalbail /*
14786e91bba0SGirish Moodalbail  * Disable the specified addrobj by removing it from active cofiguration
14796e91bba0SGirish Moodalbail  */
14806e91bba0SGirish Moodalbail static void
14816e91bba0SGirish Moodalbail do_disable_addr(int argc, char *argv[], const char *use)
14826e91bba0SGirish Moodalbail {
14836e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14846e91bba0SGirish Moodalbail 	int		index;
14856e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
14866e91bba0SGirish Moodalbail 
14876e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
14886e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
14896e91bba0SGirish Moodalbail 		die("persistent operation not supported for disable-addr");
14906e91bba0SGirish Moodalbail 
14916e91bba0SGirish Moodalbail 	status = ipadm_disable_addr(iph, argv[index], flags);
14926e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
14936e91bba0SGirish Moodalbail 		die("could not disable address: %s",
14946e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
14956e91bba0SGirish Moodalbail 	}
14966e91bba0SGirish Moodalbail }
14976e91bba0SGirish Moodalbail 
14986e91bba0SGirish Moodalbail /*
14996e91bba0SGirish Moodalbail  * Mark the address identified by addrobj 'down'
15006e91bba0SGirish Moodalbail  */
15016e91bba0SGirish Moodalbail static void
15026e91bba0SGirish Moodalbail do_down_addr(int argc, char *argv[], const char *use)
15036e91bba0SGirish Moodalbail {
15046e91bba0SGirish Moodalbail 	ipadm_status_t	status;
15056e91bba0SGirish Moodalbail 	int		index;
15066e91bba0SGirish Moodalbail 	uint32_t 	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
15076e91bba0SGirish Moodalbail 
15086e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
15096e91bba0SGirish Moodalbail 	status = ipadm_down_addr(iph, argv[index], flags);
15106e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
15116e91bba0SGirish Moodalbail 		die("Could not mark the address down: %s",
15126e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
15136e91bba0SGirish Moodalbail }
15146e91bba0SGirish Moodalbail 
15156e91bba0SGirish Moodalbail /*
15166e91bba0SGirish Moodalbail  * Restart DAD for static address. Extend lease duration for DHCP addresses
15176e91bba0SGirish Moodalbail  */
15186e91bba0SGirish Moodalbail static void
15196e91bba0SGirish Moodalbail do_refresh_addr(int argc, char *argv[], const char *use)
15206e91bba0SGirish Moodalbail {
15216e91bba0SGirish Moodalbail 	ipadm_status_t	status;
15226e91bba0SGirish Moodalbail 	int		option;
15236e91bba0SGirish Moodalbail 	uint32_t	flags = 0;
15246e91bba0SGirish Moodalbail 
15256e91bba0SGirish Moodalbail 	opterr = 0;
15266e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
15276e91bba0SGirish Moodalbail 	    NULL)) != -1) {
15286e91bba0SGirish Moodalbail 		switch (option) {
15296e91bba0SGirish Moodalbail 		case 'i':
15306e91bba0SGirish Moodalbail 			flags |= IPADM_OPT_INFORM;
15316e91bba0SGirish Moodalbail 			break;
15326e91bba0SGirish Moodalbail 		default:
15336e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
15346e91bba0SGirish Moodalbail 		}
15356e91bba0SGirish Moodalbail 	}
15366e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
15376e91bba0SGirish Moodalbail 		die("Usage: %s", use);
15386e91bba0SGirish Moodalbail 
15396e91bba0SGirish Moodalbail 	status = ipadm_refresh_addr(iph, argv[optind], flags);
15406e91bba0SGirish Moodalbail 	if (status == IPADM_DHCP_IPC_TIMEOUT)
15416e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
15426e91bba0SGirish Moodalbail 	else if (status != IPADM_SUCCESS)
15436e91bba0SGirish Moodalbail 		die("could not refresh address %s", ipadm_status2str(status));
15446e91bba0SGirish Moodalbail }
15456e91bba0SGirish Moodalbail 
15466e91bba0SGirish Moodalbail static void
15476e91bba0SGirish Moodalbail sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
15486e91bba0SGirish Moodalbail {
15496e91bba0SGirish Moodalbail 	socklen_t socklen;
15506e91bba0SGirish Moodalbail 	struct sockaddr *sp = (struct sockaddr *)ssp;
15516e91bba0SGirish Moodalbail 
15526e91bba0SGirish Moodalbail 	switch (ssp->ss_family) {
15536e91bba0SGirish Moodalbail 	case AF_INET:
15546e91bba0SGirish Moodalbail 		socklen = sizeof (struct sockaddr_in);
15556e91bba0SGirish Moodalbail 		break;
15566e91bba0SGirish Moodalbail 	case AF_INET6:
15576e91bba0SGirish Moodalbail 		socklen = sizeof (struct sockaddr_in6);
15586e91bba0SGirish Moodalbail 		break;
15596e91bba0SGirish Moodalbail 	default:
15606e91bba0SGirish Moodalbail 		(void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
15616e91bba0SGirish Moodalbail 		return;
15626e91bba0SGirish Moodalbail 	}
15636e91bba0SGirish Moodalbail 
15646e91bba0SGirish Moodalbail 	(void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
15656e91bba0SGirish Moodalbail 	    (NI_NOFQDN | NI_NUMERICHOST));
15666e91bba0SGirish Moodalbail }
15676e91bba0SGirish Moodalbail 
15686e91bba0SGirish Moodalbail static void
15696e91bba0SGirish Moodalbail flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
15706e91bba0SGirish Moodalbail     char *buf, uint_t bufsize)
15716e91bba0SGirish Moodalbail {
15726e91bba0SGirish Moodalbail 	int		i;
15736e91bba0SGirish Moodalbail 	boolean_t	first = _B_TRUE;
15746e91bba0SGirish Moodalbail 
15756e91bba0SGirish Moodalbail 	if (is_bits) {
15766e91bba0SGirish Moodalbail 		for (i = 0;  tbl[i].name; i++) {
15776e91bba0SGirish Moodalbail 			if ((flags & tbl[i].mask) == tbl[i].bits)
15786e91bba0SGirish Moodalbail 				(void) strlcat(buf, tbl[i].name, bufsize);
15796e91bba0SGirish Moodalbail 			else
15806e91bba0SGirish Moodalbail 				(void) strlcat(buf, "-", bufsize);
15816e91bba0SGirish Moodalbail 		}
15826e91bba0SGirish Moodalbail 	} else {
15836e91bba0SGirish Moodalbail 		for (i = 0; tbl[i].name; i++) {
15846e91bba0SGirish Moodalbail 			if ((flags & tbl[i].mask) == tbl[i].bits) {
15856e91bba0SGirish Moodalbail 				if (!first)
15866e91bba0SGirish Moodalbail 					(void) strlcat(buf, ",", bufsize);
15876e91bba0SGirish Moodalbail 				(void) strlcat(buf, tbl[i].name, bufsize);
15886e91bba0SGirish Moodalbail 				first = _B_FALSE;
15896e91bba0SGirish Moodalbail 			}
15906e91bba0SGirish Moodalbail 		}
15916e91bba0SGirish Moodalbail 	}
15926e91bba0SGirish Moodalbail }
15936e91bba0SGirish Moodalbail 
1594550b6e40SSowmini Varadhan /*
1595550b6e40SSowmini Varadhan  * return true if the address for lifname comes to us from the global zone
1596550b6e40SSowmini Varadhan  * with 'allowed-ips' constraints.
1597550b6e40SSowmini Varadhan  */
1598550b6e40SSowmini Varadhan static boolean_t
1599550b6e40SSowmini Varadhan is_from_gz(const char *lifname)
1600550b6e40SSowmini Varadhan {
1601550b6e40SSowmini Varadhan 	ipadm_if_info_t		*if_info;
1602550b6e40SSowmini Varadhan 	char			phyname[LIFNAMSIZ], *cp;
1603550b6e40SSowmini Varadhan 	boolean_t		ret = _B_FALSE;
1604550b6e40SSowmini Varadhan 	ipadm_status_t		status;
1605550b6e40SSowmini Varadhan 	zoneid_t		zoneid;
1606550b6e40SSowmini Varadhan 	ushort_t		zflags;
1607550b6e40SSowmini Varadhan 
1608550b6e40SSowmini Varadhan 	if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1609550b6e40SSowmini Varadhan 		return (_B_FALSE); /* from-gz only  makes sense in a NGZ */
1610550b6e40SSowmini Varadhan 
1611550b6e40SSowmini Varadhan 	if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1612550b6e40SSowmini Varadhan 		return (_B_FALSE);
1613550b6e40SSowmini Varadhan 
1614550b6e40SSowmini Varadhan 	if (!(zflags & ZF_NET_EXCL))
1615550b6e40SSowmini Varadhan 		return (_B_TRUE);  /* everything is from the GZ for shared-ip */
1616550b6e40SSowmini Varadhan 
1617550b6e40SSowmini Varadhan 	(void) strncpy(phyname, lifname, sizeof (phyname));
1618550b6e40SSowmini Varadhan 	if ((cp = strchr(phyname, ':')) != NULL)
1619550b6e40SSowmini Varadhan 		*cp = '\0';
1620550b6e40SSowmini Varadhan 	status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1621550b6e40SSowmini Varadhan 	if (status != IPADM_SUCCESS)
1622550b6e40SSowmini Varadhan 		return (ret);
1623550b6e40SSowmini Varadhan 
1624550b6e40SSowmini Varadhan 	if (if_info->ifi_cflags & IFIF_L3PROTECT)
1625550b6e40SSowmini Varadhan 		ret = _B_TRUE;
1626550b6e40SSowmini Varadhan 	if (if_info)
1627550b6e40SSowmini Varadhan 		ipadm_free_if_info(if_info);
1628550b6e40SSowmini Varadhan 	return (ret);
1629550b6e40SSowmini Varadhan }
1630550b6e40SSowmini Varadhan 
16316e91bba0SGirish Moodalbail static boolean_t
16326e91bba0SGirish Moodalbail print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
16336e91bba0SGirish Moodalbail {
16346e91bba0SGirish Moodalbail 	show_addr_args_t	*arg = ofarg->ofmt_cbarg;
16356e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ainfo = arg->sa_info;
16366e91bba0SGirish Moodalbail 	char			interface[LIFNAMSIZ];
16376e91bba0SGirish Moodalbail 	char			addrbuf[MAXPROPVALLEN];
16386e91bba0SGirish Moodalbail 	char			dstbuf[MAXPROPVALLEN];
16396e91bba0SGirish Moodalbail 	char			prefixlenstr[MAXPROPVALLEN];
16406e91bba0SGirish Moodalbail 	int			prefixlen;
16416e91bba0SGirish Moodalbail 	struct sockaddr_in	*sin;
16426e91bba0SGirish Moodalbail 	struct sockaddr_in6	*sin6;
16436e91bba0SGirish Moodalbail 	sa_family_t		af;
16446e91bba0SGirish Moodalbail 	char			*phyname = NULL;
16456e91bba0SGirish Moodalbail 	struct ifaddrs		*ifa = &ainfo->ia_ifa;
16466e91bba0SGirish Moodalbail 	fmask_t cflags_mask[] = {
16476e91bba0SGirish Moodalbail 		{ "U",	IA_UP,			IA_UP		},
16486e91bba0SGirish Moodalbail 		{ "u",	IA_UNNUMBERED,		IA_UNNUMBERED	},
16496e91bba0SGirish Moodalbail 		{ "p",	IA_PRIVATE,		IA_PRIVATE	},
16506e91bba0SGirish Moodalbail 		{ "t",	IA_TEMPORARY,		IA_TEMPORARY	},
16516e91bba0SGirish Moodalbail 		{ "d",	IA_DEPRECATED,		IA_DEPRECATED	},
16526e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
16536e91bba0SGirish Moodalbail 	};
16546e91bba0SGirish Moodalbail 	fmask_t pflags_mask[] = {
16556e91bba0SGirish Moodalbail 		{ "U",	IA_UP,			IA_UP		},
16566e91bba0SGirish Moodalbail 		{ "p",	IA_PRIVATE,		IA_PRIVATE	},
16576e91bba0SGirish Moodalbail 		{ "d",	IA_DEPRECATED,		IA_DEPRECATED	},
16586e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
16596e91bba0SGirish Moodalbail 	};
16606e91bba0SGirish Moodalbail 	fmask_t type[] = {
16616e91bba0SGirish Moodalbail 		{ "static",	IPADM_ADDR_STATIC,	IPADM_ALL_BITS},
16626e91bba0SGirish Moodalbail 		{ "addrconf",	IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
16636e91bba0SGirish Moodalbail 		{ "dhcp",	IPADM_ADDR_DHCP,	IPADM_ALL_BITS},
16646e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
16656e91bba0SGirish Moodalbail 	};
16666e91bba0SGirish Moodalbail 	fmask_t addr_state[] = {
16676e91bba0SGirish Moodalbail 		{ "disabled",	IFA_DISABLED,	IPADM_ALL_BITS},
16686e91bba0SGirish Moodalbail 		{ "duplicate",	IFA_DUPLICATE,	IPADM_ALL_BITS},
16696e91bba0SGirish Moodalbail 		{ "down",	IFA_DOWN,	IPADM_ALL_BITS},
16706e91bba0SGirish Moodalbail 		{ "tentative",	IFA_TENTATIVE,	IPADM_ALL_BITS},
16716e91bba0SGirish Moodalbail 		{ "ok",		IFA_OK,		IPADM_ALL_BITS},
16726e91bba0SGirish Moodalbail 		{ "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
16736e91bba0SGirish Moodalbail 		{ NULL,		0,		0	}
16746e91bba0SGirish Moodalbail 	};
16756e91bba0SGirish Moodalbail 
16766e91bba0SGirish Moodalbail 	buf[0] = '\0';
16776e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
16786e91bba0SGirish Moodalbail 	case SA_ADDROBJ:
16796e91bba0SGirish Moodalbail 		if (ainfo->ia_aobjname[0] == '\0') {
16806e91bba0SGirish Moodalbail 			(void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
16816e91bba0SGirish Moodalbail 			phyname = strrchr(interface, ':');
16826e91bba0SGirish Moodalbail 			if (phyname)
16836e91bba0SGirish Moodalbail 				*phyname = '\0';
16846e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s/%s", interface,
16856e91bba0SGirish Moodalbail 			    STR_UNKNOWN_VAL);
16866e91bba0SGirish Moodalbail 		} else {
16876e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
16886e91bba0SGirish Moodalbail 		}
16896e91bba0SGirish Moodalbail 		break;
16906e91bba0SGirish Moodalbail 	case SA_STATE:
16916e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_state, addr_state, _B_FALSE,
16926e91bba0SGirish Moodalbail 		    buf, bufsize);
16936e91bba0SGirish Moodalbail 		break;
16946e91bba0SGirish Moodalbail 	case SA_TYPE:
1695550b6e40SSowmini Varadhan 		if (is_from_gz(ifa->ifa_name))
1696550b6e40SSowmini Varadhan 			(void) snprintf(buf, bufsize, "from-gz");
1697550b6e40SSowmini Varadhan 		else
1698550b6e40SSowmini Varadhan 			flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1699550b6e40SSowmini Varadhan 			    bufsize);
17006e91bba0SGirish Moodalbail 		break;
17016e91bba0SGirish Moodalbail 	case SA_CURRENT:
17026e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
17036e91bba0SGirish Moodalbail 		break;
17046e91bba0SGirish Moodalbail 	case SA_PERSISTENT:
17056e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
17066e91bba0SGirish Moodalbail 		break;
17076e91bba0SGirish Moodalbail 	case SA_ADDR:
170864639aafSDarren Reed 		af = ifa->ifa_addr->sa_family;
17096e91bba0SGirish Moodalbail 		/*
17106e91bba0SGirish Moodalbail 		 * If the address is 0.0.0.0 or :: and the origin is DHCP,
17116e91bba0SGirish Moodalbail 		 * print STR_UNKNOWN_VAL.
17126e91bba0SGirish Moodalbail 		 */
17136e91bba0SGirish Moodalbail 		if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
17146e91bba0SGirish Moodalbail 			sin = (struct sockaddr_in *)ifa->ifa_addr;
17156e91bba0SGirish Moodalbail 			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
17166e91bba0SGirish Moodalbail 			if ((af == AF_INET &&
17176e91bba0SGirish Moodalbail 			    sin->sin_addr.s_addr == INADDR_ANY) ||
17186e91bba0SGirish Moodalbail 			    (af == AF_INET6 &&
17196e91bba0SGirish Moodalbail 			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
17206e91bba0SGirish Moodalbail 				(void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
17216e91bba0SGirish Moodalbail 				break;
17226e91bba0SGirish Moodalbail 			}
17236e91bba0SGirish Moodalbail 		}
17246e91bba0SGirish Moodalbail 		if (ifa->ifa_netmask == NULL)
17256e91bba0SGirish Moodalbail 			prefixlen = 0;
17266e91bba0SGirish Moodalbail 		else
17276e91bba0SGirish Moodalbail 			prefixlen = mask2plen(ifa->ifa_netmask);
17286e91bba0SGirish Moodalbail 		bzero(prefixlenstr, sizeof (prefixlenstr));
17296e91bba0SGirish Moodalbail 		if (prefixlen > 0) {
17306e91bba0SGirish Moodalbail 			(void) snprintf(prefixlenstr, sizeof (prefixlenstr),
17316e91bba0SGirish Moodalbail 			    "/%d", prefixlen);
17326e91bba0SGirish Moodalbail 		}
17336e91bba0SGirish Moodalbail 		bzero(addrbuf, sizeof (addrbuf));
17346e91bba0SGirish Moodalbail 		bzero(dstbuf, sizeof (dstbuf));
17356e91bba0SGirish Moodalbail 		if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
17366e91bba0SGirish Moodalbail 			/*
17376e91bba0SGirish Moodalbail 			 * Print the hostname fields if the address is not
17386e91bba0SGirish Moodalbail 			 * in active configuration.
17396e91bba0SGirish Moodalbail 			 */
17406e91bba0SGirish Moodalbail 			if (ainfo->ia_state == IFA_DISABLED) {
17416e91bba0SGirish Moodalbail 				(void) snprintf(buf, bufsize, "%s",
17426e91bba0SGirish Moodalbail 				    ainfo->ia_sname);
17436e91bba0SGirish Moodalbail 				if (ainfo->ia_dname[0] != '\0') {
17446e91bba0SGirish Moodalbail 					(void) snprintf(dstbuf, sizeof (dstbuf),
17456e91bba0SGirish Moodalbail 					    "->%s", ainfo->ia_dname);
17466e91bba0SGirish Moodalbail 					(void) strlcat(buf, dstbuf, bufsize);
17476e91bba0SGirish Moodalbail 				} else {
17486e91bba0SGirish Moodalbail 					(void) strlcat(buf, prefixlenstr,
17496e91bba0SGirish Moodalbail 					    bufsize);
17506e91bba0SGirish Moodalbail 				}
17516e91bba0SGirish Moodalbail 				break;
17526e91bba0SGirish Moodalbail 			}
175308ed54f3SVasumathi Sundaram 		}
17546e91bba0SGirish Moodalbail 		/*
17556e91bba0SGirish Moodalbail 		 * For the non-persistent case, we need to show the
17566e91bba0SGirish Moodalbail 		 * currently configured addresses for source and
17576e91bba0SGirish Moodalbail 		 * destination.
17586e91bba0SGirish Moodalbail 		 */
175908ed54f3SVasumathi Sundaram 		sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
176008ed54f3SVasumathi Sundaram 		    addrbuf, sizeof (addrbuf));
17616e91bba0SGirish Moodalbail 		if (ifa->ifa_flags & IFF_POINTOPOINT) {
17626e91bba0SGirish Moodalbail 			sockaddr2str(
17636e91bba0SGirish Moodalbail 			    (struct sockaddr_storage *)ifa->ifa_dstaddr,
17646e91bba0SGirish Moodalbail 			    dstbuf, sizeof (dstbuf));
17656e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s->%s", addrbuf,
17666e91bba0SGirish Moodalbail 			    dstbuf);
17676e91bba0SGirish Moodalbail 		} else {
17686e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s%s", addrbuf,
17696e91bba0SGirish Moodalbail 			    prefixlenstr);
17706e91bba0SGirish Moodalbail 		}
17716e91bba0SGirish Moodalbail 		break;
17726e91bba0SGirish Moodalbail 	default:
17736e91bba0SGirish Moodalbail 		die("invalid input");
17746e91bba0SGirish Moodalbail 		break;
17756e91bba0SGirish Moodalbail 	}
17766e91bba0SGirish Moodalbail 
17776e91bba0SGirish Moodalbail 	return (_B_TRUE);
17786e91bba0SGirish Moodalbail }
17796e91bba0SGirish Moodalbail 
17806e91bba0SGirish Moodalbail /*
17816e91bba0SGirish Moodalbail  * Display address information, either for the given address or
17826e91bba0SGirish Moodalbail  * for all the addresses managed by ipadm.
17836e91bba0SGirish Moodalbail  */
17846e91bba0SGirish Moodalbail static void
17856e91bba0SGirish Moodalbail do_show_addr(int argc, char *argv[], const char *use)
17866e91bba0SGirish Moodalbail {
17876e91bba0SGirish Moodalbail 	ipadm_status_t		status;
17886e91bba0SGirish Moodalbail 	show_addr_state_t	state;
17896e91bba0SGirish Moodalbail 	char			*def_fields_str = "addrobj,type,state,addr";
17906e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
17916e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ainfo;
17926e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ptr;
17936e91bba0SGirish Moodalbail 	show_addr_args_t	sargs;
17946e91bba0SGirish Moodalbail 	int			option;
17956e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
17966e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
17976e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
17986e91bba0SGirish Moodalbail 	char			*aname;
17996e91bba0SGirish Moodalbail 	char			*ifname = NULL;
18006e91bba0SGirish Moodalbail 	char			*cp;
18016e91bba0SGirish Moodalbail 	boolean_t		found = _B_FALSE;
18026e91bba0SGirish Moodalbail 
18036e91bba0SGirish Moodalbail 	opterr = 0;
18046e91bba0SGirish Moodalbail 	state.sa_parsable = _B_FALSE;
18056e91bba0SGirish Moodalbail 	state.sa_persist = _B_FALSE;
18066e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
18076e91bba0SGirish Moodalbail 	    NULL)) != -1) {
18086e91bba0SGirish Moodalbail 		switch (option) {
18096e91bba0SGirish Moodalbail 		case 'p':
18106e91bba0SGirish Moodalbail 			state.sa_parsable = _B_TRUE;
18116e91bba0SGirish Moodalbail 			break;
18126e91bba0SGirish Moodalbail 		case 'o':
18136e91bba0SGirish Moodalbail 			fields_str = optarg;
18146e91bba0SGirish Moodalbail 			break;
18156e91bba0SGirish Moodalbail 		default:
18166e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
18176e91bba0SGirish Moodalbail 			break;
18186e91bba0SGirish Moodalbail 		}
18196e91bba0SGirish Moodalbail 	}
18206e91bba0SGirish Moodalbail 	if (state.sa_parsable && fields_str == NULL)
18216e91bba0SGirish Moodalbail 		die("-p requires -o");
18226e91bba0SGirish Moodalbail 
18236e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
18246e91bba0SGirish Moodalbail 		aname = argv[optind];
18256e91bba0SGirish Moodalbail 		if ((cp = strchr(aname, '/')) == NULL)
18266e91bba0SGirish Moodalbail 			die("Invalid address object name provided");
18276e91bba0SGirish Moodalbail 		if (*(cp + 1) == '\0') {
18286e91bba0SGirish Moodalbail 			ifname = aname;
18296e91bba0SGirish Moodalbail 			*cp = '\0';
18306e91bba0SGirish Moodalbail 			aname = NULL;
18316e91bba0SGirish Moodalbail 		}
18326e91bba0SGirish Moodalbail 	} else if (optind == argc) {
18336e91bba0SGirish Moodalbail 		aname = NULL;
18346e91bba0SGirish Moodalbail 	} else {
18356e91bba0SGirish Moodalbail 		die("Usage: %s", use);
18366e91bba0SGirish Moodalbail 	}
18376e91bba0SGirish Moodalbail 
18386e91bba0SGirish Moodalbail 	if (state.sa_parsable)
18396e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
18406e91bba0SGirish Moodalbail 	if (fields_str == NULL)
18416e91bba0SGirish Moodalbail 		fields_str = def_fields_str;
18426e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
18436e91bba0SGirish Moodalbail 
18446e91bba0SGirish Moodalbail 	ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
18456e91bba0SGirish Moodalbail 	state.sa_ofmt = ofmt;
18466e91bba0SGirish Moodalbail 
18476e91bba0SGirish Moodalbail 	status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
18486e91bba0SGirish Moodalbail 	/*
18496e91bba0SGirish Moodalbail 	 * Return without printing any error, if no addresses were found,
18506e91bba0SGirish Moodalbail 	 * for the case where all addresses are requested.
18516e91bba0SGirish Moodalbail 	 */
18526e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
18536e91bba0SGirish Moodalbail 		die("Could not get address: %s", ipadm_status2str(status));
18546e91bba0SGirish Moodalbail 	if (ainfo == NULL) {
18556e91bba0SGirish Moodalbail 		ofmt_close(ofmt);
18566e91bba0SGirish Moodalbail 		return;
18576e91bba0SGirish Moodalbail 	}
18586e91bba0SGirish Moodalbail 
18596e91bba0SGirish Moodalbail 	bzero(&sargs, sizeof (sargs));
18606e91bba0SGirish Moodalbail 	sargs.sa_state = &state;
18616e91bba0SGirish Moodalbail 	for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
18626e91bba0SGirish Moodalbail 		sargs.sa_info = ptr;
18636e91bba0SGirish Moodalbail 		if (aname != NULL) {
18646e91bba0SGirish Moodalbail 			if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
18656e91bba0SGirish Moodalbail 				continue;
18666e91bba0SGirish Moodalbail 			found = _B_TRUE;
18676e91bba0SGirish Moodalbail 		}
18686e91bba0SGirish Moodalbail 		ofmt_print(state.sa_ofmt, &sargs);
18696e91bba0SGirish Moodalbail 	}
18706e91bba0SGirish Moodalbail 	if (ainfo)
18716e91bba0SGirish Moodalbail 		ipadm_free_addr_info(ainfo);
18726e91bba0SGirish Moodalbail 	if (aname != NULL && !found)
18736e91bba0SGirish Moodalbail 		die("Address object not found");
18746e91bba0SGirish Moodalbail }
18756e91bba0SGirish Moodalbail 
18766e91bba0SGirish Moodalbail static boolean_t
18776e91bba0SGirish Moodalbail print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
18786e91bba0SGirish Moodalbail {
18796e91bba0SGirish Moodalbail 	show_if_args_t		*arg = ofarg->ofmt_cbarg;
18806e91bba0SGirish Moodalbail 	ipadm_if_info_t		*ifinfo = arg->si_info;
18816e91bba0SGirish Moodalbail 	char			*ifname = ifinfo->ifi_name;
18826e91bba0SGirish Moodalbail 	fmask_t intf_state[] = {
18836e91bba0SGirish Moodalbail 		{ "ok",		IFIS_OK,	IPADM_ALL_BITS},
18846e91bba0SGirish Moodalbail 		{ "down",	IFIS_DOWN,	IPADM_ALL_BITS},
18856e91bba0SGirish Moodalbail 		{ "disabled",	IFIS_DISABLED,	IPADM_ALL_BITS},
18866e91bba0SGirish Moodalbail 		{ "failed",	IFIS_FAILED,	IPADM_ALL_BITS},
18876e91bba0SGirish Moodalbail 		{ "offline",	IFIS_OFFLINE,	IPADM_ALL_BITS},
18886e91bba0SGirish Moodalbail 		{ NULL,		0,		0	}
18896e91bba0SGirish Moodalbail 	};
18906e91bba0SGirish Moodalbail 	fmask_t intf_pflags[] = {
18916e91bba0SGirish Moodalbail 		{ "s",	IFIF_STANDBY,		IFIF_STANDBY	},
18926e91bba0SGirish Moodalbail 		{ "4",	IFIF_IPV4,		IFIF_IPV4	},
18936e91bba0SGirish Moodalbail 		{ "6",	IFIF_IPV6,		IFIF_IPV6	},
18946e91bba0SGirish Moodalbail 		{ NULL,	0,			0		}
18956e91bba0SGirish Moodalbail 	};
18966e91bba0SGirish Moodalbail 	fmask_t intf_cflags[] = {
18976e91bba0SGirish Moodalbail 		{ "b",	IFIF_BROADCAST,		IFIF_BROADCAST	},
18986e91bba0SGirish Moodalbail 		{ "m",	IFIF_MULTICAST,		IFIF_MULTICAST	},
18996e91bba0SGirish Moodalbail 		{ "p",	IFIF_POINTOPOINT,	IFIF_POINTOPOINT},
19006e91bba0SGirish Moodalbail 		{ "v",	IFIF_VIRTUAL,		IFIF_VIRTUAL	},
19016e91bba0SGirish Moodalbail 		{ "I",	IFIF_IPMP,		IFIF_IPMP	},
19026e91bba0SGirish Moodalbail 		{ "s",	IFIF_STANDBY,		IFIF_STANDBY	},
19036e91bba0SGirish Moodalbail 		{ "i",	IFIF_INACTIVE,		IFIF_INACTIVE	},
19046e91bba0SGirish Moodalbail 		{ "V",	IFIF_VRRP,		IFIF_VRRP	},
19056e91bba0SGirish Moodalbail 		{ "a",	IFIF_NOACCEPT,		IFIF_NOACCEPT	},
1906550b6e40SSowmini Varadhan 		{ "Z",	IFIF_L3PROTECT,		IFIF_L3PROTECT	},
19076e91bba0SGirish Moodalbail 		{ "4",	IFIF_IPV4,		IFIF_IPV4	},
19086e91bba0SGirish Moodalbail 		{ "6",	IFIF_IPV6,		IFIF_IPV6	},
19096e91bba0SGirish Moodalbail 		{ NULL,	0,			0		}
19106e91bba0SGirish Moodalbail 	};
19116e91bba0SGirish Moodalbail 
19126e91bba0SGirish Moodalbail 	buf[0] = '\0';
19136e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
19146e91bba0SGirish Moodalbail 	case SI_IFNAME:
19156e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", ifname);
19166e91bba0SGirish Moodalbail 		break;
19176e91bba0SGirish Moodalbail 	case SI_STATE:
19186e91bba0SGirish Moodalbail 		flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
19196e91bba0SGirish Moodalbail 		    buf, bufsize);
19206e91bba0SGirish Moodalbail 		break;
19216e91bba0SGirish Moodalbail 	case SI_CURRENT:
19226e91bba0SGirish Moodalbail 		flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
19236e91bba0SGirish Moodalbail 		    buf, bufsize);
19246e91bba0SGirish Moodalbail 		break;
19256e91bba0SGirish Moodalbail 	case SI_PERSISTENT:
19266e91bba0SGirish Moodalbail 		flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
19276e91bba0SGirish Moodalbail 		    buf, bufsize);
19286e91bba0SGirish Moodalbail 		break;
19296e91bba0SGirish Moodalbail 	default:
19306e91bba0SGirish Moodalbail 		die("invalid input");
19316e91bba0SGirish Moodalbail 		break;
19326e91bba0SGirish Moodalbail 	}
19336e91bba0SGirish Moodalbail 
19346e91bba0SGirish Moodalbail 	return (_B_TRUE);
19356e91bba0SGirish Moodalbail }
19366e91bba0SGirish Moodalbail 
19376e91bba0SGirish Moodalbail /*
19386e91bba0SGirish Moodalbail  * Display interface information, either for the given interface or
19396e91bba0SGirish Moodalbail  * for all the interfaces in the system.
19406e91bba0SGirish Moodalbail  */
19416e91bba0SGirish Moodalbail static void
19426e91bba0SGirish Moodalbail do_show_if(int argc, char *argv[], const char *use)
19436e91bba0SGirish Moodalbail {
19446e91bba0SGirish Moodalbail 	ipadm_status_t		status;
19456e91bba0SGirish Moodalbail 	show_if_state_t		state;
19466e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
19476e91bba0SGirish Moodalbail 	ipadm_if_info_t		*if_info, *ptr;
19486e91bba0SGirish Moodalbail 	show_if_args_t		sargs;
19496e91bba0SGirish Moodalbail 	int			option;
19506e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
19516e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
19526e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
19536e91bba0SGirish Moodalbail 	char			*ifname = NULL;
19546e91bba0SGirish Moodalbail 
19556e91bba0SGirish Moodalbail 	opterr = 0;
19566e91bba0SGirish Moodalbail 	state.si_parsable = _B_FALSE;
19576e91bba0SGirish Moodalbail 
19586e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
19596e91bba0SGirish Moodalbail 	    NULL)) != -1) {
19606e91bba0SGirish Moodalbail 		switch (option) {
19616e91bba0SGirish Moodalbail 		case 'p':
19626e91bba0SGirish Moodalbail 			state.si_parsable = _B_TRUE;
19636e91bba0SGirish Moodalbail 			break;
19646e91bba0SGirish Moodalbail 		case 'o':
19656e91bba0SGirish Moodalbail 			fields_str = optarg;
19666e91bba0SGirish Moodalbail 			break;
19676e91bba0SGirish Moodalbail 		default:
19686e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
19696e91bba0SGirish Moodalbail 			break;
19706e91bba0SGirish Moodalbail 		}
19716e91bba0SGirish Moodalbail 	}
19726e91bba0SGirish Moodalbail 	if (optind == argc - 1)
19736e91bba0SGirish Moodalbail 		ifname = argv[optind];
19746e91bba0SGirish Moodalbail 	else if (optind != argc)
19756e91bba0SGirish Moodalbail 		die("Usage: %s", use);
19766e91bba0SGirish Moodalbail 	if (state.si_parsable)
19776e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
19786e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
19796e91bba0SGirish Moodalbail 	ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
19806e91bba0SGirish Moodalbail 	state.si_ofmt = ofmt;
19816e91bba0SGirish Moodalbail 	bzero(&sargs, sizeof (sargs));
19826e91bba0SGirish Moodalbail 	sargs.si_state = &state;
19836e91bba0SGirish Moodalbail 	status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
19846e91bba0SGirish Moodalbail 	/*
19856e91bba0SGirish Moodalbail 	 * Return without printing any error, if no addresses were found.
19866e91bba0SGirish Moodalbail 	 */
19876e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
19886e91bba0SGirish Moodalbail 		die("Could not get interface(s): %s",
19896e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
19906e91bba0SGirish Moodalbail 	}
19916e91bba0SGirish Moodalbail 
19926e91bba0SGirish Moodalbail 	for (ptr = if_info; ptr; ptr = ptr->ifi_next) {
19936e91bba0SGirish Moodalbail 		sargs.si_info = ptr;
19946e91bba0SGirish Moodalbail 		ofmt_print(state.si_ofmt, &sargs);
19956e91bba0SGirish Moodalbail 	}
19966e91bba0SGirish Moodalbail 	if (if_info)
19976e91bba0SGirish Moodalbail 		ipadm_free_if_info(if_info);
19986e91bba0SGirish Moodalbail }
19996e91bba0SGirish Moodalbail 
20006e91bba0SGirish Moodalbail /*
20016e91bba0SGirish Moodalbail  * set/reset the address property for a given address
20026e91bba0SGirish Moodalbail  */
20036e91bba0SGirish Moodalbail static void
20046e91bba0SGirish Moodalbail set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
20056e91bba0SGirish Moodalbail {
20066e91bba0SGirish Moodalbail 	int 			option;
20076e91bba0SGirish Moodalbail 	ipadm_status_t 		status = IPADM_SUCCESS;
20086e91bba0SGirish Moodalbail 	boolean_t 		p_arg = _B_FALSE;
20096e91bba0SGirish Moodalbail 	char 			*nv, *aobjname;
20106e91bba0SGirish Moodalbail 	char			*prop_name, *prop_val;
20116e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
20126e91bba0SGirish Moodalbail 
20136e91bba0SGirish Moodalbail 	opterr = 0;
20146e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
20156e91bba0SGirish Moodalbail 	    NULL)) != -1) {
20166e91bba0SGirish Moodalbail 		switch (option) {
20176e91bba0SGirish Moodalbail 		case 'p':
20186e91bba0SGirish Moodalbail 			if (p_arg)
20196e91bba0SGirish Moodalbail 				die("-p must be specified once only");
20206e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
20216e91bba0SGirish Moodalbail 
20226e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
20236e91bba0SGirish Moodalbail 			nv = optarg;
20246e91bba0SGirish Moodalbail 			break;
20256e91bba0SGirish Moodalbail 		case 't':
20266e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
20276e91bba0SGirish Moodalbail 			break;
20286e91bba0SGirish Moodalbail 		default:
20296e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
20306e91bba0SGirish Moodalbail 		}
20316e91bba0SGirish Moodalbail 	}
20326e91bba0SGirish Moodalbail 
20336e91bba0SGirish Moodalbail 	if (!p_arg || optind != (argc - 1))
20346e91bba0SGirish Moodalbail 		die("Usage: %s", use);
20356e91bba0SGirish Moodalbail 
20366e91bba0SGirish Moodalbail 	prop_name = nv;
20376e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
20386e91bba0SGirish Moodalbail 	if (prop_val != NULL)
20396e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
20406e91bba0SGirish Moodalbail 	aobjname = argv[optind];
20416e91bba0SGirish Moodalbail 	if (reset)
20426e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
20436e91bba0SGirish Moodalbail 	status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
20446e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
20456e91bba0SGirish Moodalbail 		if (reset)
20466e91bba0SGirish Moodalbail 			die("reset-addrprop: %s: %s", prop_name,
20476e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
20486e91bba0SGirish Moodalbail 		else
20496e91bba0SGirish Moodalbail 			die("set-addrprop: %s: %s", prop_name,
20506e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
20516e91bba0SGirish Moodalbail 	}
20526e91bba0SGirish Moodalbail }
20536e91bba0SGirish Moodalbail 
20546e91bba0SGirish Moodalbail /*
20556e91bba0SGirish Moodalbail  * Sets a property on an address object.
20566e91bba0SGirish Moodalbail  */
20576e91bba0SGirish Moodalbail static void
20586e91bba0SGirish Moodalbail do_set_addrprop(int argc, char **argv, const char *use)
20596e91bba0SGirish Moodalbail {
20606e91bba0SGirish Moodalbail 	set_addrprop(argc, argv, _B_FALSE, use);
20616e91bba0SGirish Moodalbail }
20626e91bba0SGirish Moodalbail 
20636e91bba0SGirish Moodalbail /*
20646e91bba0SGirish Moodalbail  * Resets a property to its default value on an address object.
20656e91bba0SGirish Moodalbail  */
20666e91bba0SGirish Moodalbail static void
20676e91bba0SGirish Moodalbail do_reset_addrprop(int argc, char **argv, const char *use)
20686e91bba0SGirish Moodalbail {
20696e91bba0SGirish Moodalbail 	set_addrprop(argc, argv,  _B_TRUE, use);
20706e91bba0SGirish Moodalbail }
20716e91bba0SGirish Moodalbail 
20726e91bba0SGirish Moodalbail /*
20736e91bba0SGirish Moodalbail  * Display information for all or specific address properties, either for a
20746e91bba0SGirish Moodalbail  * given address or for all the addresses in the system.
20756e91bba0SGirish Moodalbail  */
20766e91bba0SGirish Moodalbail static void
20776e91bba0SGirish Moodalbail do_show_addrprop(int argc, char *argv[], const char *use)
20786e91bba0SGirish Moodalbail {
20796e91bba0SGirish Moodalbail 	int 			option;
20806e91bba0SGirish Moodalbail 	nvlist_t 		*proplist = NULL;
20816e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
20826e91bba0SGirish Moodalbail 	show_prop_state_t 	state;
20836e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
20846e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
20856e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
20866e91bba0SGirish Moodalbail 	char			*aobjname;
20876e91bba0SGirish Moodalbail 	char			*ifname = NULL;
20886e91bba0SGirish Moodalbail 	char			*cp;
20896e91bba0SGirish Moodalbail 
20906e91bba0SGirish Moodalbail 	opterr = 0;
20916e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
20926e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
20936e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
20946e91bba0SGirish Moodalbail 	state.sps_addrprop = _B_TRUE;
20956e91bba0SGirish Moodalbail 	state.sps_proto = MOD_PROTO_NONE;
20966e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
20976e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:i:cPo:",
20986e91bba0SGirish Moodalbail 	    show_prop_longopts, NULL)) != -1) {
20996e91bba0SGirish Moodalbail 		switch (option) {
21006e91bba0SGirish Moodalbail 		case 'p':
21016e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
21026e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
21036e91bba0SGirish Moodalbail 				die("invalid interface properties specified");
21046e91bba0SGirish Moodalbail 			break;
21056e91bba0SGirish Moodalbail 		case 'c':
21066e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
21076e91bba0SGirish Moodalbail 			break;
21086e91bba0SGirish Moodalbail 		case 'o':
21096e91bba0SGirish Moodalbail 			fields_str = optarg;
21106e91bba0SGirish Moodalbail 			break;
21116e91bba0SGirish Moodalbail 		default:
21126e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
21136e91bba0SGirish Moodalbail 			break;
21146e91bba0SGirish Moodalbail 		}
21156e91bba0SGirish Moodalbail 	}
21166e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
21176e91bba0SGirish Moodalbail 		aobjname = argv[optind];
21186e91bba0SGirish Moodalbail 		cp = strchr(aobjname, '/');
21196e91bba0SGirish Moodalbail 		if (cp == NULL)
21206e91bba0SGirish Moodalbail 			die("Invalid address object name provided");
21216e91bba0SGirish Moodalbail 		if (*(cp + 1) == '\0') {
21226e91bba0SGirish Moodalbail 			ifname = aobjname;
21236e91bba0SGirish Moodalbail 			*cp = '\0';
21246e91bba0SGirish Moodalbail 			aobjname = NULL;
21256e91bba0SGirish Moodalbail 		}
21266e91bba0SGirish Moodalbail 	} else if (optind == argc) {
21276e91bba0SGirish Moodalbail 		aobjname = NULL;
21286e91bba0SGirish Moodalbail 	} else {
21296e91bba0SGirish Moodalbail 		die("Usage: %s", use);
21306e91bba0SGirish Moodalbail 	}
21316e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
21326e91bba0SGirish Moodalbail 	if (state.sps_parsable)
21336e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
21346e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
21356e91bba0SGirish Moodalbail 	ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
21366e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
21376e91bba0SGirish Moodalbail 
21386e91bba0SGirish Moodalbail 	if (aobjname != NULL) {
21396e91bba0SGirish Moodalbail 		(void) strlcpy(state.sps_aobjname, aobjname,
21406e91bba0SGirish Moodalbail 		    sizeof (state.sps_aobjname));
21416e91bba0SGirish Moodalbail 		show_properties(&state, IPADMPROP_CLASS_ADDR);
21426e91bba0SGirish Moodalbail 	} else {
21436e91bba0SGirish Moodalbail 		ipadm_addr_info_t	*ainfop = NULL;
21446e91bba0SGirish Moodalbail 		ipadm_addr_info_t	*ptr;
21456e91bba0SGirish Moodalbail 		ipadm_status_t		status;
21466e91bba0SGirish Moodalbail 
21476e91bba0SGirish Moodalbail 		status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
21486e91bba0SGirish Moodalbail 		/*
21496e91bba0SGirish Moodalbail 		 * Return without printing any error, if no addresses were
21506e91bba0SGirish Moodalbail 		 * found.
21516e91bba0SGirish Moodalbail 		 */
21526e91bba0SGirish Moodalbail 		if (status == IPADM_NOTFOUND)
21536e91bba0SGirish Moodalbail 			return;
21546e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
21556e91bba0SGirish Moodalbail 			die("Error retrieving address: %s",
21566e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
21576e91bba0SGirish Moodalbail 		}
21586e91bba0SGirish Moodalbail 		for (ptr = ainfop; ptr; ptr = IA_NEXT(ptr)) {
21596e91bba0SGirish Moodalbail 			aobjname = ptr->ia_aobjname;
21606e91bba0SGirish Moodalbail 			if (aobjname[0] == '\0' ||
21616e91bba0SGirish Moodalbail 			    ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
21626e91bba0SGirish Moodalbail 				continue;
21636e91bba0SGirish Moodalbail 			}
21646e91bba0SGirish Moodalbail 			(void) strlcpy(state.sps_aobjname, aobjname,
21656e91bba0SGirish Moodalbail 			    sizeof (state.sps_aobjname));
21666e91bba0SGirish Moodalbail 			show_properties(&state, IPADMPROP_CLASS_ADDR);
21676e91bba0SGirish Moodalbail 		}
21686e91bba0SGirish Moodalbail 		ipadm_free_addr_info(ainfop);
21696e91bba0SGirish Moodalbail 	}
21706e91bba0SGirish Moodalbail 	nvlist_free(proplist);
21716e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
21726e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
21736e91bba0SGirish Moodalbail 		ipadm_close(iph);
21746e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
21756e91bba0SGirish Moodalbail 	}
21766e91bba0SGirish Moodalbail }
21776e91bba0SGirish Moodalbail 
21786e91bba0SGirish Moodalbail static void
21796e91bba0SGirish Moodalbail ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
21806e91bba0SGirish Moodalbail     ofmt_handle_t ofmt)
21816e91bba0SGirish Moodalbail {
21826e91bba0SGirish Moodalbail 	char buf[OFMT_BUFSIZE];
21836e91bba0SGirish Moodalbail 
21846e91bba0SGirish Moodalbail 	if (oferr == OFMT_SUCCESS)
21856e91bba0SGirish Moodalbail 		return;
21866e91bba0SGirish Moodalbail 	(void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
21876e91bba0SGirish Moodalbail 	/*
21886e91bba0SGirish Moodalbail 	 * All errors are considered fatal in parsable mode.
21896e91bba0SGirish Moodalbail 	 * NOMEM errors are always fatal, regardless of mode.
21906e91bba0SGirish Moodalbail 	 * For other errors, we print diagnostics in human-readable
21916e91bba0SGirish Moodalbail 	 * mode and processs what we can.
21926e91bba0SGirish Moodalbail 	 */
21936e91bba0SGirish Moodalbail 	if (parsable || oferr == OFMT_ENOFIELDS) {
21946e91bba0SGirish Moodalbail 		ofmt_close(ofmt);
21956e91bba0SGirish Moodalbail 		die(buf);
21966e91bba0SGirish Moodalbail 	} else {
21976e91bba0SGirish Moodalbail 		warn(buf);
21986e91bba0SGirish Moodalbail 	}
21996e91bba0SGirish Moodalbail }
22006e91bba0SGirish Moodalbail 
22016e91bba0SGirish Moodalbail /*
22026e91bba0SGirish Moodalbail  * check if the `pstr' adheres to following syntax
22036e91bba0SGirish Moodalbail  *	- prop=<value[,...]>	(for set)
22046e91bba0SGirish Moodalbail  *	- prop			(for reset)
22056e91bba0SGirish Moodalbail  */
22066e91bba0SGirish Moodalbail static void
22076e91bba0SGirish Moodalbail ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
22086e91bba0SGirish Moodalbail {
22096e91bba0SGirish Moodalbail 	char	*nv;
22106e91bba0SGirish Moodalbail 
22116e91bba0SGirish Moodalbail 	nv = strchr(pstr, '=');
22126e91bba0SGirish Moodalbail 	if (reset) {
22136e91bba0SGirish Moodalbail 		if (nv != NULL)
22146e91bba0SGirish Moodalbail 			die("incorrect syntax used for -p.\n%s", use);
22156e91bba0SGirish Moodalbail 	} else {
22166e91bba0SGirish Moodalbail 		if (nv == NULL || *++nv == '\0')
22176e91bba0SGirish Moodalbail 			die("please specify the value to be set.\n%s", use);
22186e91bba0SGirish Moodalbail 		nv = strchr(nv, '=');
22196e91bba0SGirish Moodalbail 		/* cannot have multiple 'prop=val' for single -p */
22206e91bba0SGirish Moodalbail 		if (nv != NULL)
22216e91bba0SGirish Moodalbail 			die("cannot specify more than one prop=val at "
22226e91bba0SGirish Moodalbail 			    "a time.\n%s", use);
22236e91bba0SGirish Moodalbail 	}
22246e91bba0SGirish Moodalbail }
2225