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  */
218c8556f9SYuri Pankov 
226e91bba0SGirish Moodalbail /*
238b88711aSGirish Moodalbail  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24cbf54fedSJohn Levon  * Copyright (c) 2018, Joyent, Inc.
25d7c57852SGary Mills  * Copyright 2017 Gary Mills
26b31320a7SChris Fraire  * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
27a73be61aSHans Rosenfeld  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
28f3f00a64SAndy Fiddaman  * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
296e91bba0SGirish Moodalbail  */
308c8556f9SYuri Pankov 
316e91bba0SGirish Moodalbail #include <arpa/inet.h>
326e91bba0SGirish Moodalbail #include <errno.h>
336e91bba0SGirish Moodalbail #include <getopt.h>
346e91bba0SGirish Moodalbail #include <inet/ip.h>
356e91bba0SGirish Moodalbail #include <inet/iptun.h>
366e91bba0SGirish Moodalbail #include <inet/tunables.h>
376e91bba0SGirish Moodalbail #include <libdladm.h>
386e91bba0SGirish Moodalbail #include <libdliptun.h>
396e91bba0SGirish Moodalbail #include <libdllink.h>
406e91bba0SGirish Moodalbail #include <libinetutil.h>
416e91bba0SGirish Moodalbail #include <libipadm.h>
42a73be61aSHans Rosenfeld #include <ipmp.h>
43a73be61aSHans Rosenfeld #include <ipmp_admin.h>
446e91bba0SGirish Moodalbail #include <locale.h>
456e91bba0SGirish Moodalbail #include <netdb.h>
466e91bba0SGirish Moodalbail #include <netinet/in.h>
476e91bba0SGirish Moodalbail #include <ofmt.h>
486e91bba0SGirish Moodalbail #include <stdarg.h>
496e91bba0SGirish Moodalbail #include <stddef.h>
506e91bba0SGirish Moodalbail #include <stdio.h>
516e91bba0SGirish Moodalbail #include <stdlib.h>
526e91bba0SGirish Moodalbail #include <string.h>
536e91bba0SGirish Moodalbail #include <strings.h>
546e91bba0SGirish Moodalbail #include <sys/stat.h>
556e91bba0SGirish Moodalbail #include <sys/types.h>
566e91bba0SGirish Moodalbail #include <zone.h>
57a73be61aSHans Rosenfeld #include <sys/list.h>
58a73be61aSHans Rosenfeld #include <stddef.h>
596e91bba0SGirish Moodalbail 
606e91bba0SGirish Moodalbail #define	STR_UNKNOWN_VAL	"?"
616e91bba0SGirish Moodalbail #define	LIFC_DEFAULT	(LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
626e91bba0SGirish Moodalbail 			LIFC_UNDER_IPMP)
636e91bba0SGirish Moodalbail 
64a73be61aSHans Rosenfeld static void do_create_ip_common(int, char **, const char *, uint32_t);
65a73be61aSHans Rosenfeld 
666e91bba0SGirish Moodalbail typedef void cmdfunc_t(int, char **, const char *);
67f3f00a64SAndy Fiddaman static cmdfunc_t do_help;
68a73be61aSHans Rosenfeld static cmdfunc_t do_create_ip, do_delete_ip;
69a73be61aSHans Rosenfeld static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
70a73be61aSHans Rosenfeld static cmdfunc_t do_disable_if, do_enable_if, do_show_if;
71a73be61aSHans Rosenfeld static cmdfunc_t do_set_ifprop, do_reset_ifprop, do_show_ifprop;
72a73be61aSHans Rosenfeld static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr, do_refresh_addr;
73a73be61aSHans Rosenfeld static cmdfunc_t do_disable_addr, do_enable_addr, do_down_addr, do_up_addr;
74a73be61aSHans Rosenfeld static cmdfunc_t do_set_addrprop, do_reset_addrprop, do_show_addrprop;
75a73be61aSHans Rosenfeld static cmdfunc_t do_set_prop, do_reset_prop, do_show_prop;
766e91bba0SGirish Moodalbail 
776e91bba0SGirish Moodalbail typedef struct	cmd {
786e91bba0SGirish Moodalbail 	char		*c_name;
796e91bba0SGirish Moodalbail 	cmdfunc_t	*c_fn;
806e91bba0SGirish Moodalbail 	const char	*c_usage;
816e91bba0SGirish Moodalbail } cmd_t;
826e91bba0SGirish Moodalbail 
836e91bba0SGirish Moodalbail static cmd_t	cmds[] = {
84f3f00a64SAndy Fiddaman 	{ "help",	do_help,	NULL },
856e91bba0SGirish Moodalbail 	/* interface management related sub-commands */
86a73be61aSHans Rosenfeld 	{ "create-if", do_create_ip, "\tcreate-if\t[-t] <interface>"	},
87a73be61aSHans Rosenfeld 	{ "create-ip", do_create_ip, "\tcreate-ip\t[-t] <interface>"	},
88a73be61aSHans Rosenfeld 	{ "delete-if", do_delete_ip, "\tdelete-if\t<interface>\n"	},
89a73be61aSHans Rosenfeld 	{ "delete-ip", do_delete_ip, "\tdelete-ip\t<interface>\n"	},
90a73be61aSHans Rosenfeld 
91a73be61aSHans Rosenfeld 	{ "create-ipmp", do_create_ipmp,
92a73be61aSHans Rosenfeld 	    "\tcreate-ipmp\t[-t] [-i <interface>[,<interface>]...] "
93a73be61aSHans Rosenfeld 	    "<ipmp-interface>"						},
94a73be61aSHans Rosenfeld 	{ "delete-ipmp", do_delete_ip,
95a73be61aSHans Rosenfeld 	    "\tdelete-ipmp\t<ipmp-interface>"				},
96a73be61aSHans Rosenfeld 	{ "add-ipmp", do_add_ipmp,
97a73be61aSHans Rosenfeld 	    "\tadd-ipmp\t[-t] -i <interface>[,<interface>]... "
98a73be61aSHans Rosenfeld 	    "<ipmp-interface>"						},
99a73be61aSHans Rosenfeld 	{ "remove-ipmp", do_remove_ipmp,
100a73be61aSHans Rosenfeld 	    "\tremove-ipmp\t[-t] -i <interface>[,<interface>]... "
101a73be61aSHans Rosenfeld 	    "<ipmp-interface>\n"					},
102a73be61aSHans Rosenfeld 
103a73be61aSHans Rosenfeld 	{ "disable-if", do_disable_if, "\tdisable-if\t-t <interface>"	},
104a73be61aSHans Rosenfeld 	{ "enable-if", do_enable_if, "\tenable-if\t-t <interface>"	},
105a73be61aSHans Rosenfeld 	{ "show-if", do_show_if,
1066e91bba0SGirish Moodalbail 	    "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"	},
107a73be61aSHans Rosenfeld 
1086e91bba0SGirish Moodalbail 	{ "set-ifprop",	do_set_ifprop,
1096e91bba0SGirish Moodalbail 	    "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
110467e811cSToomas Soome 	    "<interface>"						},
1116e91bba0SGirish Moodalbail 	{ "reset-ifprop", do_reset_ifprop,
1126e91bba0SGirish Moodalbail 	    "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>"	},
1136e91bba0SGirish Moodalbail 	{ "show-ifprop", do_show_ifprop,
1146e91bba0SGirish Moodalbail 	    "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
115467e811cSToomas Soome 	    "\t\t\t[-m <protocol>] [interface]\n"			},
1166e91bba0SGirish Moodalbail 
1176e91bba0SGirish Moodalbail 	/* address management related sub-commands */
1186e91bba0SGirish Moodalbail 	{ "create-addr", do_create_addr,
1197bc87895SYuri Pankov 	    "\tcreate-addr\t[-t] -T static [-d] "
1207bc87895SYuri Pankov 	    "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
121b31320a7SChris Fraire 	    "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
122b31320a7SChris Fraire 	    "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
1237bc87895SYuri Pankov 	    "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
1247bc87895SYuri Pankov 	    "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
1256e91bba0SGirish Moodalbail 	{ "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
126a73be61aSHans Rosenfeld 	{ "show-addr", do_show_addr,
127a73be61aSHans Rosenfeld 	    "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]"		},
128a73be61aSHans Rosenfeld 	{ "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
129a73be61aSHans Rosenfeld 	{ "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>"	},
130a73be61aSHans Rosenfeld 	{ "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>"	},
131a73be61aSHans Rosenfeld 	{ "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
132a73be61aSHans Rosenfeld 	{ "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>\n" },
133a73be61aSHans Rosenfeld 
1346e91bba0SGirish Moodalbail 	{ "set-addrprop", do_set_addrprop,
1356e91bba0SGirish Moodalbail 	    "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>"	},
1366e91bba0SGirish Moodalbail 	{ "reset-addrprop", do_reset_addrprop,
1376e91bba0SGirish Moodalbail 	    "\treset-addrprop\t[-t] -p <prop> <addrobj>"		},
1386e91bba0SGirish Moodalbail 	{ "show-addrprop", do_show_addrprop,
1396e91bba0SGirish Moodalbail 	    "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
140467e811cSToomas Soome 	    "<addrobj>\n"						},
1416e91bba0SGirish Moodalbail 
1426e91bba0SGirish Moodalbail 	/* protocol properties related sub-commands */
143a73be61aSHans Rosenfeld 	{ "set-prop", do_set_prop,
1446e91bba0SGirish Moodalbail 	    "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>"	},
145a73be61aSHans Rosenfeld 	{ "reset-prop", do_reset_prop,
1466e91bba0SGirish Moodalbail 	    "\treset-prop\t[-t] -p <prop> <protocol>"			},
147a73be61aSHans Rosenfeld 	{ "show-prop", do_show_prop,
1486e91bba0SGirish Moodalbail 	    "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
1498887b57dSGirish Moodalbail 	    " [protocol]"						}
1506e91bba0SGirish Moodalbail };
1516e91bba0SGirish Moodalbail 
1526e91bba0SGirish Moodalbail static const struct option if_longopts[] = {
1536e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1546e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1556e91bba0SGirish Moodalbail };
1566e91bba0SGirish Moodalbail 
1576e91bba0SGirish Moodalbail static const struct option show_prop_longopts[] = {
1586e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'c'	},
1596e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1606e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1616e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1626e91bba0SGirish Moodalbail };
1636e91bba0SGirish Moodalbail 
1646e91bba0SGirish Moodalbail static const struct option show_ifprop_longopts[] = {
1656e91bba0SGirish Moodalbail 	{"module",	required_argument,	0, 'm'	},
1666e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'c'	},
1676e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1686e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
1696e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1706e91bba0SGirish Moodalbail };
1716e91bba0SGirish Moodalbail 
1726e91bba0SGirish Moodalbail static const struct option set_prop_longopts[] = {
1736e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1746e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1756e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1766e91bba0SGirish Moodalbail };
1776e91bba0SGirish Moodalbail 
1786e91bba0SGirish Moodalbail static const struct option set_ifprop_longopts[] = {
1796e91bba0SGirish Moodalbail 	{"module",	required_argument,	0, 'm'	},
1806e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
1816e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1826e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1836e91bba0SGirish Moodalbail };
1846e91bba0SGirish Moodalbail 
1856e91bba0SGirish Moodalbail static const struct option addr_misc_longopts[] = {
1866e91bba0SGirish Moodalbail 	{"inform",	no_argument,		0, 'i'	},
1876e91bba0SGirish Moodalbail 	{"release",	no_argument,		0, 'r'	},
1886e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
1896e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
1906e91bba0SGirish Moodalbail };
1916e91bba0SGirish Moodalbail 
1926e91bba0SGirish Moodalbail static const struct option addr_longopts[] = {
1936e91bba0SGirish Moodalbail 	{"address",	required_argument,	0, 'a'	},
1946e91bba0SGirish Moodalbail 	{"down",	no_argument,		0, 'd'	},
1956e91bba0SGirish Moodalbail 	{"interface-id", required_argument,	0, 'i'	},
196b31320a7SChris Fraire 	{"primary",	no_argument,		0, '1'	},
1976e91bba0SGirish Moodalbail 	{"prop",	required_argument,	0, 'p'	},
198b31320a7SChris Fraire 	{"reqhost", required_argument,	0, 'h'	},
1996e91bba0SGirish Moodalbail 	{"temporary",	no_argument,		0, 't'	},
2006e91bba0SGirish Moodalbail 	{"type",	required_argument,	0, 'T'	},
2016e91bba0SGirish Moodalbail 	{"wait",	required_argument,	0, 'w'	},
2026e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
2036e91bba0SGirish Moodalbail };
2046e91bba0SGirish Moodalbail 
2056e91bba0SGirish Moodalbail static const struct option show_addr_longopts[] = {
2066e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'p'	},
2076e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
2086e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
2096e91bba0SGirish Moodalbail };
2106e91bba0SGirish Moodalbail 
2116e91bba0SGirish Moodalbail static const struct option show_if_longopts[] = {
2126e91bba0SGirish Moodalbail 	{"parsable",	no_argument,		0, 'p'	},
2136e91bba0SGirish Moodalbail 	{"output",	required_argument,	0, 'o'	},
2146e91bba0SGirish Moodalbail 	{ 0, 0, 0, 0 }
2156e91bba0SGirish Moodalbail };
2166e91bba0SGirish Moodalbail 
2176e91bba0SGirish Moodalbail /* callback functions to print show-* subcommands output */
2186e91bba0SGirish Moodalbail static ofmt_cb_t print_prop_cb;
2196e91bba0SGirish Moodalbail static ofmt_cb_t print_sa_cb;
2206e91bba0SGirish Moodalbail static ofmt_cb_t print_si_cb;
2216e91bba0SGirish Moodalbail 
2226e91bba0SGirish Moodalbail /* structures for 'ipadm show-*' subcommands */
2236e91bba0SGirish Moodalbail typedef enum {
2246e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_IFNAME,
2256e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PROTO,
2266e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_ADDROBJ,
2276e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PROPERTY,
2286e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PERM,
2296e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_CURRENT,
2306e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_PERSISTENT,
2316e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_DEFAULT,
2326e91bba0SGirish Moodalbail 	IPADM_PROPFIELD_POSSIBLE
2336e91bba0SGirish Moodalbail } ipadm_propfield_index_t;
2346e91bba0SGirish Moodalbail 
2356e91bba0SGirish Moodalbail static ofmt_field_t intfprop_fields[] = {
2366e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2376e91bba0SGirish Moodalbail { "IFNAME",	12,	IPADM_PROPFIELD_IFNAME,		print_prop_cb},
2386e91bba0SGirish Moodalbail { "PROPERTY",	16,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2396e91bba0SGirish Moodalbail { "PROTO",	6,	IPADM_PROPFIELD_PROTO,		print_prop_cb},
2406e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2416e91bba0SGirish Moodalbail { "CURRENT",	11,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2426e91bba0SGirish Moodalbail { "PERSISTENT",	11,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2436e91bba0SGirish Moodalbail { "DEFAULT",	11,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2446e91bba0SGirish Moodalbail { "POSSIBLE",	16,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2456e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2466e91bba0SGirish Moodalbail };
2476e91bba0SGirish Moodalbail 
2486e91bba0SGirish Moodalbail 
2496e91bba0SGirish Moodalbail static ofmt_field_t modprop_fields[] = {
2506e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2516e91bba0SGirish Moodalbail { "PROTO",	6,	IPADM_PROPFIELD_PROTO,		print_prop_cb},
2526e91bba0SGirish Moodalbail { "PROPERTY",	22,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2536e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2546e91bba0SGirish Moodalbail { "CURRENT",	13,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2556e91bba0SGirish Moodalbail { "PERSISTENT",	13,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2566e91bba0SGirish Moodalbail { "DEFAULT",	13,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2576e91bba0SGirish Moodalbail { "POSSIBLE",	15,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2586e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2596e91bba0SGirish Moodalbail };
2606e91bba0SGirish Moodalbail 
2616e91bba0SGirish Moodalbail static ofmt_field_t addrprop_fields[] = {
2626e91bba0SGirish Moodalbail /* name,	field width,	index,			callback */
2636e91bba0SGirish Moodalbail { "ADDROBJ",	18,	IPADM_PROPFIELD_ADDROBJ,	print_prop_cb},
2646e91bba0SGirish Moodalbail { "PROPERTY",	11,	IPADM_PROPFIELD_PROPERTY,	print_prop_cb},
2656e91bba0SGirish Moodalbail { "PERM",	5,	IPADM_PROPFIELD_PERM,		print_prop_cb},
2666e91bba0SGirish Moodalbail { "CURRENT",	16,	IPADM_PROPFIELD_CURRENT,	print_prop_cb},
2676e91bba0SGirish Moodalbail { "PERSISTENT",	16,	IPADM_PROPFIELD_PERSISTENT,	print_prop_cb},
2686e91bba0SGirish Moodalbail { "DEFAULT",	16,	IPADM_PROPFIELD_DEFAULT,	print_prop_cb},
2696e91bba0SGirish Moodalbail { "POSSIBLE",	15,	IPADM_PROPFIELD_POSSIBLE,	print_prop_cb},
2706e91bba0SGirish Moodalbail { NULL,		0,	0,				NULL}
2716e91bba0SGirish Moodalbail };
2726e91bba0SGirish Moodalbail 
2736e91bba0SGirish Moodalbail typedef struct show_prop_state {
2746e91bba0SGirish Moodalbail 	char		sps_ifname[LIFNAMSIZ];
2756e91bba0SGirish Moodalbail 	char		sps_aobjname[IPADM_AOBJSIZ];
2766e91bba0SGirish Moodalbail 	const char	*sps_pname;
2776e91bba0SGirish Moodalbail 	uint_t		sps_proto;
2786e91bba0SGirish Moodalbail 	char		*sps_propval;
2796e91bba0SGirish Moodalbail 	nvlist_t	*sps_proplist;
2806e91bba0SGirish Moodalbail 	boolean_t	sps_parsable;
2816e91bba0SGirish Moodalbail 	boolean_t	sps_addrprop;
2826e91bba0SGirish Moodalbail 	boolean_t	sps_ifprop;
2836e91bba0SGirish Moodalbail 	boolean_t	sps_modprop;
2846e91bba0SGirish Moodalbail 	ipadm_status_t	sps_status;
2856e91bba0SGirish Moodalbail 	ipadm_status_t	sps_retstatus;
2866e91bba0SGirish Moodalbail 	ofmt_handle_t	sps_ofmt;
2876e91bba0SGirish Moodalbail } show_prop_state_t;
2886e91bba0SGirish Moodalbail 
2896e91bba0SGirish Moodalbail typedef struct show_addr_state {
2906e91bba0SGirish Moodalbail 	boolean_t	sa_parsable;
2916e91bba0SGirish Moodalbail 	boolean_t	sa_persist;
2926e91bba0SGirish Moodalbail 	ofmt_handle_t	sa_ofmt;
2936e91bba0SGirish Moodalbail } show_addr_state_t;
2946e91bba0SGirish Moodalbail 
2956e91bba0SGirish Moodalbail typedef struct show_if_state {
2966e91bba0SGirish Moodalbail 	boolean_t	si_parsable;
2976e91bba0SGirish Moodalbail 	ofmt_handle_t	si_ofmt;
2986e91bba0SGirish Moodalbail } show_if_state_t;
2996e91bba0SGirish Moodalbail 
3006e91bba0SGirish Moodalbail typedef struct show_addr_args_s {
3016e91bba0SGirish Moodalbail 	show_addr_state_t	*sa_state;
3026e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*sa_info;
3036e91bba0SGirish Moodalbail } show_addr_args_t;
3046e91bba0SGirish Moodalbail 
3056e91bba0SGirish Moodalbail typedef struct show_if_args_s {
3066e91bba0SGirish Moodalbail 	show_if_state_t *si_state;
307a73be61aSHans Rosenfeld 	ipadm_if_info_t *si_info;
3086e91bba0SGirish Moodalbail } show_if_args_t;
3096e91bba0SGirish Moodalbail 
3106e91bba0SGirish Moodalbail typedef enum {
3116e91bba0SGirish Moodalbail 	SA_ADDROBJ,
3126e91bba0SGirish Moodalbail 	SA_TYPE,
3136e91bba0SGirish Moodalbail 	SA_STATE,
3146e91bba0SGirish Moodalbail 	SA_CURRENT,
3156e91bba0SGirish Moodalbail 	SA_PERSISTENT,
3166e91bba0SGirish Moodalbail 	SA_ADDR
3176e91bba0SGirish Moodalbail } sa_field_index_t;
3186e91bba0SGirish Moodalbail 
3196e91bba0SGirish Moodalbail typedef enum {
3206e91bba0SGirish Moodalbail 	SI_IFNAME,
321a73be61aSHans Rosenfeld 	SI_IFCLASS,
3226e91bba0SGirish Moodalbail 	SI_STATE,
3236e91bba0SGirish Moodalbail 	SI_CURRENT,
3246e91bba0SGirish Moodalbail 	SI_PERSISTENT
3256e91bba0SGirish Moodalbail } si_field_index_t;
3266e91bba0SGirish Moodalbail 
3276e91bba0SGirish Moodalbail static ofmt_field_t show_addr_fields[] = {
3286e91bba0SGirish Moodalbail /* name,	field width,	id,		callback */
3296e91bba0SGirish Moodalbail { "ADDROBJ",	18,		SA_ADDROBJ,	print_sa_cb},
3306e91bba0SGirish Moodalbail { "TYPE",	9,		SA_TYPE,	print_sa_cb},
3316e91bba0SGirish Moodalbail { "STATE",	13,		SA_STATE,	print_sa_cb},
3326e91bba0SGirish Moodalbail { "CURRENT",	8,		SA_CURRENT,	print_sa_cb},
3336e91bba0SGirish Moodalbail { "PERSISTENT",	11,		SA_PERSISTENT,	print_sa_cb},
3346e91bba0SGirish Moodalbail { "ADDR",	46,		SA_ADDR,	print_sa_cb},
3356e91bba0SGirish Moodalbail { NULL,		0,		0,		NULL}
3366e91bba0SGirish Moodalbail };
3376e91bba0SGirish Moodalbail 
3386e91bba0SGirish Moodalbail static ofmt_field_t show_if_fields[] = {
3396e91bba0SGirish Moodalbail /* name,	field width,	id,		callback */
3406e91bba0SGirish Moodalbail { "IFNAME",	11,		SI_IFNAME,	print_si_cb},
341a73be61aSHans Rosenfeld { "CLASS",	10,		SI_IFCLASS,	print_si_cb},
3426e91bba0SGirish Moodalbail { "STATE",	9,		SI_STATE,	print_si_cb},
343550b6e40SSowmini Varadhan { "CURRENT",	13,		SI_CURRENT,	print_si_cb},
3446e91bba0SGirish Moodalbail { "PERSISTENT",	11,		SI_PERSISTENT,	print_si_cb},
3456e91bba0SGirish Moodalbail { NULL,		0,		0,		NULL}
3466e91bba0SGirish Moodalbail };
3476e91bba0SGirish Moodalbail 
3486e91bba0SGirish Moodalbail #define	IPADM_ALL_BITS	((uint_t)-1)
3496e91bba0SGirish Moodalbail typedef struct intf_mask {
3506e91bba0SGirish Moodalbail 	char		*name;
3516e91bba0SGirish Moodalbail 	uint64_t	bits;
3526e91bba0SGirish Moodalbail 	uint64_t	mask;
3536e91bba0SGirish Moodalbail } fmask_t;
3546e91bba0SGirish Moodalbail 
355a73be61aSHans Rosenfeld typedef enum {
356a73be61aSHans Rosenfeld     IPMP_ADD_MEMBER,
357a73be61aSHans Rosenfeld     IPMP_REMOVE_MEMBER
358a73be61aSHans Rosenfeld } ipmp_action_t;
359a73be61aSHans Rosenfeld 
3606e91bba0SGirish Moodalbail /*
3616e91bba0SGirish Moodalbail  * Handle to libipadm. Opened in main() before the sub-command specific
3626e91bba0SGirish Moodalbail  * function is called and is closed before the program exits.
3636e91bba0SGirish Moodalbail  */
3646e91bba0SGirish Moodalbail ipadm_handle_t	iph = NULL;
3656e91bba0SGirish Moodalbail 
3666e91bba0SGirish Moodalbail /*
3676e91bba0SGirish Moodalbail  * Opaque ipadm address object. Used by all the address management subcommands.
3686e91bba0SGirish Moodalbail  */
3696e91bba0SGirish Moodalbail ipadm_addrobj_t	ipaddr = NULL;
3706e91bba0SGirish Moodalbail 
3716e91bba0SGirish Moodalbail static char *progname;
3726e91bba0SGirish Moodalbail 
373467e811cSToomas Soome 
374467e811cSToomas Soome static void	warn(const char *, ...);
375467e811cSToomas Soome static void	die(const char *, ...) __NORETURN;
376467e811cSToomas Soome static void	die_opterr(int, int, const char *) __NORETURN;
3776e91bba0SGirish Moodalbail static void	warn_ipadmerr(ipadm_status_t, const char *, ...);
378467e811cSToomas Soome static void	ipadm_check_propstr(const char *, boolean_t, const char *);
379467e811cSToomas Soome static void	process_misc_addrargs(int, char **, const char *, int *,
3806e91bba0SGirish Moodalbail 		    uint32_t *);
381a73be61aSHans Rosenfeld static void	do_action_ipmp(char *, ipadm_ipmp_members_t *, ipmp_action_t,
382a73be61aSHans Rosenfeld     uint32_t);
383a73be61aSHans Rosenfeld 
3846e91bba0SGirish Moodalbail 
3856e91bba0SGirish Moodalbail static void
usage(int ret)386f3f00a64SAndy Fiddaman usage(int ret)
3876e91bba0SGirish Moodalbail {
3886e91bba0SGirish Moodalbail 	int	i;
3896e91bba0SGirish Moodalbail 	cmd_t	*cmdp;
3906e91bba0SGirish Moodalbail 
3916e91bba0SGirish Moodalbail 	(void) fprintf(stderr,
3926e91bba0SGirish Moodalbail 	    gettext("usage:  ipadm <subcommand> <args> ...\n"));
3936e91bba0SGirish Moodalbail 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
3946e91bba0SGirish Moodalbail 		cmdp = &cmds[i];
3956e91bba0SGirish Moodalbail 		if (cmdp->c_usage != NULL)
3966e91bba0SGirish Moodalbail 			(void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
3976e91bba0SGirish Moodalbail 	}
3986e91bba0SGirish Moodalbail 
3996e91bba0SGirish Moodalbail 	ipadm_destroy_addrobj(ipaddr);
4006e91bba0SGirish Moodalbail 	ipadm_close(iph);
401f3f00a64SAndy Fiddaman 	exit(ret);
402f3f00a64SAndy Fiddaman }
403f3f00a64SAndy Fiddaman 
404f3f00a64SAndy Fiddaman static void
do_help(int argc __unused,char ** argv __unused,const char * use __unused)405f3f00a64SAndy Fiddaman do_help(int argc __unused, char **argv __unused, const char *use __unused)
406f3f00a64SAndy Fiddaman {
407f3f00a64SAndy Fiddaman 	usage(0);
4086e91bba0SGirish Moodalbail }
4096e91bba0SGirish Moodalbail 
4106e91bba0SGirish Moodalbail int
main(int argc,char * argv[])4116e91bba0SGirish Moodalbail main(int argc, char *argv[])
4126e91bba0SGirish Moodalbail {
4136e91bba0SGirish Moodalbail 	int	i;
4146e91bba0SGirish Moodalbail 	cmd_t	*cmdp;
4156e91bba0SGirish Moodalbail 	ipadm_status_t status;
4166e91bba0SGirish Moodalbail 
4176e91bba0SGirish Moodalbail 	(void) setlocale(LC_ALL, "");
4186e91bba0SGirish Moodalbail 	(void) textdomain(TEXT_DOMAIN);
4196e91bba0SGirish Moodalbail 
4206e91bba0SGirish Moodalbail 	if ((progname = strrchr(argv[0], '/')) == NULL)
4216e91bba0SGirish Moodalbail 		progname = argv[0];
4226e91bba0SGirish Moodalbail 	else
4236e91bba0SGirish Moodalbail 		progname++;
4246e91bba0SGirish Moodalbail 
425f3f00a64SAndy Fiddaman 	if (argc < 2) {
426f3f00a64SAndy Fiddaman 		argv[1] = "show-addr";
427f3f00a64SAndy Fiddaman 		argc = 2;
428f3f00a64SAndy Fiddaman 	}
4296e91bba0SGirish Moodalbail 
4306e91bba0SGirish Moodalbail 	status = ipadm_open(&iph, 0);
4316e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
4326e91bba0SGirish Moodalbail 		die("Could not open handle to library - %s",
4336e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
4346e91bba0SGirish Moodalbail 	}
4356e91bba0SGirish Moodalbail 
4366e91bba0SGirish Moodalbail 	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
4376e91bba0SGirish Moodalbail 		cmdp = &cmds[i];
4386e91bba0SGirish Moodalbail 		if (strcmp(argv[1], cmdp->c_name) == 0) {
4396e91bba0SGirish Moodalbail 			cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
4406e91bba0SGirish Moodalbail 			ipadm_destroy_addrobj(ipaddr);
4416e91bba0SGirish Moodalbail 			ipadm_close(iph);
4426e91bba0SGirish Moodalbail 			exit(0);
4436e91bba0SGirish Moodalbail 		}
4446e91bba0SGirish Moodalbail 	}
4456e91bba0SGirish Moodalbail 
4466e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
4476e91bba0SGirish Moodalbail 	    progname, argv[1]);
448f3f00a64SAndy Fiddaman 	usage(1);
4496e91bba0SGirish Moodalbail 
4506e91bba0SGirish Moodalbail 	return (0);
4516e91bba0SGirish Moodalbail }
4526e91bba0SGirish Moodalbail 
4536e91bba0SGirish Moodalbail /*
454a73be61aSHans Rosenfeld  * Create regular IP interface or IPMP group interface
4556e91bba0SGirish Moodalbail  */
4566e91bba0SGirish Moodalbail static void
do_create_ip_common(int argc,char * argv[],const char * use,uint32_t flags)457a73be61aSHans Rosenfeld do_create_ip_common(int argc, char *argv[], const char *use, uint32_t flags)
4586e91bba0SGirish Moodalbail {
4596e91bba0SGirish Moodalbail 	ipadm_status_t	status;
4606e91bba0SGirish Moodalbail 	int		option;
4616e91bba0SGirish Moodalbail 
4626e91bba0SGirish Moodalbail 	opterr = 0;
463a73be61aSHans Rosenfeld 	while ((option = getopt_long(argc, argv,
464a73be61aSHans Rosenfeld 	    ":t", if_longopts, NULL)) != -1) {
4656e91bba0SGirish Moodalbail 		switch (option) {
4666e91bba0SGirish Moodalbail 		case 't':
4676e91bba0SGirish Moodalbail 			/*
4686e91bba0SGirish Moodalbail 			 * "ifconfig" mode - plumb interface, but do not
4696e91bba0SGirish Moodalbail 			 * restore settings that may exist in db.
4706e91bba0SGirish Moodalbail 			 */
4716e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
4726e91bba0SGirish Moodalbail 			break;
4736e91bba0SGirish Moodalbail 		default:
4746e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
4756e91bba0SGirish Moodalbail 		}
4766e91bba0SGirish Moodalbail 	}
477a73be61aSHans Rosenfeld 	if (optind != (argc - 1)) {
478a73be61aSHans Rosenfeld 		if (use != NULL)
479a73be61aSHans Rosenfeld 			die("usage: %s", use);
480a73be61aSHans Rosenfeld 		else
481a73be61aSHans Rosenfeld 			die(NULL);
482a73be61aSHans Rosenfeld 	}
4836e91bba0SGirish Moodalbail 	status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
4846e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
4856e91bba0SGirish Moodalbail 		die("Could not create %s : %s",
4866e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
4876e91bba0SGirish Moodalbail 	}
4886e91bba0SGirish Moodalbail }
4896e91bba0SGirish Moodalbail 
490a73be61aSHans Rosenfeld /*
491a73be61aSHans Rosenfeld  * Helpers to parse options into ipadm_ipmp_members_t list, and to free it.
492a73be61aSHans Rosenfeld  */
493a73be61aSHans Rosenfeld static ipadm_ipmp_members_t *
get_ipmp_members(int argc,char * argv[],const char * use,uint32_t * flags)494a73be61aSHans Rosenfeld get_ipmp_members(int argc, char *argv[], const char *use, uint32_t *flags)
495a73be61aSHans Rosenfeld {
496a73be61aSHans Rosenfeld 	ipadm_ipmp_members_t *members = NULL;
497a73be61aSHans Rosenfeld 	ipadm_ipmp_member_t *member;
498a73be61aSHans Rosenfeld 	char *ifname;
499a73be61aSHans Rosenfeld 	int option;
500a73be61aSHans Rosenfeld 
501a73be61aSHans Rosenfeld 
502a73be61aSHans Rosenfeld 	opterr = 0;
503a73be61aSHans Rosenfeld 	while ((option = getopt_long(argc, argv, ":i:", if_longopts, NULL)) !=
504a73be61aSHans Rosenfeld 	    -1) {
505a73be61aSHans Rosenfeld 		switch (option) {
506a73be61aSHans Rosenfeld 		case 't':
507a73be61aSHans Rosenfeld 			*flags &= ~IPADM_OPT_PERSIST;
508a73be61aSHans Rosenfeld 			break;
509a73be61aSHans Rosenfeld 		case 'i':
510a73be61aSHans Rosenfeld 			if (members == NULL) {
511a73be61aSHans Rosenfeld 				members = calloc(1,
512a73be61aSHans Rosenfeld 				    sizeof (ipadm_ipmp_members_t));
513a73be61aSHans Rosenfeld 				if (members == NULL)
514a73be61aSHans Rosenfeld 					die("insufficient memory");
515a73be61aSHans Rosenfeld 				list_create(members,
516a73be61aSHans Rosenfeld 				    sizeof (ipadm_ipmp_member_t),
517a73be61aSHans Rosenfeld 				    offsetof(ipadm_ipmp_member_t, node));
518a73be61aSHans Rosenfeld 			}
519a73be61aSHans Rosenfeld 
520a73be61aSHans Rosenfeld 			for (ifname = strtok(optarg, ",");
521a73be61aSHans Rosenfeld 			    ifname != NULL;
522a73be61aSHans Rosenfeld 			    ifname = strtok(NULL, ",")) {
523a73be61aSHans Rosenfeld 				if ((member = calloc(1,
524a73be61aSHans Rosenfeld 				    sizeof (ipadm_ipmp_member_t))) == NULL)
525a73be61aSHans Rosenfeld 					die("insufficient memory");
526a73be61aSHans Rosenfeld 
527a73be61aSHans Rosenfeld 				if (strlcpy(member->if_name, ifname,
528a73be61aSHans Rosenfeld 				    sizeof (member->if_name)) >= LIFNAMSIZ)
529a73be61aSHans Rosenfeld 					die("Incorrect length of interface "
530a73be61aSHans Rosenfeld 					    "name: %s", ifname);
531a73be61aSHans Rosenfeld 
532a73be61aSHans Rosenfeld 				list_insert_tail(members, member);
533a73be61aSHans Rosenfeld 			}
534a73be61aSHans Rosenfeld 			break;
535a73be61aSHans Rosenfeld 		default:
536a73be61aSHans Rosenfeld 			die_opterr(optopt, option, use);
537a73be61aSHans Rosenfeld 		}
538a73be61aSHans Rosenfeld 	}
539a73be61aSHans Rosenfeld 
540a73be61aSHans Rosenfeld 	if (optind != (argc - 1))
541a73be61aSHans Rosenfeld 		die("Usage: %s", use);
542a73be61aSHans Rosenfeld 
543a73be61aSHans Rosenfeld 	if (members != NULL && list_is_empty(members)) {
544a73be61aSHans Rosenfeld 		free(members);
545a73be61aSHans Rosenfeld 		members = NULL;
546a73be61aSHans Rosenfeld 	}
547a73be61aSHans Rosenfeld 
548a73be61aSHans Rosenfeld 	return (members);
549a73be61aSHans Rosenfeld }
550a73be61aSHans Rosenfeld 
551a73be61aSHans Rosenfeld static void
free_ipmp_members(ipadm_ipmp_members_t * members)552a73be61aSHans Rosenfeld free_ipmp_members(ipadm_ipmp_members_t *members)
553a73be61aSHans Rosenfeld {
554a73be61aSHans Rosenfeld 	ipadm_ipmp_member_t *member;
555a73be61aSHans Rosenfeld 
556a73be61aSHans Rosenfeld 	while ((member = list_remove_head(members)) != NULL)
557a73be61aSHans Rosenfeld 		free(member);
558a73be61aSHans Rosenfeld 
559a73be61aSHans Rosenfeld 	list_destroy(members);
560a73be61aSHans Rosenfeld 
561a73be61aSHans Rosenfeld 	free(members);
562a73be61aSHans Rosenfeld }
563a73be61aSHans Rosenfeld 
564a73be61aSHans Rosenfeld /*
565a73be61aSHans Rosenfeld  * Create an IPMP group interface for which no saved configuration
566a73be61aSHans Rosenfeld  * exists in the persistent store.
567a73be61aSHans Rosenfeld  */
568a73be61aSHans Rosenfeld static void
do_create_ipmp(int argc,char * argv[],const char * use)569a73be61aSHans Rosenfeld do_create_ipmp(int argc, char *argv[], const char *use)
570a73be61aSHans Rosenfeld {
571a73be61aSHans Rosenfeld 	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP;
572a73be61aSHans Rosenfeld 	ipadm_ipmp_members_t *members = NULL;
573a73be61aSHans Rosenfeld 	ipmp_handle_t ipmp_handle;
574a73be61aSHans Rosenfeld 	int retval;
575a73be61aSHans Rosenfeld 
576a73be61aSHans Rosenfeld 	retval = ipmp_open(&ipmp_handle);
577a73be61aSHans Rosenfeld 	if (retval != IPMP_SUCCESS) {
578a73be61aSHans Rosenfeld 		die("Could not create IPMP handle: %s",
579a73be61aSHans Rosenfeld 		    ipadm_status2str(retval));
580a73be61aSHans Rosenfeld 	}
581a73be61aSHans Rosenfeld 
582a73be61aSHans Rosenfeld 	retval = ipmp_ping_daemon(ipmp_handle);
583a73be61aSHans Rosenfeld 	ipmp_close(ipmp_handle);
584a73be61aSHans Rosenfeld 
585a73be61aSHans Rosenfeld 	if (retval != IPMP_SUCCESS) {
586a73be61aSHans Rosenfeld 		die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval));
587a73be61aSHans Rosenfeld 	}
588a73be61aSHans Rosenfeld 
589a73be61aSHans Rosenfeld 	members = get_ipmp_members(argc, argv, use, &flags);
590a73be61aSHans Rosenfeld 
591a73be61aSHans Rosenfeld 	do_create_ip_common(argc, argv, use, flags);
592a73be61aSHans Rosenfeld 
593a73be61aSHans Rosenfeld 	if (members != NULL) {
594a73be61aSHans Rosenfeld 		do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags);
595a73be61aSHans Rosenfeld 		free_ipmp_members(members);
596a73be61aSHans Rosenfeld 	}
597a73be61aSHans Rosenfeld }
598a73be61aSHans Rosenfeld 
599a73be61aSHans Rosenfeld static void
do_add_ipmp(int argc,char * argv[],const char * use)600a73be61aSHans Rosenfeld do_add_ipmp(int argc, char *argv[], const char *use)
601a73be61aSHans Rosenfeld {
602a73be61aSHans Rosenfeld 	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
603a73be61aSHans Rosenfeld 	ipadm_ipmp_members_t *members;
604a73be61aSHans Rosenfeld 
605a73be61aSHans Rosenfeld 	members = get_ipmp_members(argc, argv, use, &flags);
606a73be61aSHans Rosenfeld 
607a73be61aSHans Rosenfeld 	if (members == NULL)
608a73be61aSHans Rosenfeld 		die_opterr(optopt, ':', use);
609a73be61aSHans Rosenfeld 
610a73be61aSHans Rosenfeld 	do_action_ipmp(argv[optind], members, IPMP_ADD_MEMBER, flags);
611a73be61aSHans Rosenfeld 	free_ipmp_members(members);
612a73be61aSHans Rosenfeld }
613a73be61aSHans Rosenfeld 
614a73be61aSHans Rosenfeld static void
do_remove_ipmp(int argc,char * argv[],const char * use)615a73be61aSHans Rosenfeld do_remove_ipmp(int argc, char *argv[], const char *use)
616a73be61aSHans Rosenfeld {
617a73be61aSHans Rosenfeld 	uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
618a73be61aSHans Rosenfeld 	ipadm_ipmp_members_t *members;
619a73be61aSHans Rosenfeld 
620a73be61aSHans Rosenfeld 	members = get_ipmp_members(argc, argv, use, &flags);
621a73be61aSHans Rosenfeld 
622a73be61aSHans Rosenfeld 	if (members == NULL)
623a73be61aSHans Rosenfeld 		die_opterr(optopt, ':', use);
624a73be61aSHans Rosenfeld 
625a73be61aSHans Rosenfeld 	do_action_ipmp(argv[optind], members, IPMP_REMOVE_MEMBER, flags);
626a73be61aSHans Rosenfeld 	free_ipmp_members(members);
627a73be61aSHans Rosenfeld }
628a73be61aSHans Rosenfeld 
629a73be61aSHans Rosenfeld static void
do_action_ipmp(char * ipmp,ipadm_ipmp_members_t * members,ipmp_action_t action,uint32_t flags)630a73be61aSHans Rosenfeld do_action_ipmp(char *ipmp, ipadm_ipmp_members_t *members, ipmp_action_t action,
631a73be61aSHans Rosenfeld     uint32_t flags)
632a73be61aSHans Rosenfeld {
633a73be61aSHans Rosenfeld 	ipadm_status_t (*func)(ipadm_handle_t, const char *, const char *,
634a73be61aSHans Rosenfeld 	    uint32_t);
635a73be61aSHans Rosenfeld 	ipadm_status_t  status;
636a73be61aSHans Rosenfeld 	ipadm_ipmp_member_t *member;
637a73be61aSHans Rosenfeld 	char *ifname;
638a73be61aSHans Rosenfeld 	const char *msg;
639a73be61aSHans Rosenfeld 
640a73be61aSHans Rosenfeld 	if (action == IPMP_ADD_MEMBER) {
641a73be61aSHans Rosenfeld 		func = ipadm_add_ipmp_member;
642a73be61aSHans Rosenfeld 		msg = "Cannot add interface '%s' to IPMP interface '%s': %s";
643a73be61aSHans Rosenfeld 	} else {
644a73be61aSHans Rosenfeld 		func = ipadm_remove_ipmp_member;
645a73be61aSHans Rosenfeld 		msg = "Cannot remove interface '%s' from IPMP interface '%s': "
646a73be61aSHans Rosenfeld 		    "%s";
647a73be61aSHans Rosenfeld 	}
648a73be61aSHans Rosenfeld 
649a73be61aSHans Rosenfeld 	while ((member = list_remove_head(members)) != NULL) {
650a73be61aSHans Rosenfeld 		ifname = member->if_name;
651a73be61aSHans Rosenfeld 
652a73be61aSHans Rosenfeld 		status = func(iph, ipmp, ifname, flags);
653a73be61aSHans Rosenfeld 		if (status != IPADM_SUCCESS)
654a73be61aSHans Rosenfeld 			die(msg, ifname, ipmp, ipadm_status2str(status));
655a73be61aSHans Rosenfeld 	}
656a73be61aSHans Rosenfeld }
657a73be61aSHans Rosenfeld 
658a73be61aSHans Rosenfeld /*
659a73be61aSHans Rosenfeld  * Create an IP interface for which no saved configuration exists in the
660a73be61aSHans Rosenfeld  * persistent store.
661a73be61aSHans Rosenfeld  */
662a73be61aSHans Rosenfeld static void
do_create_ip(int argc,char * argv[],const char * use)663a73be61aSHans Rosenfeld do_create_ip(int argc, char *argv[], const char *use)
664a73be61aSHans Rosenfeld {
665a73be61aSHans Rosenfeld 	do_create_ip_common(argc, argv, use,
666a73be61aSHans Rosenfeld 	    IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE);
667a73be61aSHans Rosenfeld }
668a73be61aSHans Rosenfeld 
6696e91bba0SGirish Moodalbail /*
6706e91bba0SGirish Moodalbail  * Enable an IP interface based on the persistent configuration for
6716e91bba0SGirish Moodalbail  * that interface.
6726e91bba0SGirish Moodalbail  */
6736e91bba0SGirish Moodalbail static void
do_enable_if(int argc,char * argv[],const char * use)6746e91bba0SGirish Moodalbail do_enable_if(int argc, char *argv[], const char *use)
6756e91bba0SGirish Moodalbail {
6766e91bba0SGirish Moodalbail 	ipadm_status_t	status;
6776e91bba0SGirish Moodalbail 	int		index;
678467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
6796e91bba0SGirish Moodalbail 
6806e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
6816e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
6826e91bba0SGirish Moodalbail 		die("persistent operation not supported for enable-if");
6836e91bba0SGirish Moodalbail 	status = ipadm_enable_if(iph, argv[index], flags);
6846e91bba0SGirish Moodalbail 	if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
6856e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
6866e91bba0SGirish Moodalbail 	} else if (status != IPADM_SUCCESS) {
6876e91bba0SGirish Moodalbail 		die("Could not enable %s : %s",
6886e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
6896e91bba0SGirish Moodalbail 	}
6906e91bba0SGirish Moodalbail }
6916e91bba0SGirish Moodalbail 
6926e91bba0SGirish Moodalbail /*
6936e91bba0SGirish Moodalbail  * Remove an IP interface from both active and persistent configuration.
6946e91bba0SGirish Moodalbail  */
6956e91bba0SGirish Moodalbail static void
do_delete_ip(int argc,char * argv[],const char * use)696a73be61aSHans Rosenfeld do_delete_ip(int argc, char *argv[], const char *use)
6976e91bba0SGirish Moodalbail {
6986e91bba0SGirish Moodalbail 	ipadm_status_t	status;
6996e91bba0SGirish Moodalbail 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
7006e91bba0SGirish Moodalbail 
7016e91bba0SGirish Moodalbail 	if (argc != 2)
7026e91bba0SGirish Moodalbail 		die("Usage: %s", use);
7036e91bba0SGirish Moodalbail 
7046e91bba0SGirish Moodalbail 	status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
7056e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
7066e91bba0SGirish Moodalbail 		die("Could not delete %s: %s",
7076e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
7086e91bba0SGirish Moodalbail 	}
7096e91bba0SGirish Moodalbail }
7106e91bba0SGirish Moodalbail 
7116e91bba0SGirish Moodalbail /*
7126e91bba0SGirish Moodalbail  * Disable an IP interface by removing it from active configuration.
7136e91bba0SGirish Moodalbail  */
7146e91bba0SGirish Moodalbail static void
do_disable_if(int argc,char * argv[],const char * use)7156e91bba0SGirish Moodalbail do_disable_if(int argc, char *argv[], const char *use)
7166e91bba0SGirish Moodalbail {
7176e91bba0SGirish Moodalbail 	ipadm_status_t	status;
7186e91bba0SGirish Moodalbail 	int		index;
719467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
7206e91bba0SGirish Moodalbail 
7216e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
7226e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
7236e91bba0SGirish Moodalbail 		die("persistent operation not supported for disable-if");
7246e91bba0SGirish Moodalbail 	status = ipadm_disable_if(iph, argv[index], flags);
7256e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
7266e91bba0SGirish Moodalbail 		die("Could not disable %s: %s",
7276e91bba0SGirish Moodalbail 		    argv[optind], ipadm_status2str(status));
7286e91bba0SGirish Moodalbail 	}
7296e91bba0SGirish Moodalbail }
7306e91bba0SGirish Moodalbail 
7316e91bba0SGirish Moodalbail /*
7328c8556f9SYuri Pankov  * Print individual columns for the show-*prop subcommands.
7336e91bba0SGirish Moodalbail  */
7346e91bba0SGirish Moodalbail static void
print_prop(show_prop_state_t * statep,uint_t flags,char * buf,size_t bufsize)7356e91bba0SGirish Moodalbail print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
7366e91bba0SGirish Moodalbail {
7376e91bba0SGirish Moodalbail 	const char		*prop_name = statep->sps_pname;
7386e91bba0SGirish Moodalbail 	char			*ifname = statep->sps_ifname;
7396e91bba0SGirish Moodalbail 	char			*propval = statep->sps_propval;
7406e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
7416e91bba0SGirish Moodalbail 	size_t			propsize = MAXPROPVALLEN;
7426e91bba0SGirish Moodalbail 	ipadm_status_t		status;
7436e91bba0SGirish Moodalbail 
7446e91bba0SGirish Moodalbail 	if (statep->sps_ifprop) {
7456e91bba0SGirish Moodalbail 		status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
7466e91bba0SGirish Moodalbail 		    &propsize, proto, flags);
7476e91bba0SGirish Moodalbail 	} else if (statep->sps_modprop) {
7486e91bba0SGirish Moodalbail 		status = ipadm_get_prop(iph, prop_name, propval, &propsize,
7496e91bba0SGirish Moodalbail 		    proto, flags);
7506e91bba0SGirish Moodalbail 	} else {
7516e91bba0SGirish Moodalbail 		status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
7526e91bba0SGirish Moodalbail 		    statep->sps_aobjname, flags);
7536e91bba0SGirish Moodalbail 	}
7546e91bba0SGirish Moodalbail 
7556e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
7568c8556f9SYuri Pankov 		if ((status == IPADM_NOTFOUND && (flags & IPADM_OPT_PERSIST)) ||
7578c8556f9SYuri Pankov 		    status == IPADM_ENXIO) {
7586e91bba0SGirish Moodalbail 			propval[0] = '\0';
7596e91bba0SGirish Moodalbail 			goto cont;
7606e91bba0SGirish Moodalbail 		}
7616e91bba0SGirish Moodalbail 		statep->sps_status = status;
7626e91bba0SGirish Moodalbail 		statep->sps_retstatus = status;
7636e91bba0SGirish Moodalbail 		return;
7646e91bba0SGirish Moodalbail 	}
7656e91bba0SGirish Moodalbail cont:
7666e91bba0SGirish Moodalbail 	statep->sps_status = IPADM_SUCCESS;
7676e91bba0SGirish Moodalbail 	(void) snprintf(buf, bufsize, "%s", propval);
7686e91bba0SGirish Moodalbail }
7696e91bba0SGirish Moodalbail 
7706e91bba0SGirish Moodalbail /*
7718c8556f9SYuri Pankov  * Callback function for show-*prop subcommands.
7726e91bba0SGirish Moodalbail  */
7736e91bba0SGirish Moodalbail static boolean_t
print_prop_cb(ofmt_arg_t * ofarg,char * buf,size_t bufsize)7746e91bba0SGirish Moodalbail print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
7756e91bba0SGirish Moodalbail {
7766e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = ofarg->ofmt_cbarg;
7776e91bba0SGirish Moodalbail 	const char		*propname = statep->sps_pname;
7786e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
7796e91bba0SGirish Moodalbail 	boolean_t		cont = _B_TRUE;
7806e91bba0SGirish Moodalbail 
7816e91bba0SGirish Moodalbail 	/*
7826e91bba0SGirish Moodalbail 	 * Fail retrieving remaining fields, if you fail
7836e91bba0SGirish Moodalbail 	 * to retrieve a field.
7846e91bba0SGirish Moodalbail 	 */
7856e91bba0SGirish Moodalbail 	if (statep->sps_status != IPADM_SUCCESS)
7866e91bba0SGirish Moodalbail 		return (_B_FALSE);
7876e91bba0SGirish Moodalbail 
7886e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
7896e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_IFNAME:
7906e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
7916e91bba0SGirish Moodalbail 		break;
7926e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PROTO:
7936e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
7946e91bba0SGirish Moodalbail 		break;
7956e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_ADDROBJ:
7966e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
7976e91bba0SGirish Moodalbail 		break;
7986e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PROPERTY:
7996e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", propname);
8006e91bba0SGirish Moodalbail 		break;
8016e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PERM:
8026e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
8036e91bba0SGirish Moodalbail 		break;
8046e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_CURRENT:
8056e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
8066e91bba0SGirish Moodalbail 		break;
8076e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_PERSISTENT:
8086e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
8096e91bba0SGirish Moodalbail 		break;
8106e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_DEFAULT:
8116e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
8126e91bba0SGirish Moodalbail 		break;
8136e91bba0SGirish Moodalbail 	case IPADM_PROPFIELD_POSSIBLE:
8146e91bba0SGirish Moodalbail 		print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
8156e91bba0SGirish Moodalbail 		break;
8166e91bba0SGirish Moodalbail 	}
8176e91bba0SGirish Moodalbail 	if (statep->sps_status != IPADM_SUCCESS)
8186e91bba0SGirish Moodalbail 		cont = _B_FALSE;
8196e91bba0SGirish Moodalbail 	return (cont);
8206e91bba0SGirish Moodalbail }
8216e91bba0SGirish Moodalbail 
8226e91bba0SGirish Moodalbail /*
8236e91bba0SGirish Moodalbail  * Callback function called by the property walker (ipadm_walk_prop() or
8246e91bba0SGirish Moodalbail  * ipadm_walk_proptbl()), for every matched property. This function in turn
8256e91bba0SGirish Moodalbail  * calls ofmt_print() to print property information.
8266e91bba0SGirish Moodalbail  */
8276e91bba0SGirish Moodalbail boolean_t
show_property(void * arg,const char * pname,uint_t proto)8286e91bba0SGirish Moodalbail show_property(void *arg, const char *pname, uint_t proto)
8296e91bba0SGirish Moodalbail {
8306e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = arg;
8316e91bba0SGirish Moodalbail 
8326e91bba0SGirish Moodalbail 	statep->sps_pname = pname;
8336e91bba0SGirish Moodalbail 	statep->sps_proto = proto;
8346e91bba0SGirish Moodalbail 	statep->sps_status = IPADM_SUCCESS;
8356e91bba0SGirish Moodalbail 	ofmt_print(statep->sps_ofmt, arg);
8366e91bba0SGirish Moodalbail 
8376e91bba0SGirish Moodalbail 	/*
8386e91bba0SGirish Moodalbail 	 * if an object is not found or operation is not supported then
8396e91bba0SGirish Moodalbail 	 * stop the walker.
8406e91bba0SGirish Moodalbail 	 */
8416e91bba0SGirish Moodalbail 	if (statep->sps_status == IPADM_NOTFOUND ||
8426e91bba0SGirish Moodalbail 	    statep->sps_status == IPADM_NOTSUP)
8436e91bba0SGirish Moodalbail 		return (_B_FALSE);
8446e91bba0SGirish Moodalbail 	return (_B_TRUE);
8456e91bba0SGirish Moodalbail }
8466e91bba0SGirish Moodalbail 
8476e91bba0SGirish Moodalbail /*
8486e91bba0SGirish Moodalbail  * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
849b31320a7SChris Fraire  * for all the properties for the specified object, display relevant
850b31320a7SChris Fraire  * information. Otherwise, for the selected property set, display relevant
8516e91bba0SGirish Moodalbail  * information
8526e91bba0SGirish Moodalbail  */
8536e91bba0SGirish Moodalbail static void
show_properties(void * arg,int prop_class)8546e91bba0SGirish Moodalbail show_properties(void *arg, int prop_class)
8556e91bba0SGirish Moodalbail {
8566e91bba0SGirish Moodalbail 	show_prop_state_t	*statep = arg;
857467e811cSToomas Soome 	nvlist_t		*nvl = statep->sps_proplist;
8586e91bba0SGirish Moodalbail 	uint_t			proto = statep->sps_proto;
8596e91bba0SGirish Moodalbail 	nvpair_t		*curr_nvp;
860467e811cSToomas Soome 	char			*buf, *name;
8616e91bba0SGirish Moodalbail 	ipadm_status_t		status;
8626e91bba0SGirish Moodalbail 
8636e91bba0SGirish Moodalbail 	/* allocate sufficient buffer to hold a property value */
8646e91bba0SGirish Moodalbail 	if ((buf = malloc(MAXPROPVALLEN)) == NULL)
8656e91bba0SGirish Moodalbail 		die("insufficient memory");
8666e91bba0SGirish Moodalbail 	statep->sps_propval = buf;
8676e91bba0SGirish Moodalbail 
8686e91bba0SGirish Moodalbail 	/* if no properties were specified, display all the properties */
8696e91bba0SGirish Moodalbail 	if (nvl == NULL) {
8706e91bba0SGirish Moodalbail 		(void) ipadm_walk_proptbl(proto, prop_class, show_property,
8716e91bba0SGirish Moodalbail 		    statep);
8726e91bba0SGirish Moodalbail 	} else {
8736e91bba0SGirish Moodalbail 		for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
8746e91bba0SGirish Moodalbail 		    curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
8756e91bba0SGirish Moodalbail 			name = nvpair_name(curr_nvp);
8766e91bba0SGirish Moodalbail 			status = ipadm_walk_prop(name, proto, prop_class,
8776e91bba0SGirish Moodalbail 			    show_property, statep);
8786e91bba0SGirish Moodalbail 			if (status == IPADM_PROP_UNKNOWN)
8796e91bba0SGirish Moodalbail 				(void) show_property(statep, name, proto);
8806e91bba0SGirish Moodalbail 		}
8816e91bba0SGirish Moodalbail 	}
8826e91bba0SGirish Moodalbail 
8836e91bba0SGirish Moodalbail 	free(buf);
8846e91bba0SGirish Moodalbail }
8856e91bba0SGirish Moodalbail 
8866e91bba0SGirish Moodalbail /*
8876e91bba0SGirish Moodalbail  * Display information for all or specific interface properties, either for a
8886e91bba0SGirish Moodalbail  * given interface or for all the interfaces in the system.
8896e91bba0SGirish Moodalbail  */
8906e91bba0SGirish Moodalbail static void
do_show_ifprop(int argc,char ** argv,const char * use)8916e91bba0SGirish Moodalbail do_show_ifprop(int argc, char **argv, const char *use)
8926e91bba0SGirish Moodalbail {
893467e811cSToomas Soome 	int		option;
894467e811cSToomas Soome 	nvlist_t	*proplist = NULL;
8956e91bba0SGirish Moodalbail 	char		*fields_str = NULL;
896467e811cSToomas Soome 	char		*ifname;
8976e91bba0SGirish Moodalbail 	ofmt_handle_t	ofmt;
8986e91bba0SGirish Moodalbail 	ofmt_status_t	oferr;
8996e91bba0SGirish Moodalbail 	uint_t		ofmtflags = 0;
9006e91bba0SGirish Moodalbail 	uint_t		proto;
9016e91bba0SGirish Moodalbail 	boolean_t	m_arg = _B_FALSE;
9026e91bba0SGirish Moodalbail 	char		*protostr;
903a73be61aSHans Rosenfeld 	ipadm_if_info_t	*ifinfo, *ifp;
9046e91bba0SGirish Moodalbail 	ipadm_status_t	status;
9056e91bba0SGirish Moodalbail 	show_prop_state_t state;
9066e91bba0SGirish Moodalbail 
907467e811cSToomas Soome 	protostr = "ip";
9086e91bba0SGirish Moodalbail 	opterr = 0;
9096e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
9106e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
9116e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
9126e91bba0SGirish Moodalbail 	state.sps_ifprop = _B_TRUE;
9136e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
9146e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:m:co:",
9156e91bba0SGirish Moodalbail 	    show_ifprop_longopts, NULL)) != -1) {
9166e91bba0SGirish Moodalbail 		switch (option) {
9176e91bba0SGirish Moodalbail 		case 'p':
9186e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
9196e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
9206e91bba0SGirish Moodalbail 				die("invalid interface properties specified");
9216e91bba0SGirish Moodalbail 			break;
9226e91bba0SGirish Moodalbail 		case 'c':
9236e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
9246e91bba0SGirish Moodalbail 			break;
9256e91bba0SGirish Moodalbail 		case 'o':
9266e91bba0SGirish Moodalbail 			fields_str = optarg;
9276e91bba0SGirish Moodalbail 			break;
9286e91bba0SGirish Moodalbail 		case 'm':
9296e91bba0SGirish Moodalbail 			if (m_arg)
9306e91bba0SGirish Moodalbail 				die("cannot specify more than one -m");
9316e91bba0SGirish Moodalbail 			m_arg = _B_TRUE;
9326e91bba0SGirish Moodalbail 			protostr = optarg;
9336e91bba0SGirish Moodalbail 			break;
9346e91bba0SGirish Moodalbail 		default:
9356e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
9366e91bba0SGirish Moodalbail 			break;
9376e91bba0SGirish Moodalbail 		}
9386e91bba0SGirish Moodalbail 	}
9396e91bba0SGirish Moodalbail 
9406e91bba0SGirish Moodalbail 	if (optind == argc - 1)
9416e91bba0SGirish Moodalbail 		ifname = argv[optind];
9426e91bba0SGirish Moodalbail 	else if (optind != argc)
9436e91bba0SGirish Moodalbail 		die("Usage: %s", use);
9446e91bba0SGirish Moodalbail 	else
9456e91bba0SGirish Moodalbail 		ifname = NULL;
9466e91bba0SGirish Moodalbail 
9476e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
9486e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
9496e91bba0SGirish Moodalbail 
9506e91bba0SGirish Moodalbail 	state.sps_proto = proto;
9516e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
9526e91bba0SGirish Moodalbail 
9536e91bba0SGirish Moodalbail 	if (state.sps_parsable)
9546e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
9556e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
956b2f26520SBryan Cantrill 	ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
9576e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
9586e91bba0SGirish Moodalbail 
9596e91bba0SGirish Moodalbail 	/* retrieve interface(s) and print the properties */
9606e91bba0SGirish Moodalbail 	status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
9616e91bba0SGirish Moodalbail 	if (ifname != NULL && status == IPADM_ENXIO)
9626e91bba0SGirish Moodalbail 		die("no such object '%s': %s", ifname,
9636e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
9646e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
9656e91bba0SGirish Moodalbail 		die("Error retrieving interface(s): %s",
9666e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
967a73be61aSHans Rosenfeld 	for (ifp = ifinfo; ifp != NULL; ifp = ifp->ifi_next) {
968a73be61aSHans Rosenfeld 		(void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
9696e91bba0SGirish Moodalbail 		state.sps_proto = proto;
9706e91bba0SGirish Moodalbail 		show_properties(&state, IPADMPROP_CLASS_IF);
9716e91bba0SGirish Moodalbail 	}
9726e91bba0SGirish Moodalbail 	if (ifinfo)
9736e91bba0SGirish Moodalbail 		ipadm_free_if_info(ifinfo);
9746e91bba0SGirish Moodalbail 
9756e91bba0SGirish Moodalbail 	nvlist_free(proplist);
9766e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
9776e91bba0SGirish Moodalbail 
9786e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
9796e91bba0SGirish Moodalbail 		ipadm_close(iph);
9806e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
9816e91bba0SGirish Moodalbail 	}
9826e91bba0SGirish Moodalbail }
9836e91bba0SGirish Moodalbail 
9846e91bba0SGirish Moodalbail /*
9856e91bba0SGirish Moodalbail  * set/reset the interface property for a given interface.
9866e91bba0SGirish Moodalbail  */
9876e91bba0SGirish Moodalbail static void
set_ifprop(int argc,char ** argv,boolean_t reset,const char * use)9886e91bba0SGirish Moodalbail set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
9896e91bba0SGirish Moodalbail {
990467e811cSToomas Soome 	int			option;
991467e811cSToomas Soome 	ipadm_status_t		status = IPADM_SUCCESS;
992467e811cSToomas Soome 	boolean_t		p_arg = _B_FALSE;
9936e91bba0SGirish Moodalbail 	boolean_t		m_arg = _B_FALSE;
994467e811cSToomas Soome 	char			*ifname, *nv, *protostr;
9956e91bba0SGirish Moodalbail 	char			*prop_name, *prop_val;
9966e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_PERSIST;
9976e91bba0SGirish Moodalbail 	uint_t			proto;
9986e91bba0SGirish Moodalbail 
999467e811cSToomas Soome 	nv = NULL;
1000467e811cSToomas Soome 	protostr = NULL;
10016e91bba0SGirish Moodalbail 	opterr = 0;
10026e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":m:p:t",
10036e91bba0SGirish Moodalbail 	    set_ifprop_longopts, NULL)) != -1) {
10046e91bba0SGirish Moodalbail 		switch (option) {
10056e91bba0SGirish Moodalbail 		case 'p':
10066e91bba0SGirish Moodalbail 			if (p_arg)
10076e91bba0SGirish Moodalbail 				die("-p must be specified once only");
10086e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
10096e91bba0SGirish Moodalbail 
10106e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
10116e91bba0SGirish Moodalbail 			nv = optarg;
10126e91bba0SGirish Moodalbail 			break;
10136e91bba0SGirish Moodalbail 		case 'm':
10146e91bba0SGirish Moodalbail 			if (m_arg)
10156e91bba0SGirish Moodalbail 				die("-m must be specified once only");
10166e91bba0SGirish Moodalbail 			m_arg = _B_TRUE;
10176e91bba0SGirish Moodalbail 			protostr = optarg;
10186e91bba0SGirish Moodalbail 			break;
10196e91bba0SGirish Moodalbail 		case 't':
10206e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
10216e91bba0SGirish Moodalbail 			break;
10226e91bba0SGirish Moodalbail 		default:
10236e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
10246e91bba0SGirish Moodalbail 		}
10256e91bba0SGirish Moodalbail 	}
10266e91bba0SGirish Moodalbail 
10276e91bba0SGirish Moodalbail 	if (!m_arg || !p_arg || optind != argc - 1)
10286e91bba0SGirish Moodalbail 		die("Usage: %s", use);
10296e91bba0SGirish Moodalbail 
10306e91bba0SGirish Moodalbail 	ifname = argv[optind];
10316e91bba0SGirish Moodalbail 
10326e91bba0SGirish Moodalbail 	prop_name = nv;
10336e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
10346e91bba0SGirish Moodalbail 	if (prop_val != NULL)
10356e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
10366e91bba0SGirish Moodalbail 
10376e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
10386e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
10396e91bba0SGirish Moodalbail 
10406e91bba0SGirish Moodalbail 	if (reset)
10416e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
10426e91bba0SGirish Moodalbail 	else
10436e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_ACTIVE;
10446e91bba0SGirish Moodalbail 	status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
10456e91bba0SGirish Moodalbail 	    flags);
10466e91bba0SGirish Moodalbail 
10476e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
10486e91bba0SGirish Moodalbail 		if (reset)
10496e91bba0SGirish Moodalbail 			die("reset-ifprop: %s: %s",
10506e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
10516e91bba0SGirish Moodalbail 		else
10526e91bba0SGirish Moodalbail 			die("set-ifprop: %s: %s",
10536e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
10546e91bba0SGirish Moodalbail 	}
10556e91bba0SGirish Moodalbail }
10566e91bba0SGirish Moodalbail 
10576e91bba0SGirish Moodalbail static void
do_set_ifprop(int argc,char ** argv,const char * use)10586e91bba0SGirish Moodalbail do_set_ifprop(int argc, char **argv, const char *use)
10596e91bba0SGirish Moodalbail {
10606e91bba0SGirish Moodalbail 	set_ifprop(argc, argv, _B_FALSE, use);
10616e91bba0SGirish Moodalbail }
10626e91bba0SGirish Moodalbail 
10636e91bba0SGirish Moodalbail static void
do_reset_ifprop(int argc,char ** argv,const char * use)10646e91bba0SGirish Moodalbail do_reset_ifprop(int argc, char **argv, const char *use)
10656e91bba0SGirish Moodalbail {
10666e91bba0SGirish Moodalbail 	set_ifprop(argc, argv, _B_TRUE, use);
10676e91bba0SGirish Moodalbail }
10686e91bba0SGirish Moodalbail 
10696e91bba0SGirish Moodalbail /*
10706e91bba0SGirish Moodalbail  * Display information for all or specific protocol properties, either for a
10716e91bba0SGirish Moodalbail  * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
10726e91bba0SGirish Moodalbail  */
10736e91bba0SGirish Moodalbail static void
do_show_prop(int argc,char ** argv,const char * use)10746e91bba0SGirish Moodalbail do_show_prop(int argc, char **argv, const char *use)
10756e91bba0SGirish Moodalbail {
1076*ef150c2bSRichard Lowe 	int			option;
1077467e811cSToomas Soome 	nvlist_t		*proplist = NULL;
10786e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
1079467e811cSToomas Soome 	char			*protostr;
1080467e811cSToomas Soome 	show_prop_state_t	state;
10816e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
10826e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
10836e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
10846e91bba0SGirish Moodalbail 	uint_t			proto;
10856e91bba0SGirish Moodalbail 	boolean_t		p_arg = _B_FALSE;
10866e91bba0SGirish Moodalbail 
10876e91bba0SGirish Moodalbail 	opterr = 0;
10886e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
10896e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
10906e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
10916e91bba0SGirish Moodalbail 	state.sps_modprop = _B_TRUE;
10926e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
10936e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
10946e91bba0SGirish Moodalbail 	    NULL)) != -1) {
10956e91bba0SGirish Moodalbail 		switch (option) {
10966e91bba0SGirish Moodalbail 		case 'p':
10976e91bba0SGirish Moodalbail 			if (p_arg)
10986e91bba0SGirish Moodalbail 				die("-p must be specified once only");
10996e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
11006e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
11016e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
11026e91bba0SGirish Moodalbail 				die("invalid protocol properties specified");
11036e91bba0SGirish Moodalbail 			break;
11046e91bba0SGirish Moodalbail 		case 'c':
11056e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
11066e91bba0SGirish Moodalbail 			break;
11076e91bba0SGirish Moodalbail 		case 'o':
11086e91bba0SGirish Moodalbail 			fields_str = optarg;
11096e91bba0SGirish Moodalbail 			break;
11106e91bba0SGirish Moodalbail 		default:
11116e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
11126e91bba0SGirish Moodalbail 			break;
11136e91bba0SGirish Moodalbail 		}
11146e91bba0SGirish Moodalbail 	}
11156e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
11166e91bba0SGirish Moodalbail 		protostr =  argv[optind];
11176e91bba0SGirish Moodalbail 		if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
11186e91bba0SGirish Moodalbail 			die("invalid protocol '%s' specified", protostr);
11196e91bba0SGirish Moodalbail 		state.sps_proto = proto;
11206e91bba0SGirish Moodalbail 	} else if (optind != argc) {
11216e91bba0SGirish Moodalbail 		die("Usage: %s", use);
11226e91bba0SGirish Moodalbail 	} else {
11236e91bba0SGirish Moodalbail 		if (p_arg)
11246e91bba0SGirish Moodalbail 			die("protocol must be specified when "
11256e91bba0SGirish Moodalbail 			    "property name is used");
11266e91bba0SGirish Moodalbail 		state.sps_proto = MOD_PROTO_NONE;
11276e91bba0SGirish Moodalbail 	}
11286e91bba0SGirish Moodalbail 
11296e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
11306e91bba0SGirish Moodalbail 
11316e91bba0SGirish Moodalbail 	if (state.sps_parsable)
11326e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
11336e91bba0SGirish Moodalbail 	else
11346e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_WRAP;
11356e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
1136b2f26520SBryan Cantrill 	ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
11376e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
11386e91bba0SGirish Moodalbail 
11396e91bba0SGirish Moodalbail 	/* handles all the errors */
11406e91bba0SGirish Moodalbail 	show_properties(&state, IPADMPROP_CLASS_MODULE);
11416e91bba0SGirish Moodalbail 
11426e91bba0SGirish Moodalbail 	nvlist_free(proplist);
11436e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
11446e91bba0SGirish Moodalbail 
11456e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
11466e91bba0SGirish Moodalbail 		ipadm_close(iph);
11476e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
11486e91bba0SGirish Moodalbail 	}
11496e91bba0SGirish Moodalbail }
11506e91bba0SGirish Moodalbail 
11516e91bba0SGirish Moodalbail /*
11526e91bba0SGirish Moodalbail  * Checks to see if there are any modifiers, + or -. If there are modifiers
11536e91bba0SGirish Moodalbail  * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
11546e91bba0SGirish Moodalbail  */
11556e91bba0SGirish Moodalbail static void
parse_modifiers(const char * pstr,uint_t * flags,const char * use)11568b88711aSGirish Moodalbail parse_modifiers(const char *pstr, uint_t *flags, const char *use)
11576e91bba0SGirish Moodalbail {
11586e91bba0SGirish Moodalbail 	char *p;
11596e91bba0SGirish Moodalbail 
11608b88711aSGirish Moodalbail 	if ((p = strchr(pstr, '=')) == NULL)
11618b88711aSGirish Moodalbail 		return;
11626e91bba0SGirish Moodalbail 
11638b88711aSGirish Moodalbail 	if (p == pstr)
11648b88711aSGirish Moodalbail 		die("Invalid prop=val specified\n%s", use);
11656e91bba0SGirish Moodalbail 
11668b88711aSGirish Moodalbail 	--p;
11678b88711aSGirish Moodalbail 	if (*p == '+')
11686e91bba0SGirish Moodalbail 		*flags |= IPADM_OPT_APPEND;
11698b88711aSGirish Moodalbail 	else if (*p == '-')
11706e91bba0SGirish Moodalbail 		*flags |= IPADM_OPT_REMOVE;
11716e91bba0SGirish Moodalbail }
11726e91bba0SGirish Moodalbail 
11736e91bba0SGirish Moodalbail /*
11746e91bba0SGirish Moodalbail  * set/reset the protocol property for a given protocol.
11756e91bba0SGirish Moodalbail  */
11766e91bba0SGirish Moodalbail static void
set_prop(int argc,char ** argv,boolean_t reset,const char * use)11776e91bba0SGirish Moodalbail set_prop(int argc, char **argv, boolean_t reset, const char *use)
11786e91bba0SGirish Moodalbail {
1179467e811cSToomas Soome 	int			option;
1180467e811cSToomas Soome 	ipadm_status_t		status = IPADM_SUCCESS;
1181467e811cSToomas Soome 	char			*protostr, *nv, *prop_name, *prop_val;
1182467e811cSToomas Soome 	boolean_t		p_arg = _B_FALSE;
1183467e811cSToomas Soome 	uint_t			proto;
11846e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_PERSIST;
11856e91bba0SGirish Moodalbail 
1186467e811cSToomas Soome 	nv = NULL;
11876e91bba0SGirish Moodalbail 	opterr = 0;
11886e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
11896e91bba0SGirish Moodalbail 	    NULL)) != -1) {
11906e91bba0SGirish Moodalbail 		switch (option) {
11916e91bba0SGirish Moodalbail 		case 'p':
11926e91bba0SGirish Moodalbail 			if (p_arg)
11936e91bba0SGirish Moodalbail 				die("-p must be specified once only");
11946e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
11956e91bba0SGirish Moodalbail 
11966e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
11976e91bba0SGirish Moodalbail 			nv = optarg;
11986e91bba0SGirish Moodalbail 			break;
11996e91bba0SGirish Moodalbail 		case 't':
12006e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
12016e91bba0SGirish Moodalbail 			break;
12026e91bba0SGirish Moodalbail 		default:
12036e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
12046e91bba0SGirish Moodalbail 		}
12056e91bba0SGirish Moodalbail 	}
12066e91bba0SGirish Moodalbail 
12076e91bba0SGirish Moodalbail 	if (!p_arg || optind != argc - 1)
12086e91bba0SGirish Moodalbail 		die("Usage: %s", use);
12096e91bba0SGirish Moodalbail 
12106e91bba0SGirish Moodalbail 	parse_modifiers(nv, &flags, use);
12116e91bba0SGirish Moodalbail 	prop_name = nv;
12126e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
12136e91bba0SGirish Moodalbail 	if (prop_val != NULL) {
12146e91bba0SGirish Moodalbail 		if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
12156e91bba0SGirish Moodalbail 			*(prop_val - 1) = '\0';
12166e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
12176e91bba0SGirish Moodalbail 	}
12186e91bba0SGirish Moodalbail 	protostr = argv[optind];
12196e91bba0SGirish Moodalbail 	if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
12206e91bba0SGirish Moodalbail 		die("invalid protocol '%s' specified", protostr);
12216e91bba0SGirish Moodalbail 
12226e91bba0SGirish Moodalbail 	if (reset)
12236e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
12246e91bba0SGirish Moodalbail 	else
12256e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_ACTIVE;
12266e91bba0SGirish Moodalbail 	status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
1227467e811cSToomas Soome 
12286e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
12296e91bba0SGirish Moodalbail 		if (reset)
12306e91bba0SGirish Moodalbail 			die("reset-prop: %s: %s",
12316e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
12326e91bba0SGirish Moodalbail 		else
12336e91bba0SGirish Moodalbail 			die("set-prop: %s: %s",
12346e91bba0SGirish Moodalbail 			    prop_name, ipadm_status2str(status));
12356e91bba0SGirish Moodalbail 	}
12366e91bba0SGirish Moodalbail }
12376e91bba0SGirish Moodalbail 
12386e91bba0SGirish Moodalbail static void
do_set_prop(int argc,char ** argv,const char * use)12396e91bba0SGirish Moodalbail do_set_prop(int argc, char **argv, const char *use)
12406e91bba0SGirish Moodalbail {
12416e91bba0SGirish Moodalbail 	set_prop(argc, argv, _B_FALSE, use);
12426e91bba0SGirish Moodalbail }
12436e91bba0SGirish Moodalbail 
12446e91bba0SGirish Moodalbail static void
do_reset_prop(int argc,char ** argv,const char * use)12456e91bba0SGirish Moodalbail do_reset_prop(int argc, char **argv, const char *use)
12466e91bba0SGirish Moodalbail {
12476e91bba0SGirish Moodalbail 	set_prop(argc, argv,  _B_TRUE, use);
12486e91bba0SGirish Moodalbail }
12496e91bba0SGirish Moodalbail 
12506e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
12516e91bba0SGirish Moodalbail static void
warn(const char * format,...)12526e91bba0SGirish Moodalbail warn(const char *format, ...)
12536e91bba0SGirish Moodalbail {
12546e91bba0SGirish Moodalbail 	va_list alist;
12556e91bba0SGirish Moodalbail 
12566e91bba0SGirish Moodalbail 	format = gettext(format);
12576e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: warning: "), progname);
12586e91bba0SGirish Moodalbail 
12596e91bba0SGirish Moodalbail 	va_start(alist, format);
12606e91bba0SGirish Moodalbail 	(void) vfprintf(stderr, format, alist);
12616e91bba0SGirish Moodalbail 	va_end(alist);
12626e91bba0SGirish Moodalbail 
12636e91bba0SGirish Moodalbail 	(void) fprintf(stderr, "\n");
12646e91bba0SGirish Moodalbail }
12656e91bba0SGirish Moodalbail 
12666e91bba0SGirish Moodalbail /* PRINTFLIKE1 */
12676e91bba0SGirish Moodalbail static void
die(const char * format,...)12686e91bba0SGirish Moodalbail die(const char *format, ...)
12696e91bba0SGirish Moodalbail {
12706e91bba0SGirish Moodalbail 	va_list alist;
12716e91bba0SGirish Moodalbail 
1272a73be61aSHans Rosenfeld 	if (format != NULL) {
1273a73be61aSHans Rosenfeld 		format = gettext(format);
1274a73be61aSHans Rosenfeld 		(void) fprintf(stderr, "%s: ", progname);
12756e91bba0SGirish Moodalbail 
1276a73be61aSHans Rosenfeld 		va_start(alist, format);
1277a73be61aSHans Rosenfeld 		(void) vfprintf(stderr, format, alist);
1278a73be61aSHans Rosenfeld 		va_end(alist);
12796e91bba0SGirish Moodalbail 
1280a73be61aSHans Rosenfeld 		(void) putchar('\n');
1281a73be61aSHans Rosenfeld 	}
12826e91bba0SGirish Moodalbail 
12836e91bba0SGirish Moodalbail 	ipadm_destroy_addrobj(ipaddr);
12846e91bba0SGirish Moodalbail 	ipadm_close(iph);
12856e91bba0SGirish Moodalbail 	exit(EXIT_FAILURE);
12866e91bba0SGirish Moodalbail }
12876e91bba0SGirish Moodalbail 
12886e91bba0SGirish Moodalbail static void
die_opterr(int opt,int opterr,const char * usage)12896e91bba0SGirish Moodalbail die_opterr(int opt, int opterr, const char *usage)
12906e91bba0SGirish Moodalbail {
12916e91bba0SGirish Moodalbail 	switch (opterr) {
12926e91bba0SGirish Moodalbail 	case ':':
12936e91bba0SGirish Moodalbail 		die("option '-%c' requires a value\nusage: %s", opt,
12946e91bba0SGirish Moodalbail 		    gettext(usage));
12956e91bba0SGirish Moodalbail 		break;
12966e91bba0SGirish Moodalbail 	case '?':
12976e91bba0SGirish Moodalbail 	default:
12986e91bba0SGirish Moodalbail 		die("unrecognized option '-%c'\nusage: %s", opt,
12996e91bba0SGirish Moodalbail 		    gettext(usage));
13006e91bba0SGirish Moodalbail 		break;
13016e91bba0SGirish Moodalbail 	}
13026e91bba0SGirish Moodalbail }
13036e91bba0SGirish Moodalbail 
13046e91bba0SGirish Moodalbail /* PRINTFLIKE2 */
13056e91bba0SGirish Moodalbail static void
warn_ipadmerr(ipadm_status_t err,const char * format,...)13066e91bba0SGirish Moodalbail warn_ipadmerr(ipadm_status_t err, const char *format, ...)
13076e91bba0SGirish Moodalbail {
13086e91bba0SGirish Moodalbail 	va_list alist;
13096e91bba0SGirish Moodalbail 
13106e91bba0SGirish Moodalbail 	format = gettext(format);
13116e91bba0SGirish Moodalbail 	(void) fprintf(stderr, gettext("%s: warning: "), progname);
13126e91bba0SGirish Moodalbail 
13136e91bba0SGirish Moodalbail 	va_start(alist, format);
13146e91bba0SGirish Moodalbail 	(void) vfprintf(stderr, format, alist);
13156e91bba0SGirish Moodalbail 	va_end(alist);
13166e91bba0SGirish Moodalbail 
13176e91bba0SGirish Moodalbail 	(void) fprintf(stderr, "%s\n", ipadm_status2str(err));
13186e91bba0SGirish Moodalbail }
13196e91bba0SGirish Moodalbail 
13206e91bba0SGirish Moodalbail static void
process_static_addrargs(const char * use,char * addrarg,const char * aobjname)13216e91bba0SGirish Moodalbail process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
13226e91bba0SGirish Moodalbail {
13236e91bba0SGirish Moodalbail 	int		option;
13246e91bba0SGirish Moodalbail 	char		*val;
13256e91bba0SGirish Moodalbail 	char		*laddr = NULL;
13266e91bba0SGirish Moodalbail 	char		*raddr = NULL;
13276e91bba0SGirish Moodalbail 	char		*save_input_arg = addrarg;
13286e91bba0SGirish Moodalbail 	boolean_t	found_mismatch = _B_FALSE;
13296e91bba0SGirish Moodalbail 	ipadm_status_t	status;
13306e91bba0SGirish Moodalbail 	enum		{ A_LOCAL, A_REMOTE };
13316e91bba0SGirish Moodalbail 	static char	*addr_optstr[] = {
13326e91bba0SGirish Moodalbail 		"local",
13336e91bba0SGirish Moodalbail 		"remote",
13346e91bba0SGirish Moodalbail 		NULL,
13356e91bba0SGirish Moodalbail 	};
13366e91bba0SGirish Moodalbail 
13376e91bba0SGirish Moodalbail 	while (*addrarg != '\0') {
13386e91bba0SGirish Moodalbail 		option = getsubopt(&addrarg, addr_optstr, &val);
13396e91bba0SGirish Moodalbail 		switch (option) {
13406e91bba0SGirish Moodalbail 		case A_LOCAL:
13416e91bba0SGirish Moodalbail 			if (laddr != NULL)
13426e91bba0SGirish Moodalbail 				die("Multiple local addresses provided");
13436e91bba0SGirish Moodalbail 			laddr = val;
13446e91bba0SGirish Moodalbail 			break;
13456e91bba0SGirish Moodalbail 		case A_REMOTE:
13466e91bba0SGirish Moodalbail 			if (raddr != NULL)
13476e91bba0SGirish Moodalbail 				die("Multiple remote addresses provided");
13486e91bba0SGirish Moodalbail 			raddr = val;
13496e91bba0SGirish Moodalbail 			break;
13506e91bba0SGirish Moodalbail 		default:
13516e91bba0SGirish Moodalbail 			if (found_mismatch)
13526e91bba0SGirish Moodalbail 				die("Invalid address provided\nusage: %s", use);
13536e91bba0SGirish Moodalbail 			found_mismatch = _B_TRUE;
13546e91bba0SGirish Moodalbail 			break;
13556e91bba0SGirish Moodalbail 		}
13566e91bba0SGirish Moodalbail 	}
13576e91bba0SGirish Moodalbail 	if (raddr != NULL && laddr == NULL)
13586e91bba0SGirish Moodalbail 		die("Missing local address\nusage: %s", use);
13596e91bba0SGirish Moodalbail 
13606e91bba0SGirish Moodalbail 	/* If only one address is provided, it is assumed a local address. */
13616e91bba0SGirish Moodalbail 	if (laddr == NULL) {
13626e91bba0SGirish Moodalbail 		if (found_mismatch)
13636e91bba0SGirish Moodalbail 			laddr = save_input_arg;
13646e91bba0SGirish Moodalbail 		else
13656e91bba0SGirish Moodalbail 			die("Missing local address\nusage: %s", use);
13666e91bba0SGirish Moodalbail 	}
13676e91bba0SGirish Moodalbail 
13686e91bba0SGirish Moodalbail 	/* Initialize the addrobj for static addresses. */
13696e91bba0SGirish Moodalbail 	status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
13706e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
13716e91bba0SGirish Moodalbail 		die("Error in creating address object: %s",
13726e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
13736e91bba0SGirish Moodalbail 	}
13746e91bba0SGirish Moodalbail 
13756e91bba0SGirish Moodalbail 	/* Set the local and remote addresses */
13766e91bba0SGirish Moodalbail 	status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
13776e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
13786e91bba0SGirish Moodalbail 		die("Error in setting local address: %s",
13796e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
13806e91bba0SGirish Moodalbail 	}
13816e91bba0SGirish Moodalbail 	if (raddr != NULL) {
13826e91bba0SGirish Moodalbail 		status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
13836e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
13846e91bba0SGirish Moodalbail 			die("Error in setting remote address: %s",
13856e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
13866e91bba0SGirish Moodalbail 		}
13876e91bba0SGirish Moodalbail 	}
13886e91bba0SGirish Moodalbail }
13896e91bba0SGirish Moodalbail 
13906e91bba0SGirish Moodalbail static void
process_addrconf_addrargs(const char * use,char * addrarg)13916e91bba0SGirish Moodalbail process_addrconf_addrargs(const char *use, char *addrarg)
13926e91bba0SGirish Moodalbail {
13936e91bba0SGirish Moodalbail 	int		option;
13946e91bba0SGirish Moodalbail 	char		*val;
13956e91bba0SGirish Moodalbail 	enum		{ P_STATELESS, P_STATEFUL };
13966e91bba0SGirish Moodalbail 	static char	*addr_optstr[] = {
13976e91bba0SGirish Moodalbail 		"stateless",
13986e91bba0SGirish Moodalbail 		"stateful",
13996e91bba0SGirish Moodalbail 		NULL,
14006e91bba0SGirish Moodalbail 	};
1401467e811cSToomas Soome 	boolean_t	stateless = _B_FALSE;
14026e91bba0SGirish Moodalbail 	boolean_t	stateless_arg = _B_FALSE;
1403467e811cSToomas Soome 	boolean_t	stateful = _B_FALSE;
14046e91bba0SGirish Moodalbail 	boolean_t	stateful_arg = _B_FALSE;
14056e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14066e91bba0SGirish Moodalbail 
14076e91bba0SGirish Moodalbail 	while (*addrarg != '\0') {
14086e91bba0SGirish Moodalbail 		option = getsubopt(&addrarg, addr_optstr, &val);
14096e91bba0SGirish Moodalbail 		switch (option) {
14106e91bba0SGirish Moodalbail 		case P_STATELESS:
14116e91bba0SGirish Moodalbail 			if (stateless_arg)
14126e91bba0SGirish Moodalbail 				die("Duplicate option");
14137bc87895SYuri Pankov 			if (val == NULL)
14147bc87895SYuri Pankov 				die("Invalid argument");
14156e91bba0SGirish Moodalbail 			if (strcmp(val, "yes") == 0)
14166e91bba0SGirish Moodalbail 				stateless = _B_TRUE;
14176e91bba0SGirish Moodalbail 			else if (strcmp(val, "no") == 0)
14186e91bba0SGirish Moodalbail 				stateless = _B_FALSE;
14196e91bba0SGirish Moodalbail 			else
14206e91bba0SGirish Moodalbail 				die("Invalid argument");
14216e91bba0SGirish Moodalbail 			stateless_arg = _B_TRUE;
14226e91bba0SGirish Moodalbail 			break;
14236e91bba0SGirish Moodalbail 		case P_STATEFUL:
14246e91bba0SGirish Moodalbail 			if (stateful_arg)
14256e91bba0SGirish Moodalbail 				die("Duplicate option");
14267bc87895SYuri Pankov 			if (val == NULL)
14277bc87895SYuri Pankov 				die("Invalid argument");
14286e91bba0SGirish Moodalbail 			if (strcmp(val, "yes") == 0)
14296e91bba0SGirish Moodalbail 				stateful = _B_TRUE;
14306e91bba0SGirish Moodalbail 			else if (strcmp(val, "no") == 0)
14316e91bba0SGirish Moodalbail 				stateful = _B_FALSE;
14326e91bba0SGirish Moodalbail 			else
14336e91bba0SGirish Moodalbail 				die("Invalid argument");
14346e91bba0SGirish Moodalbail 			stateful_arg = _B_TRUE;
14356e91bba0SGirish Moodalbail 			break;
14366e91bba0SGirish Moodalbail 		default:
14376e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
14386e91bba0SGirish Moodalbail 		}
14396e91bba0SGirish Moodalbail 	}
14406e91bba0SGirish Moodalbail 
14416e91bba0SGirish Moodalbail 	if (!stateless_arg && !stateful_arg)
14426e91bba0SGirish Moodalbail 		die("Invalid arguments for option -p");
14436e91bba0SGirish Moodalbail 
14446e91bba0SGirish Moodalbail 	/* Set the addrobj fields for addrconf */
14456e91bba0SGirish Moodalbail 	if (stateless_arg) {
14466e91bba0SGirish Moodalbail 		status = ipadm_set_stateless(ipaddr, stateless);
14476e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
14486e91bba0SGirish Moodalbail 			die("Error in setting stateless option: %s",
14496e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
14506e91bba0SGirish Moodalbail 		}
14516e91bba0SGirish Moodalbail 	}
14526e91bba0SGirish Moodalbail 	if (stateful_arg) {
14536e91bba0SGirish Moodalbail 		status = ipadm_set_stateful(ipaddr, stateful);
14546e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
14556e91bba0SGirish Moodalbail 			die("Error in setting stateful option: %s",
14566e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
14576e91bba0SGirish Moodalbail 		}
14586e91bba0SGirish Moodalbail 	}
14596e91bba0SGirish Moodalbail }
14606e91bba0SGirish Moodalbail 
14616e91bba0SGirish Moodalbail /*
14626e91bba0SGirish Moodalbail  * Creates static, dhcp or addrconf addresses and associates the created
14636e91bba0SGirish Moodalbail  * addresses with the specified address object name.
14646e91bba0SGirish Moodalbail  */
14656e91bba0SGirish Moodalbail static void
do_create_addr(int argc,char * argv[],const char * use)14666e91bba0SGirish Moodalbail do_create_addr(int argc, char *argv[], const char *use)
14676e91bba0SGirish Moodalbail {
14686e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14696e91bba0SGirish Moodalbail 	int		option;
14706e91bba0SGirish Moodalbail 	uint32_t	flags =
1471f6da83d4SAnurag S. Maskey 	    IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
14726e91bba0SGirish Moodalbail 	char		*cp;
14736e91bba0SGirish Moodalbail 	char		*atype = NULL;
14746e91bba0SGirish Moodalbail 	char		*static_arg = NULL;
14756e91bba0SGirish Moodalbail 	char		*addrconf_arg = NULL;
14766e91bba0SGirish Moodalbail 	char		*interface_id = NULL;
14776e91bba0SGirish Moodalbail 	char		*wait = NULL;
1478b31320a7SChris Fraire 	char		*reqhost = NULL;
14796e91bba0SGirish Moodalbail 	boolean_t	s_opt = _B_FALSE;	/* static addr options */
14806e91bba0SGirish Moodalbail 	boolean_t	auto_opt = _B_FALSE;	/* Addrconf options */
14816e91bba0SGirish Moodalbail 	boolean_t	dhcp_opt = _B_FALSE;	/* dhcp options */
1482b31320a7SChris Fraire 	boolean_t	primary_opt = _B_FALSE;	/* dhcp primary option */
14836e91bba0SGirish Moodalbail 
14846e91bba0SGirish Moodalbail 	opterr = 0;
1485b31320a7SChris Fraire 	while ((option = getopt_long(argc, argv, ":1T:a:dh:i:p:w:t",
14866e91bba0SGirish Moodalbail 	    addr_longopts, NULL)) != -1) {
14876e91bba0SGirish Moodalbail 		switch (option) {
1488b31320a7SChris Fraire 		case '1':
1489b31320a7SChris Fraire 			primary_opt = _B_TRUE;
1490b31320a7SChris Fraire 			break;
14916e91bba0SGirish Moodalbail 		case 'T':
14926e91bba0SGirish Moodalbail 			atype = optarg;
14936e91bba0SGirish Moodalbail 			break;
14946e91bba0SGirish Moodalbail 		case 'a':
14956e91bba0SGirish Moodalbail 			static_arg = optarg;
14966e91bba0SGirish Moodalbail 			s_opt = _B_TRUE;
14976e91bba0SGirish Moodalbail 			break;
14986e91bba0SGirish Moodalbail 		case 'd':
14996e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_UP;
15006e91bba0SGirish Moodalbail 			s_opt = _B_TRUE;
15016e91bba0SGirish Moodalbail 			break;
1502b31320a7SChris Fraire 		case 'h':
1503b31320a7SChris Fraire 			reqhost = optarg;
1504b31320a7SChris Fraire 			break;
15056e91bba0SGirish Moodalbail 		case 'i':
15066e91bba0SGirish Moodalbail 			interface_id = optarg;
15076e91bba0SGirish Moodalbail 			auto_opt = _B_TRUE;
15086e91bba0SGirish Moodalbail 			break;
15096e91bba0SGirish Moodalbail 		case 'p':
15106e91bba0SGirish Moodalbail 			addrconf_arg = optarg;
15116e91bba0SGirish Moodalbail 			auto_opt = _B_TRUE;
15126e91bba0SGirish Moodalbail 			break;
15136e91bba0SGirish Moodalbail 		case 'w':
15146e91bba0SGirish Moodalbail 			wait = optarg;
15156e91bba0SGirish Moodalbail 			dhcp_opt = _B_TRUE;
15166e91bba0SGirish Moodalbail 			break;
15176e91bba0SGirish Moodalbail 		case 't':
15186e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
15196e91bba0SGirish Moodalbail 			break;
15206e91bba0SGirish Moodalbail 		default:
15216e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
15226e91bba0SGirish Moodalbail 		}
15236e91bba0SGirish Moodalbail 	}
15246e91bba0SGirish Moodalbail 	if (atype == NULL || optind != (argc - 1)) {
15256e91bba0SGirish Moodalbail 		die("Invalid arguments\nusage: %s", use);
15266e91bba0SGirish Moodalbail 	} else if ((cp = strchr(argv[optind], '/')) == NULL ||
15276e91bba0SGirish Moodalbail 	    strlen(++cp) == 0) {
15286e91bba0SGirish Moodalbail 		die("invalid address object name: %s\nusage: %s",
15296e91bba0SGirish Moodalbail 		    argv[optind], use);
15306e91bba0SGirish Moodalbail 	}
15316e91bba0SGirish Moodalbail 
15326e91bba0SGirish Moodalbail 	/*
15336e91bba0SGirish Moodalbail 	 * Allocate and initialize the addrobj based on the address type.
15346e91bba0SGirish Moodalbail 	 */
15356e91bba0SGirish Moodalbail 	if (strcmp(atype, "static") == 0) {
1536b31320a7SChris Fraire 		if (static_arg == NULL || auto_opt || dhcp_opt ||
1537b31320a7SChris Fraire 		    reqhost != NULL || primary_opt) {
15386e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
15396e91bba0SGirish Moodalbail 			    atype, use);
15406e91bba0SGirish Moodalbail 		}
15416e91bba0SGirish Moodalbail 		process_static_addrargs(use, static_arg, argv[optind]);
15426e91bba0SGirish Moodalbail 	} else if (strcmp(atype, "dhcp") == 0) {
15436e91bba0SGirish Moodalbail 		if (auto_opt || s_opt) {
15446e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
15456e91bba0SGirish Moodalbail 			    atype, use);
15466e91bba0SGirish Moodalbail 		}
15476e91bba0SGirish Moodalbail 
15486e91bba0SGirish Moodalbail 		/* Initialize the addrobj for dhcp addresses. */
15496e91bba0SGirish Moodalbail 		status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
15506e91bba0SGirish Moodalbail 		    &ipaddr);
15516e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
15526e91bba0SGirish Moodalbail 			die("Error in creating address object: %s",
15536e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
15546e91bba0SGirish Moodalbail 		}
15556e91bba0SGirish Moodalbail 		if (wait != NULL) {
15566e91bba0SGirish Moodalbail 			int32_t ipadm_wait;
15576e91bba0SGirish Moodalbail 
15586e91bba0SGirish Moodalbail 			if (strcmp(wait, "forever") == 0) {
15596e91bba0SGirish Moodalbail 				ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
15606e91bba0SGirish Moodalbail 			} else {
15616e91bba0SGirish Moodalbail 				char *end;
15626e91bba0SGirish Moodalbail 				long timeout = strtol(wait, &end, 10);
15636e91bba0SGirish Moodalbail 
15646e91bba0SGirish Moodalbail 				if (*end != '\0' || timeout < 0)
15656e91bba0SGirish Moodalbail 					die("Invalid argument");
15666e91bba0SGirish Moodalbail 				ipadm_wait = (int32_t)timeout;
15676e91bba0SGirish Moodalbail 			}
15686e91bba0SGirish Moodalbail 			status = ipadm_set_wait_time(ipaddr, ipadm_wait);
15696e91bba0SGirish Moodalbail 			if (status != IPADM_SUCCESS) {
15706e91bba0SGirish Moodalbail 				die("Error in setting wait time: %s",
15716e91bba0SGirish Moodalbail 				    ipadm_status2str(status));
15726e91bba0SGirish Moodalbail 			}
15736e91bba0SGirish Moodalbail 		}
1574b31320a7SChris Fraire 		if (primary_opt) {
1575b31320a7SChris Fraire 			status = ipadm_set_primary(ipaddr, _B_TRUE);
1576b31320a7SChris Fraire 			if (status != IPADM_SUCCESS) {
1577b31320a7SChris Fraire 				die("Error in setting primary flag: %s",
1578b31320a7SChris Fraire 				    ipadm_status2str(status));
1579b31320a7SChris Fraire 			}
1580b31320a7SChris Fraire 		}
1581b31320a7SChris Fraire 		if (reqhost != NULL) {
1582b31320a7SChris Fraire 			status = ipadm_set_reqhost(ipaddr, reqhost);
1583b31320a7SChris Fraire 			if (status != IPADM_SUCCESS) {
1584b31320a7SChris Fraire 				die("Error in setting reqhost: %s",
1585b31320a7SChris Fraire 				    ipadm_status2str(status));
1586b31320a7SChris Fraire 			}
1587b31320a7SChris Fraire 		}
15886e91bba0SGirish Moodalbail 	} else if (strcmp(atype, "addrconf") == 0) {
1589b31320a7SChris Fraire 		if (dhcp_opt || s_opt || reqhost != NULL || primary_opt) {
15906e91bba0SGirish Moodalbail 			die("Invalid arguments for type %s\nusage: %s",
15916e91bba0SGirish Moodalbail 			    atype, use);
15926e91bba0SGirish Moodalbail 		}
15936e91bba0SGirish Moodalbail 
1594b31320a7SChris Fraire 		/* Initialize the addrobj for ipv6-addrconf addresses. */
15956e91bba0SGirish Moodalbail 		status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
15966e91bba0SGirish Moodalbail 		    argv[optind], &ipaddr);
15976e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS) {
15986e91bba0SGirish Moodalbail 			die("Error in creating address object: %s",
15996e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
16006e91bba0SGirish Moodalbail 		}
16016e91bba0SGirish Moodalbail 		if (interface_id != NULL) {
16026e91bba0SGirish Moodalbail 			status = ipadm_set_interface_id(ipaddr, interface_id);
16036e91bba0SGirish Moodalbail 			if (status != IPADM_SUCCESS) {
16046e91bba0SGirish Moodalbail 				die("Error in setting interface ID: %s",
16056e91bba0SGirish Moodalbail 				    ipadm_status2str(status));
16066e91bba0SGirish Moodalbail 			}
16076e91bba0SGirish Moodalbail 		}
16086e91bba0SGirish Moodalbail 		if (addrconf_arg)
16096e91bba0SGirish Moodalbail 			process_addrconf_addrargs(use, addrconf_arg);
16106e91bba0SGirish Moodalbail 	} else {
16116e91bba0SGirish Moodalbail 		die("Invalid address type %s", atype);
16126e91bba0SGirish Moodalbail 	}
16136e91bba0SGirish Moodalbail 
16146e91bba0SGirish Moodalbail 	status = ipadm_create_addr(iph, ipaddr, flags);
16156e91bba0SGirish Moodalbail 	if (status == IPADM_DHCP_IPC_TIMEOUT)
16166e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
16176e91bba0SGirish Moodalbail 	else if (status != IPADM_SUCCESS)
16186e91bba0SGirish Moodalbail 		die("Could not create address: %s", ipadm_status2str(status));
16196e91bba0SGirish Moodalbail }
16206e91bba0SGirish Moodalbail 
16216e91bba0SGirish Moodalbail /*
16226e91bba0SGirish Moodalbail  * Used by some address management functions to parse the command line
16236e91bba0SGirish Moodalbail  * arguments and create `ipaddr' address object.
16246e91bba0SGirish Moodalbail  */
16256e91bba0SGirish Moodalbail static void
process_misc_addrargs(int argc,char * argv[],const char * use,int * index,uint32_t * flags)16266e91bba0SGirish Moodalbail process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
16276e91bba0SGirish Moodalbail     uint32_t *flags)
16286e91bba0SGirish Moodalbail {
16296e91bba0SGirish Moodalbail 	int		option;
16306e91bba0SGirish Moodalbail 
16316e91bba0SGirish Moodalbail 	opterr = 0;
16326e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
16336e91bba0SGirish Moodalbail 	    NULL)) != -1) {
16346e91bba0SGirish Moodalbail 		switch (option) {
16356e91bba0SGirish Moodalbail 		case 't':
16366e91bba0SGirish Moodalbail 			*flags &= ~IPADM_OPT_PERSIST;
16376e91bba0SGirish Moodalbail 			break;
16386e91bba0SGirish Moodalbail 		default:
16396e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
16406e91bba0SGirish Moodalbail 		}
16416e91bba0SGirish Moodalbail 	}
16426e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
16436e91bba0SGirish Moodalbail 		die("Usage: %s", use);
16446e91bba0SGirish Moodalbail 
16456e91bba0SGirish Moodalbail 	*index = optind;
16466e91bba0SGirish Moodalbail }
16476e91bba0SGirish Moodalbail 
16486e91bba0SGirish Moodalbail /*
16496e91bba0SGirish Moodalbail  * Remove an addrobj from both active and persistent configuration.
16506e91bba0SGirish Moodalbail  */
16516e91bba0SGirish Moodalbail static void
do_delete_addr(int argc,char * argv[],const char * use)16526e91bba0SGirish Moodalbail do_delete_addr(int argc, char *argv[], const char *use)
16536e91bba0SGirish Moodalbail {
16546e91bba0SGirish Moodalbail 	ipadm_status_t	status;
1655467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
16566e91bba0SGirish Moodalbail 	int		option;
16576e91bba0SGirish Moodalbail 
16586e91bba0SGirish Moodalbail 	opterr = 0;
16596e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
16606e91bba0SGirish Moodalbail 	    NULL)) != -1) {
16616e91bba0SGirish Moodalbail 		switch (option) {
16626e91bba0SGirish Moodalbail 		case 'r':
16636e91bba0SGirish Moodalbail 			flags |= IPADM_OPT_RELEASE;
16646e91bba0SGirish Moodalbail 			break;
16656e91bba0SGirish Moodalbail 		default:
16666e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
16676e91bba0SGirish Moodalbail 		}
16686e91bba0SGirish Moodalbail 	}
16696e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
16706e91bba0SGirish Moodalbail 		die("Usage: %s", use);
16716e91bba0SGirish Moodalbail 
16726e91bba0SGirish Moodalbail 	status = ipadm_delete_addr(iph, argv[optind], flags);
16736e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
16746e91bba0SGirish Moodalbail 		die("could not delete address: %s",
16756e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
16766e91bba0SGirish Moodalbail 	}
16776e91bba0SGirish Moodalbail }
16786e91bba0SGirish Moodalbail 
16796e91bba0SGirish Moodalbail /*
16806e91bba0SGirish Moodalbail  * Enable an IP address based on the persistent configuration for that
16816e91bba0SGirish Moodalbail  * IP address
16826e91bba0SGirish Moodalbail  */
16836e91bba0SGirish Moodalbail static void
do_enable_addr(int argc,char * argv[],const char * use)16846e91bba0SGirish Moodalbail do_enable_addr(int argc, char *argv[], const char *use)
16856e91bba0SGirish Moodalbail {
16866e91bba0SGirish Moodalbail 	ipadm_status_t	status;
16876e91bba0SGirish Moodalbail 	int		index;
1688467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
16896e91bba0SGirish Moodalbail 
16906e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
16916e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
16926e91bba0SGirish Moodalbail 		die("persistent operation not supported for enable-addr");
16936e91bba0SGirish Moodalbail 
16946e91bba0SGirish Moodalbail 	status = ipadm_enable_addr(iph, argv[index], flags);
16956e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
16966e91bba0SGirish Moodalbail 		die("could not enable address: %s", ipadm_status2str(status));
16976e91bba0SGirish Moodalbail }
16986e91bba0SGirish Moodalbail 
16996e91bba0SGirish Moodalbail /*
17006e91bba0SGirish Moodalbail  * Mark the address identified by addrobj 'up'
17016e91bba0SGirish Moodalbail  */
17026e91bba0SGirish Moodalbail static void
do_up_addr(int argc,char * argv[],const char * use)17036e91bba0SGirish Moodalbail do_up_addr(int argc, char *argv[], const char *use)
17046e91bba0SGirish Moodalbail {
17056e91bba0SGirish Moodalbail 	ipadm_status_t	status;
17066e91bba0SGirish Moodalbail 	int		index;
1707467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17086e91bba0SGirish Moodalbail 
17096e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
17106e91bba0SGirish Moodalbail 	status = ipadm_up_addr(iph, argv[index], flags);
17116e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
17126e91bba0SGirish Moodalbail 		die("Could not mark the address up: %s",
17136e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
17146e91bba0SGirish Moodalbail 	}
17156e91bba0SGirish Moodalbail }
17166e91bba0SGirish Moodalbail 
17176e91bba0SGirish Moodalbail /*
17186e91bba0SGirish Moodalbail  * Disable the specified addrobj by removing it from active cofiguration
17196e91bba0SGirish Moodalbail  */
17206e91bba0SGirish Moodalbail static void
do_disable_addr(int argc,char * argv[],const char * use)17216e91bba0SGirish Moodalbail do_disable_addr(int argc, char *argv[], const char *use)
17226e91bba0SGirish Moodalbail {
17236e91bba0SGirish Moodalbail 	ipadm_status_t	status;
17246e91bba0SGirish Moodalbail 	int		index;
1725467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17266e91bba0SGirish Moodalbail 
17276e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
17286e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_PERSIST)
17296e91bba0SGirish Moodalbail 		die("persistent operation not supported for disable-addr");
17306e91bba0SGirish Moodalbail 
17316e91bba0SGirish Moodalbail 	status = ipadm_disable_addr(iph, argv[index], flags);
17326e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
17336e91bba0SGirish Moodalbail 		die("could not disable address: %s",
17346e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
17356e91bba0SGirish Moodalbail 	}
17366e91bba0SGirish Moodalbail }
17376e91bba0SGirish Moodalbail 
17386e91bba0SGirish Moodalbail /*
17396e91bba0SGirish Moodalbail  * Mark the address identified by addrobj 'down'
17406e91bba0SGirish Moodalbail  */
17416e91bba0SGirish Moodalbail static void
do_down_addr(int argc,char * argv[],const char * use)17426e91bba0SGirish Moodalbail do_down_addr(int argc, char *argv[], const char *use)
17436e91bba0SGirish Moodalbail {
17446e91bba0SGirish Moodalbail 	ipadm_status_t	status;
17456e91bba0SGirish Moodalbail 	int		index;
1746467e811cSToomas Soome 	uint32_t	flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
17476e91bba0SGirish Moodalbail 
17486e91bba0SGirish Moodalbail 	process_misc_addrargs(argc, argv, use, &index, &flags);
17496e91bba0SGirish Moodalbail 	status = ipadm_down_addr(iph, argv[index], flags);
17506e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
17516e91bba0SGirish Moodalbail 		die("Could not mark the address down: %s",
17526e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
17536e91bba0SGirish Moodalbail }
17546e91bba0SGirish Moodalbail 
17556e91bba0SGirish Moodalbail /*
17566e91bba0SGirish Moodalbail  * Restart DAD for static address. Extend lease duration for DHCP addresses
17576e91bba0SGirish Moodalbail  */
17586e91bba0SGirish Moodalbail static void
do_refresh_addr(int argc,char * argv[],const char * use)17596e91bba0SGirish Moodalbail do_refresh_addr(int argc, char *argv[], const char *use)
17606e91bba0SGirish Moodalbail {
17616e91bba0SGirish Moodalbail 	ipadm_status_t	status;
17626e91bba0SGirish Moodalbail 	int		option;
17636e91bba0SGirish Moodalbail 	uint32_t	flags = 0;
17646e91bba0SGirish Moodalbail 
17656e91bba0SGirish Moodalbail 	opterr = 0;
17666e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
17676e91bba0SGirish Moodalbail 	    NULL)) != -1) {
17686e91bba0SGirish Moodalbail 		switch (option) {
17696e91bba0SGirish Moodalbail 		case 'i':
17706e91bba0SGirish Moodalbail 			flags |= IPADM_OPT_INFORM;
17716e91bba0SGirish Moodalbail 			break;
17726e91bba0SGirish Moodalbail 		default:
17736e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
17746e91bba0SGirish Moodalbail 		}
17756e91bba0SGirish Moodalbail 	}
17766e91bba0SGirish Moodalbail 	if (optind != (argc - 1))
17776e91bba0SGirish Moodalbail 		die("Usage: %s", use);
17786e91bba0SGirish Moodalbail 
17796e91bba0SGirish Moodalbail 	status = ipadm_refresh_addr(iph, argv[optind], flags);
17806e91bba0SGirish Moodalbail 	if (status == IPADM_DHCP_IPC_TIMEOUT)
17816e91bba0SGirish Moodalbail 		warn_ipadmerr(status, "");
17826e91bba0SGirish Moodalbail 	else if (status != IPADM_SUCCESS)
17836e91bba0SGirish Moodalbail 		die("could not refresh address %s", ipadm_status2str(status));
17846e91bba0SGirish Moodalbail }
17856e91bba0SGirish Moodalbail 
17866e91bba0SGirish Moodalbail static void
sockaddr2str(const struct sockaddr_storage * ssp,char * buf,uint_t bufsize)17876e91bba0SGirish Moodalbail sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
17886e91bba0SGirish Moodalbail {
17896e91bba0SGirish Moodalbail 	socklen_t socklen;
17906e91bba0SGirish Moodalbail 	struct sockaddr *sp = (struct sockaddr *)ssp;
17916e91bba0SGirish Moodalbail 
17926e91bba0SGirish Moodalbail 	switch (ssp->ss_family) {
17936e91bba0SGirish Moodalbail 	case AF_INET:
17946e91bba0SGirish Moodalbail 		socklen = sizeof (struct sockaddr_in);
17956e91bba0SGirish Moodalbail 		break;
17966e91bba0SGirish Moodalbail 	case AF_INET6:
17976e91bba0SGirish Moodalbail 		socklen = sizeof (struct sockaddr_in6);
17986e91bba0SGirish Moodalbail 		break;
17996e91bba0SGirish Moodalbail 	default:
18006e91bba0SGirish Moodalbail 		(void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
18016e91bba0SGirish Moodalbail 		return;
18026e91bba0SGirish Moodalbail 	}
18036e91bba0SGirish Moodalbail 
18046e91bba0SGirish Moodalbail 	(void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
18056e91bba0SGirish Moodalbail 	    (NI_NOFQDN | NI_NUMERICHOST));
18066e91bba0SGirish Moodalbail }
18076e91bba0SGirish Moodalbail 
18086e91bba0SGirish Moodalbail static void
flags2str(uint64_t flags,fmask_t * tbl,boolean_t is_bits,char * buf,uint_t bufsize)18096e91bba0SGirish Moodalbail flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
18106e91bba0SGirish Moodalbail     char *buf, uint_t bufsize)
18116e91bba0SGirish Moodalbail {
18126e91bba0SGirish Moodalbail 	int		i;
18136e91bba0SGirish Moodalbail 	boolean_t	first = _B_TRUE;
18146e91bba0SGirish Moodalbail 
18156e91bba0SGirish Moodalbail 	if (is_bits) {
18166e91bba0SGirish Moodalbail 		for (i = 0;  tbl[i].name; i++) {
18176e91bba0SGirish Moodalbail 			if ((flags & tbl[i].mask) == tbl[i].bits)
18186e91bba0SGirish Moodalbail 				(void) strlcat(buf, tbl[i].name, bufsize);
18196e91bba0SGirish Moodalbail 			else
18206e91bba0SGirish Moodalbail 				(void) strlcat(buf, "-", bufsize);
18216e91bba0SGirish Moodalbail 		}
18226e91bba0SGirish Moodalbail 	} else {
18236e91bba0SGirish Moodalbail 		for (i = 0; tbl[i].name; i++) {
18246e91bba0SGirish Moodalbail 			if ((flags & tbl[i].mask) == tbl[i].bits) {
18256e91bba0SGirish Moodalbail 				if (!first)
18266e91bba0SGirish Moodalbail 					(void) strlcat(buf, ",", bufsize);
18276e91bba0SGirish Moodalbail 				(void) strlcat(buf, tbl[i].name, bufsize);
18286e91bba0SGirish Moodalbail 				first = _B_FALSE;
18296e91bba0SGirish Moodalbail 			}
18306e91bba0SGirish Moodalbail 		}
18316e91bba0SGirish Moodalbail 	}
18326e91bba0SGirish Moodalbail }
18336e91bba0SGirish Moodalbail 
1834550b6e40SSowmini Varadhan /*
1835550b6e40SSowmini Varadhan  * return true if the address for lifname comes to us from the global zone
1836550b6e40SSowmini Varadhan  * with 'allowed-ips' constraints.
1837550b6e40SSowmini Varadhan  */
1838550b6e40SSowmini Varadhan static boolean_t
is_from_gz(const char * lifname)1839550b6e40SSowmini Varadhan is_from_gz(const char *lifname)
1840550b6e40SSowmini Varadhan {
1841a73be61aSHans Rosenfeld 	ipadm_if_info_t		*if_info;
1842550b6e40SSowmini Varadhan 	char			phyname[LIFNAMSIZ], *cp;
1843550b6e40SSowmini Varadhan 	boolean_t		ret = _B_FALSE;
1844550b6e40SSowmini Varadhan 	ipadm_status_t		status;
1845550b6e40SSowmini Varadhan 	zoneid_t		zoneid;
1846550b6e40SSowmini Varadhan 	ushort_t		zflags;
1847550b6e40SSowmini Varadhan 
1848550b6e40SSowmini Varadhan 	if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1849550b6e40SSowmini Varadhan 		return (_B_FALSE); /* from-gz only  makes sense in a NGZ */
1850550b6e40SSowmini Varadhan 
1851550b6e40SSowmini Varadhan 	if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1852550b6e40SSowmini Varadhan 		return (_B_FALSE);
1853550b6e40SSowmini Varadhan 
1854550b6e40SSowmini Varadhan 	if (!(zflags & ZF_NET_EXCL))
1855550b6e40SSowmini Varadhan 		return (_B_TRUE);  /* everything is from the GZ for shared-ip */
1856550b6e40SSowmini Varadhan 
1857550b6e40SSowmini Varadhan 	(void) strncpy(phyname, lifname, sizeof (phyname));
1858550b6e40SSowmini Varadhan 	if ((cp = strchr(phyname, ':')) != NULL)
1859550b6e40SSowmini Varadhan 		*cp = '\0';
1860550b6e40SSowmini Varadhan 	status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1861550b6e40SSowmini Varadhan 	if (status != IPADM_SUCCESS)
1862550b6e40SSowmini Varadhan 		return (ret);
1863550b6e40SSowmini Varadhan 
1864a73be61aSHans Rosenfeld 	if (if_info->ifi_cflags & IFIF_L3PROTECT)
1865550b6e40SSowmini Varadhan 		ret = _B_TRUE;
1866cbf54fedSJohn Levon 	ipadm_free_if_info(if_info);
1867550b6e40SSowmini Varadhan 	return (ret);
1868550b6e40SSowmini Varadhan }
1869550b6e40SSowmini Varadhan 
18706e91bba0SGirish Moodalbail static boolean_t
print_sa_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)18716e91bba0SGirish Moodalbail print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
18726e91bba0SGirish Moodalbail {
18736e91bba0SGirish Moodalbail 	show_addr_args_t	*arg = ofarg->ofmt_cbarg;
18746e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ainfo = arg->sa_info;
18756e91bba0SGirish Moodalbail 	char			interface[LIFNAMSIZ];
18766e91bba0SGirish Moodalbail 	char			addrbuf[MAXPROPVALLEN];
18776e91bba0SGirish Moodalbail 	char			dstbuf[MAXPROPVALLEN];
18786e91bba0SGirish Moodalbail 	char			prefixlenstr[MAXPROPVALLEN];
18796e91bba0SGirish Moodalbail 	int			prefixlen;
18806e91bba0SGirish Moodalbail 	struct sockaddr_in	*sin;
18816e91bba0SGirish Moodalbail 	struct sockaddr_in6	*sin6;
18826e91bba0SGirish Moodalbail 	sa_family_t		af;
18836e91bba0SGirish Moodalbail 	char			*phyname = NULL;
18846e91bba0SGirish Moodalbail 	struct ifaddrs		*ifa = &ainfo->ia_ifa;
18856e91bba0SGirish Moodalbail 	fmask_t cflags_mask[] = {
18866e91bba0SGirish Moodalbail 		{ "U",	IA_UP,			IA_UP		},
18876e91bba0SGirish Moodalbail 		{ "u",	IA_UNNUMBERED,		IA_UNNUMBERED	},
18886e91bba0SGirish Moodalbail 		{ "p",	IA_PRIVATE,		IA_PRIVATE	},
18896e91bba0SGirish Moodalbail 		{ "t",	IA_TEMPORARY,		IA_TEMPORARY	},
18906e91bba0SGirish Moodalbail 		{ "d",	IA_DEPRECATED,		IA_DEPRECATED	},
18916e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
18926e91bba0SGirish Moodalbail 	};
18936e91bba0SGirish Moodalbail 	fmask_t pflags_mask[] = {
18946e91bba0SGirish Moodalbail 		{ "U",	IA_UP,			IA_UP		},
18956e91bba0SGirish Moodalbail 		{ "p",	IA_PRIVATE,		IA_PRIVATE	},
18966e91bba0SGirish Moodalbail 		{ "d",	IA_DEPRECATED,		IA_DEPRECATED	},
18976e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
18986e91bba0SGirish Moodalbail 	};
18996e91bba0SGirish Moodalbail 	fmask_t type[] = {
19006e91bba0SGirish Moodalbail 		{ "static",	IPADM_ADDR_STATIC,	IPADM_ALL_BITS},
19016e91bba0SGirish Moodalbail 		{ "addrconf",	IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
19026e91bba0SGirish Moodalbail 		{ "dhcp",	IPADM_ADDR_DHCP,	IPADM_ALL_BITS},
19036e91bba0SGirish Moodalbail 		{ NULL,		0,			0	}
19046e91bba0SGirish Moodalbail 	};
19056e91bba0SGirish Moodalbail 	fmask_t addr_state[] = {
19066e91bba0SGirish Moodalbail 		{ "disabled",	IFA_DISABLED,	IPADM_ALL_BITS},
19076e91bba0SGirish Moodalbail 		{ "duplicate",	IFA_DUPLICATE,	IPADM_ALL_BITS},
19086e91bba0SGirish Moodalbail 		{ "down",	IFA_DOWN,	IPADM_ALL_BITS},
19096e91bba0SGirish Moodalbail 		{ "tentative",	IFA_TENTATIVE,	IPADM_ALL_BITS},
19106e91bba0SGirish Moodalbail 		{ "ok",		IFA_OK,		IPADM_ALL_BITS},
19116e91bba0SGirish Moodalbail 		{ "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
19126e91bba0SGirish Moodalbail 		{ NULL,		0,		0	}
19136e91bba0SGirish Moodalbail 	};
19146e91bba0SGirish Moodalbail 
19156e91bba0SGirish Moodalbail 	buf[0] = '\0';
19166e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
19176e91bba0SGirish Moodalbail 	case SA_ADDROBJ:
19186e91bba0SGirish Moodalbail 		if (ainfo->ia_aobjname[0] == '\0') {
19196e91bba0SGirish Moodalbail 			(void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
19206e91bba0SGirish Moodalbail 			phyname = strrchr(interface, ':');
19216e91bba0SGirish Moodalbail 			if (phyname)
19226e91bba0SGirish Moodalbail 				*phyname = '\0';
19236e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s/%s", interface,
19246e91bba0SGirish Moodalbail 			    STR_UNKNOWN_VAL);
19256e91bba0SGirish Moodalbail 		} else {
19266e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
19276e91bba0SGirish Moodalbail 		}
19286e91bba0SGirish Moodalbail 		break;
19296e91bba0SGirish Moodalbail 	case SA_STATE:
19306e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_state, addr_state, _B_FALSE,
19316e91bba0SGirish Moodalbail 		    buf, bufsize);
19326e91bba0SGirish Moodalbail 		break;
19336e91bba0SGirish Moodalbail 	case SA_TYPE:
1934550b6e40SSowmini Varadhan 		if (is_from_gz(ifa->ifa_name))
1935550b6e40SSowmini Varadhan 			(void) snprintf(buf, bufsize, "from-gz");
1936550b6e40SSowmini Varadhan 		else
1937550b6e40SSowmini Varadhan 			flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1938550b6e40SSowmini Varadhan 			    bufsize);
19396e91bba0SGirish Moodalbail 		break;
19406e91bba0SGirish Moodalbail 	case SA_CURRENT:
19416e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
19426e91bba0SGirish Moodalbail 		break;
19436e91bba0SGirish Moodalbail 	case SA_PERSISTENT:
19446e91bba0SGirish Moodalbail 		flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
19456e91bba0SGirish Moodalbail 		break;
19466e91bba0SGirish Moodalbail 	case SA_ADDR:
194764639aafSDarren Reed 		af = ifa->ifa_addr->sa_family;
19486e91bba0SGirish Moodalbail 		/*
19496e91bba0SGirish Moodalbail 		 * If the address is 0.0.0.0 or :: and the origin is DHCP,
19506e91bba0SGirish Moodalbail 		 * print STR_UNKNOWN_VAL.
19516e91bba0SGirish Moodalbail 		 */
19526e91bba0SGirish Moodalbail 		if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
19536e91bba0SGirish Moodalbail 			sin = (struct sockaddr_in *)ifa->ifa_addr;
19546e91bba0SGirish Moodalbail 			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
19556e91bba0SGirish Moodalbail 			if ((af == AF_INET &&
19566e91bba0SGirish Moodalbail 			    sin->sin_addr.s_addr == INADDR_ANY) ||
19576e91bba0SGirish Moodalbail 			    (af == AF_INET6 &&
19586e91bba0SGirish Moodalbail 			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
19596e91bba0SGirish Moodalbail 				(void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
19606e91bba0SGirish Moodalbail 				break;
19616e91bba0SGirish Moodalbail 			}
19626e91bba0SGirish Moodalbail 		}
19636e91bba0SGirish Moodalbail 		if (ifa->ifa_netmask == NULL)
19646e91bba0SGirish Moodalbail 			prefixlen = 0;
19656e91bba0SGirish Moodalbail 		else
19666e91bba0SGirish Moodalbail 			prefixlen = mask2plen(ifa->ifa_netmask);
19676e91bba0SGirish Moodalbail 		bzero(prefixlenstr, sizeof (prefixlenstr));
19686e91bba0SGirish Moodalbail 		if (prefixlen > 0) {
19696e91bba0SGirish Moodalbail 			(void) snprintf(prefixlenstr, sizeof (prefixlenstr),
19706e91bba0SGirish Moodalbail 			    "/%d", prefixlen);
19716e91bba0SGirish Moodalbail 		}
19726e91bba0SGirish Moodalbail 		bzero(addrbuf, sizeof (addrbuf));
19736e91bba0SGirish Moodalbail 		bzero(dstbuf, sizeof (dstbuf));
19746e91bba0SGirish Moodalbail 		if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
19756e91bba0SGirish Moodalbail 			/*
19766e91bba0SGirish Moodalbail 			 * Print the hostname fields if the address is not
19776e91bba0SGirish Moodalbail 			 * in active configuration.
19786e91bba0SGirish Moodalbail 			 */
19796e91bba0SGirish Moodalbail 			if (ainfo->ia_state == IFA_DISABLED) {
19806e91bba0SGirish Moodalbail 				(void) snprintf(buf, bufsize, "%s",
19816e91bba0SGirish Moodalbail 				    ainfo->ia_sname);
19826e91bba0SGirish Moodalbail 				if (ainfo->ia_dname[0] != '\0') {
19836e91bba0SGirish Moodalbail 					(void) snprintf(dstbuf, sizeof (dstbuf),
19846e91bba0SGirish Moodalbail 					    "->%s", ainfo->ia_dname);
19856e91bba0SGirish Moodalbail 					(void) strlcat(buf, dstbuf, bufsize);
19866e91bba0SGirish Moodalbail 				} else {
19876e91bba0SGirish Moodalbail 					(void) strlcat(buf, prefixlenstr,
19886e91bba0SGirish Moodalbail 					    bufsize);
19896e91bba0SGirish Moodalbail 				}
19906e91bba0SGirish Moodalbail 				break;
19916e91bba0SGirish Moodalbail 			}
19926e91bba0SGirish Moodalbail 		}
199308ed54f3SVasumathi Sundaram 		/*
199408ed54f3SVasumathi Sundaram 		 * For the non-persistent case, we need to show the
199508ed54f3SVasumathi Sundaram 		 * currently configured addresses for source and
199608ed54f3SVasumathi Sundaram 		 * destination.
199708ed54f3SVasumathi Sundaram 		 */
19986e91bba0SGirish Moodalbail 		sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
19996e91bba0SGirish Moodalbail 		    addrbuf, sizeof (addrbuf));
200008ed54f3SVasumathi Sundaram 		if (ifa->ifa_flags & IFF_POINTOPOINT) {
200108ed54f3SVasumathi Sundaram 			sockaddr2str(
200208ed54f3SVasumathi Sundaram 			    (struct sockaddr_storage *)ifa->ifa_dstaddr,
200308ed54f3SVasumathi Sundaram 			    dstbuf, sizeof (dstbuf));
20046e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s->%s", addrbuf,
20056e91bba0SGirish Moodalbail 			    dstbuf);
20066e91bba0SGirish Moodalbail 		} else {
20076e91bba0SGirish Moodalbail 			(void) snprintf(buf, bufsize, "%s%s", addrbuf,
20086e91bba0SGirish Moodalbail 			    prefixlenstr);
20096e91bba0SGirish Moodalbail 		}
20106e91bba0SGirish Moodalbail 		break;
20116e91bba0SGirish Moodalbail 	default:
20126e91bba0SGirish Moodalbail 		die("invalid input");
20136e91bba0SGirish Moodalbail 		break;
20146e91bba0SGirish Moodalbail 	}
20156e91bba0SGirish Moodalbail 
20166e91bba0SGirish Moodalbail 	return (_B_TRUE);
20176e91bba0SGirish Moodalbail }
20186e91bba0SGirish Moodalbail 
20196e91bba0SGirish Moodalbail /*
20206e91bba0SGirish Moodalbail  * Display address information, either for the given address or
20216e91bba0SGirish Moodalbail  * for all the addresses managed by ipadm.
20226e91bba0SGirish Moodalbail  */
20236e91bba0SGirish Moodalbail static void
do_show_addr(int argc,char * argv[],const char * use)20246e91bba0SGirish Moodalbail do_show_addr(int argc, char *argv[], const char *use)
20256e91bba0SGirish Moodalbail {
20266e91bba0SGirish Moodalbail 	ipadm_status_t		status;
20276e91bba0SGirish Moodalbail 	show_addr_state_t	state;
20286e91bba0SGirish Moodalbail 	char			*def_fields_str = "addrobj,type,state,addr";
20296e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
20306e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ainfo;
20316e91bba0SGirish Moodalbail 	ipadm_addr_info_t	*ptr;
20326e91bba0SGirish Moodalbail 	show_addr_args_t	sargs;
20336e91bba0SGirish Moodalbail 	int			option;
20346e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
20356e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
20366e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
20376e91bba0SGirish Moodalbail 	char			*aname;
20386e91bba0SGirish Moodalbail 	char			*ifname = NULL;
20396e91bba0SGirish Moodalbail 	char			*cp;
20406e91bba0SGirish Moodalbail 	boolean_t		found = _B_FALSE;
20416e91bba0SGirish Moodalbail 
20426e91bba0SGirish Moodalbail 	opterr = 0;
20436e91bba0SGirish Moodalbail 	state.sa_parsable = _B_FALSE;
20446e91bba0SGirish Moodalbail 	state.sa_persist = _B_FALSE;
20456e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
20466e91bba0SGirish Moodalbail 	    NULL)) != -1) {
20476e91bba0SGirish Moodalbail 		switch (option) {
20486e91bba0SGirish Moodalbail 		case 'p':
20496e91bba0SGirish Moodalbail 			state.sa_parsable = _B_TRUE;
20506e91bba0SGirish Moodalbail 			break;
20516e91bba0SGirish Moodalbail 		case 'o':
20526e91bba0SGirish Moodalbail 			fields_str = optarg;
20536e91bba0SGirish Moodalbail 			break;
20546e91bba0SGirish Moodalbail 		default:
20556e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
20566e91bba0SGirish Moodalbail 			break;
20576e91bba0SGirish Moodalbail 		}
20586e91bba0SGirish Moodalbail 	}
20596e91bba0SGirish Moodalbail 	if (state.sa_parsable && fields_str == NULL)
20606e91bba0SGirish Moodalbail 		die("-p requires -o");
20616e91bba0SGirish Moodalbail 
20626e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
20636e91bba0SGirish Moodalbail 		aname = argv[optind];
20646e91bba0SGirish Moodalbail 		if ((cp = strchr(aname, '/')) == NULL)
20656e91bba0SGirish Moodalbail 			die("Invalid address object name provided");
20666e91bba0SGirish Moodalbail 		if (*(cp + 1) == '\0') {
20676e91bba0SGirish Moodalbail 			ifname = aname;
20686e91bba0SGirish Moodalbail 			*cp = '\0';
20696e91bba0SGirish Moodalbail 			aname = NULL;
20706e91bba0SGirish Moodalbail 		}
20716e91bba0SGirish Moodalbail 	} else if (optind == argc) {
20726e91bba0SGirish Moodalbail 		aname = NULL;
20736e91bba0SGirish Moodalbail 	} else {
20746e91bba0SGirish Moodalbail 		die("Usage: %s", use);
20756e91bba0SGirish Moodalbail 	}
20766e91bba0SGirish Moodalbail 
20776e91bba0SGirish Moodalbail 	if (state.sa_parsable)
20786e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
20796e91bba0SGirish Moodalbail 	if (fields_str == NULL)
20806e91bba0SGirish Moodalbail 		fields_str = def_fields_str;
20816e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
20826e91bba0SGirish Moodalbail 
2083b2f26520SBryan Cantrill 	ofmt_check(oferr, state.sa_parsable, ofmt, die, warn);
20846e91bba0SGirish Moodalbail 	state.sa_ofmt = ofmt;
20856e91bba0SGirish Moodalbail 
20866e91bba0SGirish Moodalbail 	status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
20876e91bba0SGirish Moodalbail 	/*
20886e91bba0SGirish Moodalbail 	 * Return without printing any error, if no addresses were found,
20896e91bba0SGirish Moodalbail 	 * for the case where all addresses are requested.
20906e91bba0SGirish Moodalbail 	 */
20916e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
20926e91bba0SGirish Moodalbail 		die("Could not get address: %s", ipadm_status2str(status));
20936e91bba0SGirish Moodalbail 	if (ainfo == NULL) {
20946e91bba0SGirish Moodalbail 		ofmt_close(ofmt);
20956e91bba0SGirish Moodalbail 		return;
20966e91bba0SGirish Moodalbail 	}
20976e91bba0SGirish Moodalbail 
20986e91bba0SGirish Moodalbail 	bzero(&sargs, sizeof (sargs));
20996e91bba0SGirish Moodalbail 	sargs.sa_state = &state;
21006e91bba0SGirish Moodalbail 	for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
21016e91bba0SGirish Moodalbail 		sargs.sa_info = ptr;
21026e91bba0SGirish Moodalbail 		if (aname != NULL) {
21036e91bba0SGirish Moodalbail 			if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
21046e91bba0SGirish Moodalbail 				continue;
21056e91bba0SGirish Moodalbail 			found = _B_TRUE;
21066e91bba0SGirish Moodalbail 		}
21076e91bba0SGirish Moodalbail 		ofmt_print(state.sa_ofmt, &sargs);
21086e91bba0SGirish Moodalbail 	}
21096e91bba0SGirish Moodalbail 	if (ainfo)
21106e91bba0SGirish Moodalbail 		ipadm_free_addr_info(ainfo);
21116e91bba0SGirish Moodalbail 	if (aname != NULL && !found)
21126e91bba0SGirish Moodalbail 		die("Address object not found");
21136e91bba0SGirish Moodalbail }
21146e91bba0SGirish Moodalbail 
21156e91bba0SGirish Moodalbail static boolean_t
print_si_cb(ofmt_arg_t * ofarg,char * buf,uint_t bufsize)21166e91bba0SGirish Moodalbail print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
21176e91bba0SGirish Moodalbail {
21186e91bba0SGirish Moodalbail 	show_if_args_t		*arg = ofarg->ofmt_cbarg;
2119a73be61aSHans Rosenfeld 	ipadm_if_info_t		*ifinfo = arg->si_info;
2120a73be61aSHans Rosenfeld 	char			*ifname = ifinfo->ifi_name;
21216e91bba0SGirish Moodalbail 	fmask_t intf_state[] = {
21226e91bba0SGirish Moodalbail 		{ "ok",		IFIS_OK,	IPADM_ALL_BITS},
21236e91bba0SGirish Moodalbail 		{ "down",	IFIS_DOWN,	IPADM_ALL_BITS},
21246e91bba0SGirish Moodalbail 		{ "disabled",	IFIS_DISABLED,	IPADM_ALL_BITS},
21256e91bba0SGirish Moodalbail 		{ "failed",	IFIS_FAILED,	IPADM_ALL_BITS},
21266e91bba0SGirish Moodalbail 		{ "offline",	IFIS_OFFLINE,	IPADM_ALL_BITS},
21276e91bba0SGirish Moodalbail 		{ NULL,		0,		0	}
21286e91bba0SGirish Moodalbail 	};
21296e91bba0SGirish Moodalbail 	fmask_t intf_pflags[] = {
21306e91bba0SGirish Moodalbail 		{ "s",	IFIF_STANDBY,		IFIF_STANDBY	},
21316e91bba0SGirish Moodalbail 		{ "4",	IFIF_IPV4,		IFIF_IPV4	},
21326e91bba0SGirish Moodalbail 		{ "6",	IFIF_IPV6,		IFIF_IPV6	},
21336e91bba0SGirish Moodalbail 		{ NULL,	0,			0		}
21346e91bba0SGirish Moodalbail 	};
21356e91bba0SGirish Moodalbail 	fmask_t intf_cflags[] = {
21366e91bba0SGirish Moodalbail 		{ "b",	IFIF_BROADCAST,		IFIF_BROADCAST	},
21376e91bba0SGirish Moodalbail 		{ "m",	IFIF_MULTICAST,		IFIF_MULTICAST	},
21386e91bba0SGirish Moodalbail 		{ "p",	IFIF_POINTOPOINT,	IFIF_POINTOPOINT},
21396e91bba0SGirish Moodalbail 		{ "v",	IFIF_VIRTUAL,		IFIF_VIRTUAL	},
21406e91bba0SGirish Moodalbail 		{ "I",	IFIF_IPMP,		IFIF_IPMP	},
21416e91bba0SGirish Moodalbail 		{ "s",	IFIF_STANDBY,		IFIF_STANDBY	},
21426e91bba0SGirish Moodalbail 		{ "i",	IFIF_INACTIVE,		IFIF_INACTIVE	},
21436e91bba0SGirish Moodalbail 		{ "V",	IFIF_VRRP,		IFIF_VRRP	},
21446e91bba0SGirish Moodalbail 		{ "a",	IFIF_NOACCEPT,		IFIF_NOACCEPT	},
2145550b6e40SSowmini Varadhan 		{ "Z",	IFIF_L3PROTECT,		IFIF_L3PROTECT	},
21466e91bba0SGirish Moodalbail 		{ "4",	IFIF_IPV4,		IFIF_IPV4	},
21476e91bba0SGirish Moodalbail 		{ "6",	IFIF_IPV6,		IFIF_IPV6	},
21486e91bba0SGirish Moodalbail 		{ NULL,	0,			0		}
21496e91bba0SGirish Moodalbail 	};
2150a73be61aSHans Rosenfeld 	fmask_t intf_class[] = {
2151a73be61aSHans Rosenfeld 		{ "IP",		IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS},
2152a73be61aSHans Rosenfeld 		{ "IPMP",	IPADM_IF_CLASS_IPMP,    IPADM_ALL_BITS},
2153a73be61aSHans Rosenfeld 		{ "VIRTUAL",	IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS},
2154a73be61aSHans Rosenfeld 		{ "UNKNOWN",	IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS},
2155a73be61aSHans Rosenfeld 		{ NULL,	0,	0}
2156a73be61aSHans Rosenfeld 	};
21576e91bba0SGirish Moodalbail 
21586e91bba0SGirish Moodalbail 	buf[0] = '\0';
21596e91bba0SGirish Moodalbail 	switch (ofarg->ofmt_id) {
21606e91bba0SGirish Moodalbail 	case SI_IFNAME:
21616e91bba0SGirish Moodalbail 		(void) snprintf(buf, bufsize, "%s", ifname);
21626e91bba0SGirish Moodalbail 		break;
2163a73be61aSHans Rosenfeld 	case SI_IFCLASS:
2164a73be61aSHans Rosenfeld 		flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
2165a73be61aSHans Rosenfeld 		    buf, bufsize);
2166a73be61aSHans Rosenfeld 		break;
21676e91bba0SGirish Moodalbail 	case SI_STATE:
2168a73be61aSHans Rosenfeld 		flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
21696e91bba0SGirish Moodalbail 		    buf, bufsize);
21706e91bba0SGirish Moodalbail 		break;
21716e91bba0SGirish Moodalbail 	case SI_CURRENT:
2172a73be61aSHans Rosenfeld 		flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
21736e91bba0SGirish Moodalbail 		    buf, bufsize);
21746e91bba0SGirish Moodalbail 		break;
21756e91bba0SGirish Moodalbail 	case SI_PERSISTENT:
2176a73be61aSHans Rosenfeld 		flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
21776e91bba0SGirish Moodalbail 		    buf, bufsize);
21786e91bba0SGirish Moodalbail 		break;
21796e91bba0SGirish Moodalbail 	default:
21806e91bba0SGirish Moodalbail 		die("invalid input");
21816e91bba0SGirish Moodalbail 		break;
21826e91bba0SGirish Moodalbail 	}
21836e91bba0SGirish Moodalbail 
21846e91bba0SGirish Moodalbail 	return (_B_TRUE);
21856e91bba0SGirish Moodalbail }
21866e91bba0SGirish Moodalbail 
21876e91bba0SGirish Moodalbail /*
21886e91bba0SGirish Moodalbail  * Display interface information, either for the given interface or
21896e91bba0SGirish Moodalbail  * for all the interfaces in the system.
21906e91bba0SGirish Moodalbail  */
21916e91bba0SGirish Moodalbail static void
do_show_if(int argc,char * argv[],const char * use)21926e91bba0SGirish Moodalbail do_show_if(int argc, char *argv[], const char *use)
21936e91bba0SGirish Moodalbail {
21946e91bba0SGirish Moodalbail 	ipadm_status_t		status;
21956e91bba0SGirish Moodalbail 	show_if_state_t		state;
21966e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
2197a73be61aSHans Rosenfeld 	ipadm_if_info_t		*if_info, *ptr;
21986e91bba0SGirish Moodalbail 	show_if_args_t		sargs;
21996e91bba0SGirish Moodalbail 	int			option;
22006e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
22016e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
22026e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
22036e91bba0SGirish Moodalbail 	char			*ifname = NULL;
22046e91bba0SGirish Moodalbail 
22056e91bba0SGirish Moodalbail 	opterr = 0;
22066e91bba0SGirish Moodalbail 	state.si_parsable = _B_FALSE;
22076e91bba0SGirish Moodalbail 
22086e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
22096e91bba0SGirish Moodalbail 	    NULL)) != -1) {
22106e91bba0SGirish Moodalbail 		switch (option) {
22116e91bba0SGirish Moodalbail 		case 'p':
22126e91bba0SGirish Moodalbail 			state.si_parsable = _B_TRUE;
22136e91bba0SGirish Moodalbail 			break;
22146e91bba0SGirish Moodalbail 		case 'o':
22156e91bba0SGirish Moodalbail 			fields_str = optarg;
22166e91bba0SGirish Moodalbail 			break;
22176e91bba0SGirish Moodalbail 		default:
22186e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
22196e91bba0SGirish Moodalbail 			break;
22206e91bba0SGirish Moodalbail 		}
22216e91bba0SGirish Moodalbail 	}
22226e91bba0SGirish Moodalbail 	if (optind == argc - 1)
22236e91bba0SGirish Moodalbail 		ifname = argv[optind];
22246e91bba0SGirish Moodalbail 	else if (optind != argc)
22256e91bba0SGirish Moodalbail 		die("Usage: %s", use);
22266e91bba0SGirish Moodalbail 	if (state.si_parsable)
22276e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
22286e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
2229b2f26520SBryan Cantrill 	ofmt_check(oferr, state.si_parsable, ofmt, die, warn);
22306e91bba0SGirish Moodalbail 	state.si_ofmt = ofmt;
22316e91bba0SGirish Moodalbail 	bzero(&sargs, sizeof (sargs));
22326e91bba0SGirish Moodalbail 	sargs.si_state = &state;
22336e91bba0SGirish Moodalbail 	status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
22346e91bba0SGirish Moodalbail 	/*
22356e91bba0SGirish Moodalbail 	 * Return without printing any error, if no addresses were found.
22366e91bba0SGirish Moodalbail 	 */
22376e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
22386e91bba0SGirish Moodalbail 		die("Could not get interface(s): %s",
22396e91bba0SGirish Moodalbail 		    ipadm_status2str(status));
22406e91bba0SGirish Moodalbail 	}
22416e91bba0SGirish Moodalbail 
2242a73be61aSHans Rosenfeld 	for (ptr = if_info; ptr != NULL; ptr = ptr->ifi_next) {
22436e91bba0SGirish Moodalbail 		sargs.si_info = ptr;
22446e91bba0SGirish Moodalbail 		ofmt_print(state.si_ofmt, &sargs);
22456e91bba0SGirish Moodalbail 	}
22466e91bba0SGirish Moodalbail 	if (if_info)
22476e91bba0SGirish Moodalbail 		ipadm_free_if_info(if_info);
22486e91bba0SGirish Moodalbail }
22496e91bba0SGirish Moodalbail 
22506e91bba0SGirish Moodalbail /*
22516e91bba0SGirish Moodalbail  * set/reset the address property for a given address
22526e91bba0SGirish Moodalbail  */
22536e91bba0SGirish Moodalbail static void
set_addrprop(int argc,char ** argv,boolean_t reset,const char * use)22546e91bba0SGirish Moodalbail set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
22556e91bba0SGirish Moodalbail {
2256467e811cSToomas Soome 	int			option;
2257467e811cSToomas Soome 	ipadm_status_t		status = IPADM_SUCCESS;
2258467e811cSToomas Soome 	boolean_t		p_arg = _B_FALSE;
2259467e811cSToomas Soome 	char			*nv, *aobjname;
22606e91bba0SGirish Moodalbail 	char			*prop_name, *prop_val;
22616e91bba0SGirish Moodalbail 	uint_t			flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
22626e91bba0SGirish Moodalbail 
2263467e811cSToomas Soome 	nv = NULL;
22646e91bba0SGirish Moodalbail 	opterr = 0;
22656e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
22666e91bba0SGirish Moodalbail 	    NULL)) != -1) {
22676e91bba0SGirish Moodalbail 		switch (option) {
22686e91bba0SGirish Moodalbail 		case 'p':
22696e91bba0SGirish Moodalbail 			if (p_arg)
22706e91bba0SGirish Moodalbail 				die("-p must be specified once only");
22716e91bba0SGirish Moodalbail 			p_arg = _B_TRUE;
22726e91bba0SGirish Moodalbail 
22736e91bba0SGirish Moodalbail 			ipadm_check_propstr(optarg, reset, use);
22746e91bba0SGirish Moodalbail 			nv = optarg;
22756e91bba0SGirish Moodalbail 			break;
22766e91bba0SGirish Moodalbail 		case 't':
22776e91bba0SGirish Moodalbail 			flags &= ~IPADM_OPT_PERSIST;
22786e91bba0SGirish Moodalbail 			break;
22796e91bba0SGirish Moodalbail 		default:
22806e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
22816e91bba0SGirish Moodalbail 		}
22826e91bba0SGirish Moodalbail 	}
22836e91bba0SGirish Moodalbail 
22846e91bba0SGirish Moodalbail 	if (!p_arg || optind != (argc - 1))
22856e91bba0SGirish Moodalbail 		die("Usage: %s", use);
22866e91bba0SGirish Moodalbail 
22876e91bba0SGirish Moodalbail 	prop_name = nv;
22886e91bba0SGirish Moodalbail 	prop_val = strchr(nv, '=');
22896e91bba0SGirish Moodalbail 	if (prop_val != NULL)
22906e91bba0SGirish Moodalbail 		*prop_val++ = '\0';
22916e91bba0SGirish Moodalbail 	aobjname = argv[optind];
22926e91bba0SGirish Moodalbail 	if (reset)
22936e91bba0SGirish Moodalbail 		flags |= IPADM_OPT_DEFAULT;
22946e91bba0SGirish Moodalbail 	status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
22956e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS) {
22966e91bba0SGirish Moodalbail 		if (reset)
22976e91bba0SGirish Moodalbail 			die("reset-addrprop: %s: %s", prop_name,
22986e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
22996e91bba0SGirish Moodalbail 		else
23006e91bba0SGirish Moodalbail 			die("set-addrprop: %s: %s", prop_name,
23016e91bba0SGirish Moodalbail 			    ipadm_status2str(status));
23026e91bba0SGirish Moodalbail 	}
23036e91bba0SGirish Moodalbail }
23046e91bba0SGirish Moodalbail 
23056e91bba0SGirish Moodalbail /*
23066e91bba0SGirish Moodalbail  * Sets a property on an address object.
23076e91bba0SGirish Moodalbail  */
23086e91bba0SGirish Moodalbail static void
do_set_addrprop(int argc,char ** argv,const char * use)23096e91bba0SGirish Moodalbail do_set_addrprop(int argc, char **argv, const char *use)
23106e91bba0SGirish Moodalbail {
23116e91bba0SGirish Moodalbail 	set_addrprop(argc, argv, _B_FALSE, use);
23126e91bba0SGirish Moodalbail }
23136e91bba0SGirish Moodalbail 
23146e91bba0SGirish Moodalbail /*
23156e91bba0SGirish Moodalbail  * Resets a property to its default value on an address object.
23166e91bba0SGirish Moodalbail  */
23176e91bba0SGirish Moodalbail static void
do_reset_addrprop(int argc,char ** argv,const char * use)23186e91bba0SGirish Moodalbail do_reset_addrprop(int argc, char **argv, const char *use)
23196e91bba0SGirish Moodalbail {
23206e91bba0SGirish Moodalbail 	set_addrprop(argc, argv,  _B_TRUE, use);
23216e91bba0SGirish Moodalbail }
23226e91bba0SGirish Moodalbail 
23236e91bba0SGirish Moodalbail /*
23246e91bba0SGirish Moodalbail  * Display information for all or specific address properties, either for a
23256e91bba0SGirish Moodalbail  * given address or for all the addresses in the system.
23266e91bba0SGirish Moodalbail  */
23276e91bba0SGirish Moodalbail static void
do_show_addrprop(int argc,char * argv[],const char * use)23286e91bba0SGirish Moodalbail do_show_addrprop(int argc, char *argv[], const char *use)
23296e91bba0SGirish Moodalbail {
2330467e811cSToomas Soome 	int			option;
2331467e811cSToomas Soome 	nvlist_t		*proplist = NULL;
23326e91bba0SGirish Moodalbail 	char			*fields_str = NULL;
2333467e811cSToomas Soome 	show_prop_state_t	state;
23346e91bba0SGirish Moodalbail 	ofmt_handle_t		ofmt;
23356e91bba0SGirish Moodalbail 	ofmt_status_t		oferr;
23366e91bba0SGirish Moodalbail 	uint_t			ofmtflags = 0;
23378c8556f9SYuri Pankov 	char			*aobjname = NULL;
23386e91bba0SGirish Moodalbail 	char			*ifname = NULL;
23396e91bba0SGirish Moodalbail 	char			*cp;
23408c8556f9SYuri Pankov 	ipadm_addr_info_t	*ainfop = NULL;
23418c8556f9SYuri Pankov 	ipadm_addr_info_t	*ptr;
23428c8556f9SYuri Pankov 	ipadm_status_t		status;
23438c8556f9SYuri Pankov 	boolean_t		found = _B_FALSE;
23446e91bba0SGirish Moodalbail 
23456e91bba0SGirish Moodalbail 	opterr = 0;
23466e91bba0SGirish Moodalbail 	bzero(&state, sizeof (state));
23476e91bba0SGirish Moodalbail 	state.sps_propval = NULL;
23486e91bba0SGirish Moodalbail 	state.sps_parsable = _B_FALSE;
23496e91bba0SGirish Moodalbail 	state.sps_addrprop = _B_TRUE;
23506e91bba0SGirish Moodalbail 	state.sps_proto = MOD_PROTO_NONE;
23516e91bba0SGirish Moodalbail 	state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
23526e91bba0SGirish Moodalbail 	while ((option = getopt_long(argc, argv, ":p:i:cPo:",
23536e91bba0SGirish Moodalbail 	    show_prop_longopts, NULL)) != -1) {
23546e91bba0SGirish Moodalbail 		switch (option) {
23556e91bba0SGirish Moodalbail 		case 'p':
23566e91bba0SGirish Moodalbail 			if (ipadm_str2nvlist(optarg, &proplist,
23576e91bba0SGirish Moodalbail 			    IPADM_NORVAL) != 0)
23588c8556f9SYuri Pankov 				die("invalid addrobj properties specified");
23596e91bba0SGirish Moodalbail 			break;
23606e91bba0SGirish Moodalbail 		case 'c':
23616e91bba0SGirish Moodalbail 			state.sps_parsable = _B_TRUE;
23626e91bba0SGirish Moodalbail 			break;
23636e91bba0SGirish Moodalbail 		case 'o':
23646e91bba0SGirish Moodalbail 			fields_str = optarg;
23656e91bba0SGirish Moodalbail 			break;
23666e91bba0SGirish Moodalbail 		default:
23676e91bba0SGirish Moodalbail 			die_opterr(optopt, option, use);
23686e91bba0SGirish Moodalbail 			break;
23696e91bba0SGirish Moodalbail 		}
23706e91bba0SGirish Moodalbail 	}
23716e91bba0SGirish Moodalbail 	if (optind == argc - 1) {
23726e91bba0SGirish Moodalbail 		aobjname = argv[optind];
23736e91bba0SGirish Moodalbail 		cp = strchr(aobjname, '/');
23746e91bba0SGirish Moodalbail 		if (cp == NULL)
23758c8556f9SYuri Pankov 			die("invalid addrobj name provided");
23766e91bba0SGirish Moodalbail 		if (*(cp + 1) == '\0') {
23776e91bba0SGirish Moodalbail 			ifname = aobjname;
23786e91bba0SGirish Moodalbail 			*cp = '\0';
23796e91bba0SGirish Moodalbail 			aobjname = NULL;
23806e91bba0SGirish Moodalbail 		}
23818c8556f9SYuri Pankov 	} else if (optind != argc) {
23826e91bba0SGirish Moodalbail 		die("Usage: %s", use);
23836e91bba0SGirish Moodalbail 	}
23846e91bba0SGirish Moodalbail 	state.sps_proplist = proplist;
23856e91bba0SGirish Moodalbail 	if (state.sps_parsable)
23866e91bba0SGirish Moodalbail 		ofmtflags |= OFMT_PARSABLE;
23876e91bba0SGirish Moodalbail 	oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
2388b2f26520SBryan Cantrill 	ofmt_check(oferr, state.sps_parsable, ofmt, die, warn);
23896e91bba0SGirish Moodalbail 	state.sps_ofmt = ofmt;
23906e91bba0SGirish Moodalbail 
23918c8556f9SYuri Pankov 	status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
23928c8556f9SYuri Pankov 	/* Return without printing any error, if no addresses were found */
23938c8556f9SYuri Pankov 	if (status == IPADM_NOTFOUND)
23948c8556f9SYuri Pankov 		return;
23958c8556f9SYuri Pankov 	if (status != IPADM_SUCCESS)
23968c8556f9SYuri Pankov 		die("error retrieving address: %s", ipadm_status2str(status));
23976e91bba0SGirish Moodalbail 
23988c8556f9SYuri Pankov 	for (ptr = ainfop; ptr != NULL; ptr = IA_NEXT(ptr)) {
23998c8556f9SYuri Pankov 		char	*taobjname = ptr->ia_aobjname;
24008c8556f9SYuri Pankov 
24018c8556f9SYuri Pankov 		if (taobjname[0] == '\0')
24028c8556f9SYuri Pankov 			continue;
24038c8556f9SYuri Pankov 		if (aobjname != NULL) {
24048c8556f9SYuri Pankov 			if (strcmp(aobjname, taobjname) == 0)
24058c8556f9SYuri Pankov 				found = _B_TRUE;
24068c8556f9SYuri Pankov 			else
24078c8556f9SYuri Pankov 				continue;
24086e91bba0SGirish Moodalbail 		}
24098c8556f9SYuri Pankov 		if (ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
24108c8556f9SYuri Pankov 			if (found)
24118c8556f9SYuri Pankov 				break;
24128c8556f9SYuri Pankov 			else
24136e91bba0SGirish Moodalbail 				continue;
24146e91bba0SGirish Moodalbail 		}
24158c8556f9SYuri Pankov 		(void) strlcpy(state.sps_aobjname, taobjname,
24168c8556f9SYuri Pankov 		    sizeof (state.sps_aobjname));
24178c8556f9SYuri Pankov 		show_properties(&state, IPADMPROP_CLASS_ADDR);
24188c8556f9SYuri Pankov 		if (found)
24198c8556f9SYuri Pankov 			break;
24206e91bba0SGirish Moodalbail 	}
24218c8556f9SYuri Pankov 	ipadm_free_addr_info(ainfop);
24228c8556f9SYuri Pankov 
24238c8556f9SYuri Pankov 	if (aobjname != NULL && !found)
24248c8556f9SYuri Pankov 		die("addrobj not found: %s", aobjname);
24258c8556f9SYuri Pankov 
24266e91bba0SGirish Moodalbail 	nvlist_free(proplist);
24276e91bba0SGirish Moodalbail 	ofmt_close(ofmt);
24286e91bba0SGirish Moodalbail 	if (state.sps_retstatus != IPADM_SUCCESS) {
24296e91bba0SGirish Moodalbail 		ipadm_close(iph);
24306e91bba0SGirish Moodalbail 		exit(EXIT_FAILURE);
24316e91bba0SGirish Moodalbail 	}
24326e91bba0SGirish Moodalbail }
24336e91bba0SGirish Moodalbail 
24346e91bba0SGirish Moodalbail /*
24356e91bba0SGirish Moodalbail  * check if the `pstr' adheres to following syntax
24366e91bba0SGirish Moodalbail  *	- prop=<value[,...]>	(for set)
24376e91bba0SGirish Moodalbail  *	- prop			(for reset)
24386e91bba0SGirish Moodalbail  */
24396e91bba0SGirish Moodalbail static void
ipadm_check_propstr(const char * pstr,boolean_t reset,const char * use)24406e91bba0SGirish Moodalbail ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
24416e91bba0SGirish Moodalbail {
24426e91bba0SGirish Moodalbail 	char	*nv;
24436e91bba0SGirish Moodalbail 
24446e91bba0SGirish Moodalbail 	nv = strchr(pstr, '=');
24456e91bba0SGirish Moodalbail 	if (reset) {
24466e91bba0SGirish Moodalbail 		if (nv != NULL)
24476e91bba0SGirish Moodalbail 			die("incorrect syntax used for -p.\n%s", use);
24486e91bba0SGirish Moodalbail 	} else {
24496e91bba0SGirish Moodalbail 		if (nv == NULL || *++nv == '\0')
24506e91bba0SGirish Moodalbail 			die("please specify the value to be set.\n%s", use);
24516e91bba0SGirish Moodalbail 		nv = strchr(nv, '=');
24526e91bba0SGirish Moodalbail 		/* cannot have multiple 'prop=val' for single -p */
24536e91bba0SGirish Moodalbail 		if (nv != NULL)
24546e91bba0SGirish Moodalbail 			die("cannot specify more than one prop=val at "
24556e91bba0SGirish Moodalbail 			    "a time.\n%s", use);
24566e91bba0SGirish Moodalbail 	}
24576e91bba0SGirish Moodalbail }
2458