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  */
21*a73be61aSHans Rosenfeld 
226e91bba0SGirish Moodalbail /*
238b88711aSGirish Moodalbail  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2445a4b79dSSebastien Roy  * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
25*a73be61aSHans Rosenfeld  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
266e91bba0SGirish Moodalbail  */
276e91bba0SGirish Moodalbail 
286e91bba0SGirish Moodalbail /*
296e91bba0SGirish Moodalbail  * This file contains routines that are used to modify/retrieve protocol or
306e91bba0SGirish Moodalbail  * interface property values. It also holds all the supported properties for
316e91bba0SGirish Moodalbail  * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
326e91bba0SGirish Moodalbail  * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
336e91bba0SGirish Moodalbail  *
346e91bba0SGirish Moodalbail  * This file also contains walkers, which walks through the property table and
356e91bba0SGirish Moodalbail  * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
366e91bba0SGirish Moodalbail  * property in the table.
376e91bba0SGirish Moodalbail  */
386e91bba0SGirish Moodalbail 
396e91bba0SGirish Moodalbail #include <unistd.h>
406e91bba0SGirish Moodalbail #include <errno.h>
416e91bba0SGirish Moodalbail #include <ctype.h>
426e91bba0SGirish Moodalbail #include <fcntl.h>
436e91bba0SGirish Moodalbail #include <strings.h>
446e91bba0SGirish Moodalbail #include <stdlib.h>
456e91bba0SGirish Moodalbail #include <netinet/in.h>
466e91bba0SGirish Moodalbail #include <arpa/inet.h>
476e91bba0SGirish Moodalbail #include <sys/sockio.h>
486e91bba0SGirish Moodalbail #include <assert.h>
496e91bba0SGirish Moodalbail #include <libdllink.h>
506e91bba0SGirish Moodalbail #include <zone.h>
516e91bba0SGirish Moodalbail #include "libipadm_impl.h"
52f1e9465bSSowmini Varadhan #include <inet/tunables.h>
536e91bba0SGirish Moodalbail 
548887b57dSGirish Moodalbail #define	IPADM_NONESTR		"none"
558887b57dSGirish Moodalbail #define	DEF_METRIC_VAL		0	/* default metric value */
566e91bba0SGirish Moodalbail 
576e91bba0SGirish Moodalbail #define	A_CNT(arr)	(sizeof (arr) / sizeof (arr[0]))
586e91bba0SGirish Moodalbail 
598887b57dSGirish Moodalbail static ipadm_status_t	i_ipadm_validate_if(ipadm_handle_t, const char *,
608887b57dSGirish Moodalbail 			    uint_t, uint_t);
616e91bba0SGirish Moodalbail 
626e91bba0SGirish Moodalbail /*
636e91bba0SGirish Moodalbail  * Callback functions to retrieve property values from the kernel. These
646e91bba0SGirish Moodalbail  * functions, when required, translate the values from the kernel to a format
656e91bba0SGirish Moodalbail  * suitable for printing. For example: boolean values will be translated
666e91bba0SGirish Moodalbail  * to on/off. They also retrieve DEFAULT, PERM and POSSIBLE values for
676e91bba0SGirish Moodalbail  * a given property.
686e91bba0SGirish Moodalbail  */
696e91bba0SGirish Moodalbail static ipadm_pd_getf_t	i_ipadm_get_prop, i_ipadm_get_ifprop_flags,
706e91bba0SGirish Moodalbail 			i_ipadm_get_mtu, i_ipadm_get_metric,
716e91bba0SGirish Moodalbail 			i_ipadm_get_usesrc, i_ipadm_get_forwarding,
72f1e9465bSSowmini Varadhan 			i_ipadm_get_ecnsack, i_ipadm_get_hostmodel;
736e91bba0SGirish Moodalbail 
746e91bba0SGirish Moodalbail /*
756e91bba0SGirish Moodalbail  * Callback function to set property values. These functions translate the
766e91bba0SGirish Moodalbail  * values to a format suitable for kernel consumption, allocates the necessary
776e91bba0SGirish Moodalbail  * ioctl buffers and then invokes ioctl().
786e91bba0SGirish Moodalbail  */
796e91bba0SGirish Moodalbail static ipadm_pd_setf_t	i_ipadm_set_prop, i_ipadm_set_mtu,
806e91bba0SGirish Moodalbail 			i_ipadm_set_ifprop_flags,
816e91bba0SGirish Moodalbail 			i_ipadm_set_metric, i_ipadm_set_usesrc,
826e91bba0SGirish Moodalbail 			i_ipadm_set_forwarding, i_ipadm_set_eprivport,
83f1e9465bSSowmini Varadhan 			i_ipadm_set_ecnsack, i_ipadm_set_hostmodel;
846e91bba0SGirish Moodalbail 
856e91bba0SGirish Moodalbail /* array of protocols we support */
866e91bba0SGirish Moodalbail static int protocols[] = { MOD_PROTO_IP, MOD_PROTO_RAWIP,
876e91bba0SGirish Moodalbail 			    MOD_PROTO_TCP, MOD_PROTO_UDP,
886e91bba0SGirish Moodalbail 			    MOD_PROTO_SCTP };
896e91bba0SGirish Moodalbail 
906e91bba0SGirish Moodalbail /*
916e91bba0SGirish Moodalbail  * Supported IP protocol properties.
926e91bba0SGirish Moodalbail  */
936e91bba0SGirish Moodalbail static ipadm_prop_desc_t ipadm_ip_prop_table[] = {
94299625c6SSebastien Roy 	{ "arp", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
956e91bba0SGirish Moodalbail 	    i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
966e91bba0SGirish Moodalbail 	    i_ipadm_get_ifprop_flags },
976e91bba0SGirish Moodalbail 
98299625c6SSebastien Roy 	{ "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV4, 0,
996e91bba0SGirish Moodalbail 	    i_ipadm_set_forwarding, i_ipadm_get_onoff,
1006e91bba0SGirish Moodalbail 	    i_ipadm_get_forwarding },
1016e91bba0SGirish Moodalbail 
102299625c6SSebastien Roy 	{ "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
1036e91bba0SGirish Moodalbail 	    i_ipadm_set_metric, NULL, i_ipadm_get_metric },
1046e91bba0SGirish Moodalbail 
105299625c6SSebastien Roy 	{ "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
1066e91bba0SGirish Moodalbail 	    i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
1076e91bba0SGirish Moodalbail 
108299625c6SSebastien Roy 	{ "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
1096e91bba0SGirish Moodalbail 	    i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
1106e91bba0SGirish Moodalbail 	    i_ipadm_get_ifprop_flags },
1116e91bba0SGirish Moodalbail 
112299625c6SSebastien Roy 	{ "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
1136e91bba0SGirish Moodalbail 	    i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
1146e91bba0SGirish Moodalbail 
115299625c6SSebastien Roy 	{ "ttl", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
1166e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1176e91bba0SGirish Moodalbail 
118299625c6SSebastien Roy 	{ "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV6, 0,
1196e91bba0SGirish Moodalbail 	    i_ipadm_set_forwarding, i_ipadm_get_onoff,
1206e91bba0SGirish Moodalbail 	    i_ipadm_get_forwarding },
1216e91bba0SGirish Moodalbail 
122299625c6SSebastien Roy 	{ "hoplimit", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
1236e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1246e91bba0SGirish Moodalbail 
125299625c6SSebastien Roy 	{ "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
1266e91bba0SGirish Moodalbail 	    i_ipadm_set_metric, NULL, i_ipadm_get_metric },
1276e91bba0SGirish Moodalbail 
128299625c6SSebastien Roy 	{ "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
1296e91bba0SGirish Moodalbail 	    i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
1306e91bba0SGirish Moodalbail 
131299625c6SSebastien Roy 	{ "nud", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
1326e91bba0SGirish Moodalbail 	    i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
1336e91bba0SGirish Moodalbail 	    i_ipadm_get_ifprop_flags },
1346e91bba0SGirish Moodalbail 
135299625c6SSebastien Roy 	{ "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
1366e91bba0SGirish Moodalbail 	    i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
1376e91bba0SGirish Moodalbail 	    i_ipadm_get_ifprop_flags },
1386e91bba0SGirish Moodalbail 
139299625c6SSebastien Roy 	{ "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
1406e91bba0SGirish Moodalbail 	    i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
1416e91bba0SGirish Moodalbail 
142299625c6SSebastien Roy 	{ "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
143f1e9465bSSowmini Varadhan 	    i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
144f1e9465bSSowmini Varadhan 	    i_ipadm_get_hostmodel },
145f1e9465bSSowmini Varadhan 
146299625c6SSebastien Roy 	{ "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
147f1e9465bSSowmini Varadhan 	    i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
148f1e9465bSSowmini Varadhan 	    i_ipadm_get_hostmodel },
149f1e9465bSSowmini Varadhan 
150*a73be61aSHans Rosenfeld 	{ "standby", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IP, 0,
151*a73be61aSHans Rosenfeld 	    i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
152*a73be61aSHans Rosenfeld 	    i_ipadm_get_ifprop_flags },
153*a73be61aSHans Rosenfeld 
154*a73be61aSHans Rosenfeld 
155299625c6SSebastien Roy 	{ NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
1566e91bba0SGirish Moodalbail };
1576e91bba0SGirish Moodalbail 
1586e91bba0SGirish Moodalbail /* possible values for TCP properties `ecn' and `sack' */
1596e91bba0SGirish Moodalbail static const char *ecn_sack_vals[] = {"never", "passive", "active", NULL};
1606e91bba0SGirish Moodalbail 
1616e91bba0SGirish Moodalbail /* Supported TCP protocol properties */
1626e91bba0SGirish Moodalbail static ipadm_prop_desc_t ipadm_tcp_prop_table[] = {
16345a4b79dSSebastien Roy 	{ "congestion_control", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
16445a4b79dSSebastien Roy 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
16545a4b79dSSebastien Roy 
166299625c6SSebastien Roy 	{ "ecn", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1676e91bba0SGirish Moodalbail 	    i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
1686e91bba0SGirish Moodalbail 
169299625c6SSebastien Roy 	{ "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
1708b88711aSGirish Moodalbail 	    IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
1718b88711aSGirish Moodalbail 	    i_ipadm_get_prop },
1726e91bba0SGirish Moodalbail 
173299625c6SSebastien Roy 	{ "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1746e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1756e91bba0SGirish Moodalbail 
176299625c6SSebastien Roy 	{ "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1776e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1786e91bba0SGirish Moodalbail 
179299625c6SSebastien Roy 	{ "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
180299625c6SSebastien Roy 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
181299625c6SSebastien Roy 
182299625c6SSebastien Roy 	{ "sack", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1836e91bba0SGirish Moodalbail 	    i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
1846e91bba0SGirish Moodalbail 
185299625c6SSebastien Roy 	{ "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1866e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1876e91bba0SGirish Moodalbail 
188299625c6SSebastien Roy 	{ "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
1896e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1906e91bba0SGirish Moodalbail 
191299625c6SSebastien Roy 	{ "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
192299625c6SSebastien Roy 	    0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
1936e91bba0SGirish Moodalbail 
194299625c6SSebastien Roy 	{ NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
1956e91bba0SGirish Moodalbail };
1966e91bba0SGirish Moodalbail 
1976e91bba0SGirish Moodalbail /* Supported UDP protocol properties */
1986e91bba0SGirish Moodalbail static ipadm_prop_desc_t ipadm_udp_prop_table[] = {
199299625c6SSebastien Roy 	{ "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
2008b88711aSGirish Moodalbail 	    IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
2018b88711aSGirish Moodalbail 	    i_ipadm_get_prop },
2026e91bba0SGirish Moodalbail 
203299625c6SSebastien Roy 	{ "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
2046e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2056e91bba0SGirish Moodalbail 
206299625c6SSebastien Roy 	{ "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
2076e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2086e91bba0SGirish Moodalbail 
209299625c6SSebastien Roy 	{ "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
2106e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2116e91bba0SGirish Moodalbail 
212299625c6SSebastien Roy 	{ "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
2136e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2146e91bba0SGirish Moodalbail 
215299625c6SSebastien Roy 	{ "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
2166e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2176e91bba0SGirish Moodalbail 
218299625c6SSebastien Roy 	{ "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
219299625c6SSebastien Roy 	    0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
220299625c6SSebastien Roy 
221299625c6SSebastien Roy 	{ NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
2226e91bba0SGirish Moodalbail };
2236e91bba0SGirish Moodalbail 
2246e91bba0SGirish Moodalbail /* Supported SCTP protocol properties */
2256e91bba0SGirish Moodalbail static ipadm_prop_desc_t ipadm_sctp_prop_table[] = {
226299625c6SSebastien Roy 	{ "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
2278b88711aSGirish Moodalbail 	    IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
2288b88711aSGirish Moodalbail 	    i_ipadm_get_prop },
2296e91bba0SGirish Moodalbail 
230299625c6SSebastien Roy 	{ "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
2316e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2326e91bba0SGirish Moodalbail 
233299625c6SSebastien Roy 	{ "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
2346e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2356e91bba0SGirish Moodalbail 
236299625c6SSebastien Roy 	{ "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
2376e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2386e91bba0SGirish Moodalbail 
239299625c6SSebastien Roy 	{ "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
2406e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2416e91bba0SGirish Moodalbail 
242299625c6SSebastien Roy 	{ "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
2436e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2446e91bba0SGirish Moodalbail 
245299625c6SSebastien Roy 	{ "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
246299625c6SSebastien Roy 	    0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
247299625c6SSebastien Roy 
248299625c6SSebastien Roy 	{ NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
2496e91bba0SGirish Moodalbail };
2506e91bba0SGirish Moodalbail 
2516e91bba0SGirish Moodalbail /* Supported ICMP protocol properties */
2526e91bba0SGirish Moodalbail static ipadm_prop_desc_t ipadm_icmp_prop_table[] = {
253299625c6SSebastien Roy 	{ "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
2546e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2556e91bba0SGirish Moodalbail 
256299625c6SSebastien Roy 	{ "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
2576e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
2586e91bba0SGirish Moodalbail 
259299625c6SSebastien Roy 	{ "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
260299625c6SSebastien Roy 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
261299625c6SSebastien Roy 
262299625c6SSebastien Roy 	{ NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
2636e91bba0SGirish Moodalbail };
2646e91bba0SGirish Moodalbail 
2656e91bba0SGirish Moodalbail /*
2666e91bba0SGirish Moodalbail  * A dummy private property structure, used while handling private
2676e91bba0SGirish Moodalbail  * protocol properties (properties not yet supported by libipadm).
2686e91bba0SGirish Moodalbail  */
269299625c6SSebastien Roy static ipadm_prop_desc_t ipadm_privprop =
270299625c6SSebastien Roy 	{ NULL, NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_NONE, 0,
2716e91bba0SGirish Moodalbail 	    i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop };
2726e91bba0SGirish Moodalbail 
2736e91bba0SGirish Moodalbail /*
2746e91bba0SGirish Moodalbail  * Returns the property description table, for the given protocol
2756e91bba0SGirish Moodalbail  */
2766e91bba0SGirish Moodalbail static ipadm_prop_desc_t *
i_ipadm_get_propdesc_table(uint_t proto)2776e91bba0SGirish Moodalbail i_ipadm_get_propdesc_table(uint_t proto)
2786e91bba0SGirish Moodalbail {
2796e91bba0SGirish Moodalbail 	switch (proto) {
2806e91bba0SGirish Moodalbail 	case MOD_PROTO_IP:
2816e91bba0SGirish Moodalbail 	case MOD_PROTO_IPV4:
2826e91bba0SGirish Moodalbail 	case MOD_PROTO_IPV6:
2836e91bba0SGirish Moodalbail 		return (ipadm_ip_prop_table);
2846e91bba0SGirish Moodalbail 	case MOD_PROTO_RAWIP:
2856e91bba0SGirish Moodalbail 		return (ipadm_icmp_prop_table);
2866e91bba0SGirish Moodalbail 	case MOD_PROTO_TCP:
2876e91bba0SGirish Moodalbail 		return (ipadm_tcp_prop_table);
2886e91bba0SGirish Moodalbail 	case MOD_PROTO_UDP:
2896e91bba0SGirish Moodalbail 		return (ipadm_udp_prop_table);
2906e91bba0SGirish Moodalbail 	case MOD_PROTO_SCTP:
2916e91bba0SGirish Moodalbail 		return (ipadm_sctp_prop_table);
2926e91bba0SGirish Moodalbail 	}
2936e91bba0SGirish Moodalbail 
2946e91bba0SGirish Moodalbail 	return (NULL);
2956e91bba0SGirish Moodalbail }
2966e91bba0SGirish Moodalbail 
2978887b57dSGirish Moodalbail static ipadm_prop_desc_t *
i_ipadm_get_prop_desc(const char * pname,uint_t proto,int * errp)2988887b57dSGirish Moodalbail i_ipadm_get_prop_desc(const char *pname, uint_t proto, int *errp)
2998887b57dSGirish Moodalbail {
3008887b57dSGirish Moodalbail 	int		err = 0;
3018887b57dSGirish Moodalbail 	boolean_t	matched_name = B_FALSE;
3028887b57dSGirish Moodalbail 	ipadm_prop_desc_t *ipdp = NULL, *ipdtbl;
3038887b57dSGirish Moodalbail 
3048887b57dSGirish Moodalbail 	if ((ipdtbl = i_ipadm_get_propdesc_table(proto)) == NULL) {
3058887b57dSGirish Moodalbail 		err = EINVAL;
3068887b57dSGirish Moodalbail 		goto ret;
3078887b57dSGirish Moodalbail 	}
308299625c6SSebastien Roy 
3098887b57dSGirish Moodalbail 	for (ipdp = ipdtbl; ipdp->ipd_name != NULL; ipdp++) {
310299625c6SSebastien Roy 		if (strcmp(pname, ipdp->ipd_name) == 0 ||
311299625c6SSebastien Roy 		    (ipdp->ipd_old_name != NULL &&
312299625c6SSebastien Roy 		    strcmp(pname, ipdp->ipd_old_name) == 0)) {
3138887b57dSGirish Moodalbail 			matched_name = B_TRUE;
3148887b57dSGirish Moodalbail 			if (ipdp->ipd_proto == proto)
3158887b57dSGirish Moodalbail 				break;
3168887b57dSGirish Moodalbail 		}
3178887b57dSGirish Moodalbail 	}
318299625c6SSebastien Roy 
3198887b57dSGirish Moodalbail 	if (ipdp->ipd_name == NULL) {
3208887b57dSGirish Moodalbail 		err = ENOENT;
3218887b57dSGirish Moodalbail 		/* if we matched name, but failed protocol check */
3228887b57dSGirish Moodalbail 		if (matched_name)
3238887b57dSGirish Moodalbail 			err = EPROTO;
3248887b57dSGirish Moodalbail 		ipdp = NULL;
3258887b57dSGirish Moodalbail 	}
3268887b57dSGirish Moodalbail ret:
3278887b57dSGirish Moodalbail 	if (errp != NULL)
3288887b57dSGirish Moodalbail 		*errp = err;
3298887b57dSGirish Moodalbail 	return (ipdp);
3308887b57dSGirish Moodalbail }
3318887b57dSGirish Moodalbail 
3326e91bba0SGirish Moodalbail char *
ipadm_proto2str(uint_t proto)3336e91bba0SGirish Moodalbail ipadm_proto2str(uint_t proto)
3346e91bba0SGirish Moodalbail {
3356e91bba0SGirish Moodalbail 	switch (proto) {
3366e91bba0SGirish Moodalbail 	case MOD_PROTO_IP:
3376e91bba0SGirish Moodalbail 		return ("ip");
3386e91bba0SGirish Moodalbail 	case MOD_PROTO_IPV4:
3396e91bba0SGirish Moodalbail 		return ("ipv4");
3406e91bba0SGirish Moodalbail 	case MOD_PROTO_IPV6:
3416e91bba0SGirish Moodalbail 		return ("ipv6");
3426e91bba0SGirish Moodalbail 	case MOD_PROTO_RAWIP:
3436e91bba0SGirish Moodalbail 		return ("icmp");
3446e91bba0SGirish Moodalbail 	case MOD_PROTO_TCP:
3456e91bba0SGirish Moodalbail 		return ("tcp");
3466e91bba0SGirish Moodalbail 	case MOD_PROTO_UDP:
3476e91bba0SGirish Moodalbail 		return ("udp");
3486e91bba0SGirish Moodalbail 	case MOD_PROTO_SCTP:
3496e91bba0SGirish Moodalbail 		return ("sctp");
3506e91bba0SGirish Moodalbail 	}
3516e91bba0SGirish Moodalbail 
3526e91bba0SGirish Moodalbail 	return (NULL);
3536e91bba0SGirish Moodalbail }
3546e91bba0SGirish Moodalbail 
3556e91bba0SGirish Moodalbail uint_t
ipadm_str2proto(const char * protostr)3566e91bba0SGirish Moodalbail ipadm_str2proto(const char *protostr)
3576e91bba0SGirish Moodalbail {
3586e91bba0SGirish Moodalbail 	if (protostr == NULL)
3596e91bba0SGirish Moodalbail 		return (MOD_PROTO_NONE);
3606e91bba0SGirish Moodalbail 	if (strcmp(protostr, "tcp") == 0)
3616e91bba0SGirish Moodalbail 		return (MOD_PROTO_TCP);
3626e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "udp") == 0)
3636e91bba0SGirish Moodalbail 		return (MOD_PROTO_UDP);
3646e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "ip") == 0)
3656e91bba0SGirish Moodalbail 		return (MOD_PROTO_IP);
3666e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "ipv4") == 0)
3676e91bba0SGirish Moodalbail 		return (MOD_PROTO_IPV4);
3686e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "ipv6") == 0)
3696e91bba0SGirish Moodalbail 		return (MOD_PROTO_IPV6);
3706e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "icmp") == 0)
3716e91bba0SGirish Moodalbail 		return (MOD_PROTO_RAWIP);
3726e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "sctp") == 0)
3736e91bba0SGirish Moodalbail 		return (MOD_PROTO_SCTP);
3746e91bba0SGirish Moodalbail 	else if (strcmp(protostr, "arp") == 0)
3756e91bba0SGirish Moodalbail 		return (MOD_PROTO_IP);
3766e91bba0SGirish Moodalbail 
3776e91bba0SGirish Moodalbail 	return (MOD_PROTO_NONE);
3786e91bba0SGirish Moodalbail }
3796e91bba0SGirish Moodalbail 
3806e91bba0SGirish Moodalbail /* ARGSUSED */
3816e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_mtu(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)3826e91bba0SGirish Moodalbail i_ipadm_set_mtu(ipadm_handle_t iph, const void *arg,
3836e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
3846e91bba0SGirish Moodalbail {
3856e91bba0SGirish Moodalbail 	struct lifreq	lifr;
3866e91bba0SGirish Moodalbail 	char		*endp;
3876e91bba0SGirish Moodalbail 	uint_t		mtu;
3886e91bba0SGirish Moodalbail 	int		s;
3896e91bba0SGirish Moodalbail 	const char	*ifname = arg;
3906e91bba0SGirish Moodalbail 	char		val[MAXPROPVALLEN];
3916e91bba0SGirish Moodalbail 
3926e91bba0SGirish Moodalbail 	/* to reset MTU first retrieve the default MTU and then set it */
3936e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT) {
3946e91bba0SGirish Moodalbail 		ipadm_status_t	status;
3956e91bba0SGirish Moodalbail 		uint_t		size = MAXPROPVALLEN;
3966e91bba0SGirish Moodalbail 
3976e91bba0SGirish Moodalbail 		status = i_ipadm_get_prop(iph, arg, pdp, val, &size,
3986e91bba0SGirish Moodalbail 		    proto, MOD_PROP_DEFAULT);
3996e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS)
4006e91bba0SGirish Moodalbail 			return (status);
4016e91bba0SGirish Moodalbail 		pval = val;
4026e91bba0SGirish Moodalbail 	}
4036e91bba0SGirish Moodalbail 
4046e91bba0SGirish Moodalbail 	errno = 0;
4056e91bba0SGirish Moodalbail 	mtu = (uint_t)strtol(pval, &endp, 10);
4066e91bba0SGirish Moodalbail 	if (errno != 0 || *endp != '\0')
4076e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
4086e91bba0SGirish Moodalbail 
4096e91bba0SGirish Moodalbail 	bzero(&lifr, sizeof (lifr));
4106e91bba0SGirish Moodalbail 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
4116e91bba0SGirish Moodalbail 	lifr.lifr_mtu = mtu;
4126e91bba0SGirish Moodalbail 
4136e91bba0SGirish Moodalbail 	s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
4146e91bba0SGirish Moodalbail 	if (ioctl(s, SIOCSLIFMTU, (caddr_t)&lifr) < 0)
4156e91bba0SGirish Moodalbail 		return (ipadm_errno2status(errno));
4166e91bba0SGirish Moodalbail 
4176e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
4186e91bba0SGirish Moodalbail }
4196e91bba0SGirish Moodalbail 
4206e91bba0SGirish Moodalbail /* ARGSUSED */
4216e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_metric(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)4226e91bba0SGirish Moodalbail i_ipadm_set_metric(ipadm_handle_t iph, const void *arg,
4236e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
4246e91bba0SGirish Moodalbail {
4256e91bba0SGirish Moodalbail 	struct lifreq	lifr;
4266e91bba0SGirish Moodalbail 	char		*endp;
4276e91bba0SGirish Moodalbail 	int		metric;
4286e91bba0SGirish Moodalbail 	const char	*ifname = arg;
4296e91bba0SGirish Moodalbail 	int		s;
4306e91bba0SGirish Moodalbail 
4316e91bba0SGirish Moodalbail 	/* if we are resetting, set the value to its default value */
4326e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT) {
4336e91bba0SGirish Moodalbail 		metric = DEF_METRIC_VAL;
4346e91bba0SGirish Moodalbail 	} else {
4356e91bba0SGirish Moodalbail 		errno = 0;
4366e91bba0SGirish Moodalbail 		metric = (uint_t)strtol(pval, &endp, 10);
4376e91bba0SGirish Moodalbail 		if (errno != 0 || *endp != '\0')
4386e91bba0SGirish Moodalbail 			return (IPADM_INVALID_ARG);
4396e91bba0SGirish Moodalbail 	}
4406e91bba0SGirish Moodalbail 
4416e91bba0SGirish Moodalbail 	bzero(&lifr, sizeof (lifr));
4426e91bba0SGirish Moodalbail 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
4436e91bba0SGirish Moodalbail 	lifr.lifr_metric = metric;
4446e91bba0SGirish Moodalbail 
4456e91bba0SGirish Moodalbail 	s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
4466e91bba0SGirish Moodalbail 
4476e91bba0SGirish Moodalbail 	if (ioctl(s, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0)
4486e91bba0SGirish Moodalbail 		return (ipadm_errno2status(errno));
4496e91bba0SGirish Moodalbail 
4506e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
4516e91bba0SGirish Moodalbail }
4526e91bba0SGirish Moodalbail 
4536e91bba0SGirish Moodalbail /* ARGSUSED */
4546e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_usesrc(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)4556e91bba0SGirish Moodalbail i_ipadm_set_usesrc(ipadm_handle_t iph, const void *arg,
4566e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
4576e91bba0SGirish Moodalbail {
4586e91bba0SGirish Moodalbail 	struct lifreq	lifr;
4596e91bba0SGirish Moodalbail 	const char	*ifname = arg;
4606e91bba0SGirish Moodalbail 	int		s;
4616e91bba0SGirish Moodalbail 	uint_t		ifindex = 0;
4626e91bba0SGirish Moodalbail 
4636e91bba0SGirish Moodalbail 	/* if we are resetting, set the value to its default value */
4646e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT)
4656e91bba0SGirish Moodalbail 		pval = IPADM_NONESTR;
4666e91bba0SGirish Moodalbail 
4676e91bba0SGirish Moodalbail 	/*
4686e91bba0SGirish Moodalbail 	 * cannot specify logical interface name. We can also filter out other
4696e91bba0SGirish Moodalbail 	 * bogus interface names here itself through i_ipadm_validate_ifname().
4706e91bba0SGirish Moodalbail 	 */
4716e91bba0SGirish Moodalbail 	if (strcmp(pval, IPADM_NONESTR) != 0 &&
4726e91bba0SGirish Moodalbail 	    !i_ipadm_validate_ifname(iph, pval))
4736e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
4746e91bba0SGirish Moodalbail 
4756e91bba0SGirish Moodalbail 	bzero(&lifr, sizeof (lifr));
4766e91bba0SGirish Moodalbail 	(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
4776e91bba0SGirish Moodalbail 
4786e91bba0SGirish Moodalbail 	s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
4796e91bba0SGirish Moodalbail 
4806e91bba0SGirish Moodalbail 	if (strcmp(pval, IPADM_NONESTR) != 0) {
4816e91bba0SGirish Moodalbail 		if ((ifindex = if_nametoindex(pval)) == 0)
4826e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
4836e91bba0SGirish Moodalbail 		lifr.lifr_index = ifindex;
4846e91bba0SGirish Moodalbail 	} else {
4856e91bba0SGirish Moodalbail 		if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
4866e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
4876e91bba0SGirish Moodalbail 		lifr.lifr_index = 0;
4886e91bba0SGirish Moodalbail 	}
4896e91bba0SGirish Moodalbail 	if (ioctl(s, SIOCSLIFUSESRC, (caddr_t)&lifr) < 0)
4906e91bba0SGirish Moodalbail 		return (ipadm_errno2status(errno));
4916e91bba0SGirish Moodalbail 
4926e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
4936e91bba0SGirish Moodalbail }
4946e91bba0SGirish Moodalbail 
495f1e9465bSSowmini Varadhan static struct hostmodel_strval {
496f1e9465bSSowmini Varadhan 	char *esm_str;
497f1e9465bSSowmini Varadhan 	ip_hostmodel_t esm_val;
498f1e9465bSSowmini Varadhan } esm_arr[] = {
499f1e9465bSSowmini Varadhan 	{"weak", IP_WEAK_ES},
500f1e9465bSSowmini Varadhan 	{"src-priority", IP_SRC_PRI_ES},
501f1e9465bSSowmini Varadhan 	{"strong", IP_STRONG_ES},
502f1e9465bSSowmini Varadhan 	{"custom", IP_MAXVAL_ES}
503f1e9465bSSowmini Varadhan };
504f1e9465bSSowmini Varadhan 
505f1e9465bSSowmini Varadhan static ip_hostmodel_t
i_ipadm_hostmodel_str2val(const char * pval)506f1e9465bSSowmini Varadhan i_ipadm_hostmodel_str2val(const char *pval)
507f1e9465bSSowmini Varadhan {
508f1e9465bSSowmini Varadhan 	int i;
509f1e9465bSSowmini Varadhan 
510f1e9465bSSowmini Varadhan 	for (i = 0; i < A_CNT(esm_arr); i++) {
511f1e9465bSSowmini Varadhan 		if (esm_arr[i].esm_str != NULL &&
512f1e9465bSSowmini Varadhan 		    strcmp(pval, esm_arr[i].esm_str) == 0) {
513f1e9465bSSowmini Varadhan 			return (esm_arr[i].esm_val);
514f1e9465bSSowmini Varadhan 		}
515f1e9465bSSowmini Varadhan 	}
516f1e9465bSSowmini Varadhan 	return (IP_MAXVAL_ES);
517f1e9465bSSowmini Varadhan }
518f1e9465bSSowmini Varadhan 
519f1e9465bSSowmini Varadhan static char *
i_ipadm_hostmodel_val2str(ip_hostmodel_t pval)520f1e9465bSSowmini Varadhan i_ipadm_hostmodel_val2str(ip_hostmodel_t pval)
521f1e9465bSSowmini Varadhan {
522f1e9465bSSowmini Varadhan 	int i;
523f1e9465bSSowmini Varadhan 
524f1e9465bSSowmini Varadhan 	for (i = 0; i < A_CNT(esm_arr); i++) {
525f1e9465bSSowmini Varadhan 		if (esm_arr[i].esm_val == pval)
526f1e9465bSSowmini Varadhan 			return (esm_arr[i].esm_str);
527f1e9465bSSowmini Varadhan 	}
528f1e9465bSSowmini Varadhan 	return (NULL);
529f1e9465bSSowmini Varadhan }
530f1e9465bSSowmini Varadhan 
531f1e9465bSSowmini Varadhan /* ARGSUSED */
532f1e9465bSSowmini Varadhan static ipadm_status_t
i_ipadm_set_hostmodel(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)533f1e9465bSSowmini Varadhan i_ipadm_set_hostmodel(ipadm_handle_t iph, const void *arg,
534f1e9465bSSowmini Varadhan     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
535f1e9465bSSowmini Varadhan {
536f1e9465bSSowmini Varadhan 	ip_hostmodel_t hostmodel;
537f1e9465bSSowmini Varadhan 	char val[11]; /* covers uint32_max as a string */
538f1e9465bSSowmini Varadhan 
539f1e9465bSSowmini Varadhan 	if ((flags & IPADM_OPT_DEFAULT) == 0) {
540f1e9465bSSowmini Varadhan 		hostmodel = i_ipadm_hostmodel_str2val(pval);
541f1e9465bSSowmini Varadhan 		if (hostmodel == IP_MAXVAL_ES)
542f1e9465bSSowmini Varadhan 			return (IPADM_INVALID_ARG);
543f1e9465bSSowmini Varadhan 		(void) snprintf(val, sizeof (val), "%d", hostmodel);
544f1e9465bSSowmini Varadhan 		pval = val;
545f1e9465bSSowmini Varadhan 	}
546f1e9465bSSowmini Varadhan 	return (i_ipadm_set_prop(iph, NULL, pdp, pval, proto, flags));
547f1e9465bSSowmini Varadhan }
548f1e9465bSSowmini Varadhan 
549f1e9465bSSowmini Varadhan /* ARGSUSED */
550f1e9465bSSowmini Varadhan static ipadm_status_t
i_ipadm_get_hostmodel(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)551f1e9465bSSowmini Varadhan i_ipadm_get_hostmodel(ipadm_handle_t iph, const void *arg,
552f1e9465bSSowmini Varadhan     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
553f1e9465bSSowmini Varadhan     uint_t valtype)
554f1e9465bSSowmini Varadhan {
555f1e9465bSSowmini Varadhan 	ip_hostmodel_t hostmodel;
556f1e9465bSSowmini Varadhan 	char *cp;
557f1e9465bSSowmini Varadhan 	size_t nbytes;
558f1e9465bSSowmini Varadhan 	ipadm_status_t status;
559f1e9465bSSowmini Varadhan 
560f1e9465bSSowmini Varadhan 	switch (valtype) {
561f1e9465bSSowmini Varadhan 	case MOD_PROP_PERM:
562f1e9465bSSowmini Varadhan 		nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
563f1e9465bSSowmini Varadhan 		break;
564f1e9465bSSowmini Varadhan 	case MOD_PROP_DEFAULT:
565f1e9465bSSowmini Varadhan 		nbytes = snprintf(buf, *bufsize, "weak");
566f1e9465bSSowmini Varadhan 		break;
567f1e9465bSSowmini Varadhan 	case MOD_PROP_ACTIVE:
568f1e9465bSSowmini Varadhan 		status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
569f1e9465bSSowmini Varadhan 		    valtype);
570f1e9465bSSowmini Varadhan 		if (status != IPADM_SUCCESS)
571f1e9465bSSowmini Varadhan 			return (status);
572f1e9465bSSowmini Varadhan 		bcopy(buf, &hostmodel, sizeof (hostmodel));
573f1e9465bSSowmini Varadhan 		cp = i_ipadm_hostmodel_val2str(hostmodel);
574f1e9465bSSowmini Varadhan 		nbytes = snprintf(buf, *bufsize, "%s",
575f1e9465bSSowmini Varadhan 		    (cp != NULL ? cp : "?"));
576f1e9465bSSowmini Varadhan 		break;
577f1e9465bSSowmini Varadhan 	case MOD_PROP_POSSIBLE:
578f1e9465bSSowmini Varadhan 		nbytes = snprintf(buf, *bufsize, "strong,src-priority,weak");
579f1e9465bSSowmini Varadhan 		break;
580f1e9465bSSowmini Varadhan 	default:
581f1e9465bSSowmini Varadhan 		return (IPADM_INVALID_ARG);
582f1e9465bSSowmini Varadhan 	}
583f1e9465bSSowmini Varadhan 	if (nbytes >= *bufsize) {
584f1e9465bSSowmini Varadhan 		/* insufficient buffer space */
585f1e9465bSSowmini Varadhan 		*bufsize = nbytes + 1;
586f1e9465bSSowmini Varadhan 		return (IPADM_NO_BUFS);
587f1e9465bSSowmini Varadhan 	}
588f1e9465bSSowmini Varadhan 	return (IPADM_SUCCESS);
589f1e9465bSSowmini Varadhan }
590f1e9465bSSowmini Varadhan 
5916e91bba0SGirish Moodalbail /* ARGSUSED */
5926e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_ifprop_flags(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)5936e91bba0SGirish Moodalbail i_ipadm_set_ifprop_flags(ipadm_handle_t iph, const void *arg,
5946e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
5956e91bba0SGirish Moodalbail {
5966e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
5976e91bba0SGirish Moodalbail 	const char	*ifname = arg;
5986e91bba0SGirish Moodalbail 	uint64_t	on_flags = 0, off_flags = 0;
5996e91bba0SGirish Moodalbail 	boolean_t	on = B_FALSE;
6006e91bba0SGirish Moodalbail 	sa_family_t	af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
6016e91bba0SGirish Moodalbail 
6026e91bba0SGirish Moodalbail 	/* if we are resetting, set the value to its default value */
6036e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT) {
6046e91bba0SGirish Moodalbail 		if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
6056e91bba0SGirish Moodalbail 		    strcmp(pdp->ipd_name, "arp") == 0 ||
6066e91bba0SGirish Moodalbail 		    strcmp(pdp->ipd_name, "nud") == 0) {
6076e91bba0SGirish Moodalbail 			pval = IPADM_ONSTR;
608*a73be61aSHans Rosenfeld 		} else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
609*a73be61aSHans Rosenfeld 		    strcmp(pdp->ipd_name, "standby") == 0) {
6106e91bba0SGirish Moodalbail 			pval = IPADM_OFFSTR;
6116e91bba0SGirish Moodalbail 		} else {
6126e91bba0SGirish Moodalbail 			return (IPADM_PROP_UNKNOWN);
6136e91bba0SGirish Moodalbail 		}
6146e91bba0SGirish Moodalbail 	}
6156e91bba0SGirish Moodalbail 
6166e91bba0SGirish Moodalbail 	if (strcmp(pval, IPADM_ONSTR) == 0)
6176e91bba0SGirish Moodalbail 		on = B_TRUE;
6186e91bba0SGirish Moodalbail 	else if (strcmp(pval, IPADM_OFFSTR) == 0)
6196e91bba0SGirish Moodalbail 		on = B_FALSE;
6206e91bba0SGirish Moodalbail 	else
6216e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
6226e91bba0SGirish Moodalbail 
6236e91bba0SGirish Moodalbail 	if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
6246e91bba0SGirish Moodalbail 		if (on)
6256e91bba0SGirish Moodalbail 			off_flags = IFF_NORTEXCH;
6266e91bba0SGirish Moodalbail 		else
6276e91bba0SGirish Moodalbail 			on_flags = IFF_NORTEXCH;
6286e91bba0SGirish Moodalbail 	} else if (strcmp(pdp->ipd_name, "arp") == 0) {
6296e91bba0SGirish Moodalbail 		if (on)
6306e91bba0SGirish Moodalbail 			off_flags = IFF_NOARP;
6316e91bba0SGirish Moodalbail 		else
6326e91bba0SGirish Moodalbail 			on_flags = IFF_NOARP;
6336e91bba0SGirish Moodalbail 	} else if (strcmp(pdp->ipd_name, "nud") == 0) {
6346e91bba0SGirish Moodalbail 		if (on)
6356e91bba0SGirish Moodalbail 			off_flags = IFF_NONUD;
6366e91bba0SGirish Moodalbail 		else
6376e91bba0SGirish Moodalbail 			on_flags = IFF_NONUD;
6386e91bba0SGirish Moodalbail 	} else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
6396e91bba0SGirish Moodalbail 		if (on)
6406e91bba0SGirish Moodalbail 			on_flags = IFF_ROUTER;
6416e91bba0SGirish Moodalbail 		else
6426e91bba0SGirish Moodalbail 			off_flags = IFF_ROUTER;
643*a73be61aSHans Rosenfeld 	} else if (strcmp(pdp->ipd_name, "standby") == 0) {
644*a73be61aSHans Rosenfeld 		if (on)
645*a73be61aSHans Rosenfeld 			on_flags = IFF_STANDBY;
646*a73be61aSHans Rosenfeld 		else
647*a73be61aSHans Rosenfeld 			off_flags = IFF_STANDBY;
6486e91bba0SGirish Moodalbail 	}
6496e91bba0SGirish Moodalbail 
6506e91bba0SGirish Moodalbail 	if (on_flags || off_flags)  {
6516e91bba0SGirish Moodalbail 		status = i_ipadm_set_flags(iph, ifname, af, on_flags,
6526e91bba0SGirish Moodalbail 		    off_flags);
6536e91bba0SGirish Moodalbail 	}
6546e91bba0SGirish Moodalbail 	return (status);
6556e91bba0SGirish Moodalbail }
6566e91bba0SGirish Moodalbail 
6576e91bba0SGirish Moodalbail /* ARGSUSED */
6586e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_eprivport(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)6596e91bba0SGirish Moodalbail i_ipadm_set_eprivport(ipadm_handle_t iph, const void *arg,
6606e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
6616e91bba0SGirish Moodalbail {
6626e91bba0SGirish Moodalbail 	nvlist_t	*portsnvl = NULL;
6636e91bba0SGirish Moodalbail 	nvpair_t	*nvp;
6646e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
6656e91bba0SGirish Moodalbail 	uint_t		count = 0;
6666e91bba0SGirish Moodalbail 
6676e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT) {
6686e91bba0SGirish Moodalbail 		assert(pval == NULL);
6696e91bba0SGirish Moodalbail 		return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
6706e91bba0SGirish Moodalbail 	}
6716e91bba0SGirish Moodalbail 
672*a73be61aSHans Rosenfeld 	if ((status = ipadm_str2nvlist(pval, &portsnvl, IPADM_NORVAL)) != 0)
673*a73be61aSHans Rosenfeld 		return (status);
6746e91bba0SGirish Moodalbail 
6756e91bba0SGirish Moodalbail 	/* count the number of ports */
6766e91bba0SGirish Moodalbail 	for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
6776e91bba0SGirish Moodalbail 	    nvp = nvlist_next_nvpair(portsnvl, nvp)) {
6786e91bba0SGirish Moodalbail 		++count;
6796e91bba0SGirish Moodalbail 	}
6806e91bba0SGirish Moodalbail 
68117074b3aSGirish Moodalbail 	if (iph->iph_flags & IPH_INIT) {
68217074b3aSGirish Moodalbail 		flags |= IPADM_OPT_APPEND;
68317074b3aSGirish Moodalbail 	} else if (count > 1) {
68417074b3aSGirish Moodalbail 		/*
68517074b3aSGirish Moodalbail 		 * We allow only one port to be added, removed or
68617074b3aSGirish Moodalbail 		 * assigned at a time.
68717074b3aSGirish Moodalbail 		 *
68817074b3aSGirish Moodalbail 		 * However on reboot, while initializing protocol
68917074b3aSGirish Moodalbail 		 * properties, extra_priv_ports might have multiple
69017074b3aSGirish Moodalbail 		 * values. Only in that case we allow setting multiple
69117074b3aSGirish Moodalbail 		 * values.
69217074b3aSGirish Moodalbail 		 */
69317074b3aSGirish Moodalbail 		nvlist_free(portsnvl);
6946e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
69517074b3aSGirish Moodalbail 	}
6966e91bba0SGirish Moodalbail 
6976e91bba0SGirish Moodalbail 	for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
6986e91bba0SGirish Moodalbail 	    nvp = nvlist_next_nvpair(portsnvl, nvp)) {
69917074b3aSGirish Moodalbail 		status = i_ipadm_set_prop(iph, arg, pdp, nvpair_name(nvp),
70017074b3aSGirish Moodalbail 		    proto, flags);
7016e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS)
7026e91bba0SGirish Moodalbail 			break;
7036e91bba0SGirish Moodalbail 	}
7046e91bba0SGirish Moodalbail 	nvlist_free(portsnvl);
7056e91bba0SGirish Moodalbail 	return (status);
7066e91bba0SGirish Moodalbail }
7076e91bba0SGirish Moodalbail 
7086e91bba0SGirish Moodalbail /* ARGSUSED */
7096e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_forwarding(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)7106e91bba0SGirish Moodalbail i_ipadm_set_forwarding(ipadm_handle_t iph, const void *arg,
7116e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
7126e91bba0SGirish Moodalbail {
7136e91bba0SGirish Moodalbail 	const char	*ifname = arg;
7146e91bba0SGirish Moodalbail 	ipadm_status_t	status;
7156e91bba0SGirish Moodalbail 
7166e91bba0SGirish Moodalbail 	/*
7176e91bba0SGirish Moodalbail 	 * if interface name is provided, then set forwarding using the
7186e91bba0SGirish Moodalbail 	 * IFF_ROUTER flag
7196e91bba0SGirish Moodalbail 	 */
7206e91bba0SGirish Moodalbail 	if (ifname != NULL) {
7216e91bba0SGirish Moodalbail 		status = i_ipadm_set_ifprop_flags(iph, ifname, pdp, pval,
7226e91bba0SGirish Moodalbail 		    proto, flags);
7236e91bba0SGirish Moodalbail 	} else {
7246e91bba0SGirish Moodalbail 		char	*val = NULL;
7256e91bba0SGirish Moodalbail 
7266e91bba0SGirish Moodalbail 		/*
7276e91bba0SGirish Moodalbail 		 * if the caller is IPH_LEGACY, `pval' already contains
7286e91bba0SGirish Moodalbail 		 * numeric values.
7296e91bba0SGirish Moodalbail 		 */
7306e91bba0SGirish Moodalbail 		if (!(flags & IPADM_OPT_DEFAULT) &&
7316e91bba0SGirish Moodalbail 		    !(iph->iph_flags & IPH_LEGACY)) {
7326e91bba0SGirish Moodalbail 
7336e91bba0SGirish Moodalbail 			if (strcmp(pval, IPADM_ONSTR) == 0)
7346e91bba0SGirish Moodalbail 				val = "1";
7356e91bba0SGirish Moodalbail 			else if (strcmp(pval, IPADM_OFFSTR) == 0)
7366e91bba0SGirish Moodalbail 				val = "0";
7376e91bba0SGirish Moodalbail 			else
7386e91bba0SGirish Moodalbail 				return (IPADM_INVALID_ARG);
7396e91bba0SGirish Moodalbail 			pval = val;
7406e91bba0SGirish Moodalbail 		}
7416e91bba0SGirish Moodalbail 
7426e91bba0SGirish Moodalbail 		status = i_ipadm_set_prop(iph, ifname, pdp, pval, proto, flags);
7436e91bba0SGirish Moodalbail 	}
7446e91bba0SGirish Moodalbail 
7456e91bba0SGirish Moodalbail 	return (status);
7466e91bba0SGirish Moodalbail }
7476e91bba0SGirish Moodalbail 
7486e91bba0SGirish Moodalbail /* ARGSUSED */
7496e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_ecnsack(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)7506e91bba0SGirish Moodalbail i_ipadm_set_ecnsack(ipadm_handle_t iph, const void *arg,
7516e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
7526e91bba0SGirish Moodalbail {
7536e91bba0SGirish Moodalbail 	uint_t		i;
7546e91bba0SGirish Moodalbail 	char		val[MAXPROPVALLEN];
7556e91bba0SGirish Moodalbail 
7566e91bba0SGirish Moodalbail 	/* if IPH_LEGACY is set, `pval' already contains numeric values */
7576e91bba0SGirish Moodalbail 	if (!(flags & IPADM_OPT_DEFAULT) && !(iph->iph_flags & IPH_LEGACY)) {
7586e91bba0SGirish Moodalbail 		for (i = 0; ecn_sack_vals[i] != NULL; i++) {
7596e91bba0SGirish Moodalbail 			if (strcmp(pval, ecn_sack_vals[i]) == 0)
7606e91bba0SGirish Moodalbail 				break;
7616e91bba0SGirish Moodalbail 		}
7626e91bba0SGirish Moodalbail 		if (ecn_sack_vals[i] == NULL)
7636e91bba0SGirish Moodalbail 			return (IPADM_INVALID_ARG);
7646e91bba0SGirish Moodalbail 		(void) snprintf(val, MAXPROPVALLEN, "%d", i);
7656e91bba0SGirish Moodalbail 		pval = val;
7666e91bba0SGirish Moodalbail 	}
7676e91bba0SGirish Moodalbail 
7686e91bba0SGirish Moodalbail 	return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
7696e91bba0SGirish Moodalbail }
7706e91bba0SGirish Moodalbail 
7716e91bba0SGirish Moodalbail /* ARGSUSED */
7726e91bba0SGirish Moodalbail ipadm_status_t
i_ipadm_get_ecnsack(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)7736e91bba0SGirish Moodalbail i_ipadm_get_ecnsack(ipadm_handle_t iph, const void *arg,
7746e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
7756e91bba0SGirish Moodalbail     uint_t valtype)
7766e91bba0SGirish Moodalbail {
7776e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
7786e91bba0SGirish Moodalbail 	uint_t		i, nbytes = 0;
7796e91bba0SGirish Moodalbail 
7806e91bba0SGirish Moodalbail 	switch (valtype) {
7816e91bba0SGirish Moodalbail 	case MOD_PROP_POSSIBLE:
7826e91bba0SGirish Moodalbail 		for (i = 0; ecn_sack_vals[i] != NULL; i++) {
7836e91bba0SGirish Moodalbail 			if (i == 0)
7846e91bba0SGirish Moodalbail 				nbytes += snprintf(buf + nbytes,
7856e91bba0SGirish Moodalbail 				    *bufsize - nbytes, "%s", ecn_sack_vals[i]);
7866e91bba0SGirish Moodalbail 			else
7876e91bba0SGirish Moodalbail 				nbytes += snprintf(buf + nbytes,
7886e91bba0SGirish Moodalbail 				    *bufsize - nbytes, ",%s", ecn_sack_vals[i]);
7896e91bba0SGirish Moodalbail 			if (nbytes >= *bufsize)
7906e91bba0SGirish Moodalbail 				break;
7916e91bba0SGirish Moodalbail 		}
7926e91bba0SGirish Moodalbail 		break;
7936e91bba0SGirish Moodalbail 	case MOD_PROP_PERM:
7946e91bba0SGirish Moodalbail 	case MOD_PROP_DEFAULT:
7956e91bba0SGirish Moodalbail 	case MOD_PROP_ACTIVE:
7966e91bba0SGirish Moodalbail 		status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
7976e91bba0SGirish Moodalbail 		    valtype);
7986e91bba0SGirish Moodalbail 
7996e91bba0SGirish Moodalbail 		/*
8006e91bba0SGirish Moodalbail 		 * If IPH_LEGACY is set, do not convert the value returned
8016e91bba0SGirish Moodalbail 		 * from kernel,
8026e91bba0SGirish Moodalbail 		 */
8036e91bba0SGirish Moodalbail 		if (iph->iph_flags & IPH_LEGACY)
8046e91bba0SGirish Moodalbail 			break;
8056e91bba0SGirish Moodalbail 
8066e91bba0SGirish Moodalbail 		/*
8076e91bba0SGirish Moodalbail 		 * For current and default value, convert the value returned
8086e91bba0SGirish Moodalbail 		 * from kernel to more discrete representation.
8096e91bba0SGirish Moodalbail 		 */
8106e91bba0SGirish Moodalbail 		if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
8116e91bba0SGirish Moodalbail 		    valtype == MOD_PROP_DEFAULT)) {
8126e91bba0SGirish Moodalbail 			i = atoi(buf);
8136e91bba0SGirish Moodalbail 			assert(i < 3);
8146e91bba0SGirish Moodalbail 			nbytes = snprintf(buf, *bufsize, "%s",
8156e91bba0SGirish Moodalbail 			    ecn_sack_vals[i]);
8166e91bba0SGirish Moodalbail 		}
8176e91bba0SGirish Moodalbail 		break;
8186e91bba0SGirish Moodalbail 	default:
8196e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
8206e91bba0SGirish Moodalbail 	}
8216e91bba0SGirish Moodalbail 	if (nbytes >= *bufsize) {
8226e91bba0SGirish Moodalbail 		/* insufficient buffer space */
8236e91bba0SGirish Moodalbail 		*bufsize = nbytes + 1;
8246e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
8256e91bba0SGirish Moodalbail 	}
8266e91bba0SGirish Moodalbail 
8276e91bba0SGirish Moodalbail 	return (status);
8286e91bba0SGirish Moodalbail }
8296e91bba0SGirish Moodalbail 
8306e91bba0SGirish Moodalbail /* ARGSUSED */
8316e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_forwarding(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)8326e91bba0SGirish Moodalbail i_ipadm_get_forwarding(ipadm_handle_t iph, const void *arg,
8336e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
8346e91bba0SGirish Moodalbail     uint_t valtype)
8356e91bba0SGirish Moodalbail {
8366e91bba0SGirish Moodalbail 	const char	*ifname = arg;
8376e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
8386e91bba0SGirish Moodalbail 
8396e91bba0SGirish Moodalbail 	/*
8406e91bba0SGirish Moodalbail 	 * if interface name is provided, then get forwarding status using
8416e91bba0SGirish Moodalbail 	 * SIOCGLIFFLAGS
8426e91bba0SGirish Moodalbail 	 */
8436e91bba0SGirish Moodalbail 	if (ifname != NULL) {
8446e91bba0SGirish Moodalbail 		status = i_ipadm_get_ifprop_flags(iph, ifname, pdp,
8456e91bba0SGirish Moodalbail 		    buf, bufsize, pdp->ipd_proto, valtype);
8466e91bba0SGirish Moodalbail 	} else {
8476e91bba0SGirish Moodalbail 		status = i_ipadm_get_prop(iph, ifname, pdp, buf,
8486e91bba0SGirish Moodalbail 		    bufsize, proto, valtype);
8496e91bba0SGirish Moodalbail 		/*
8506e91bba0SGirish Moodalbail 		 * If IPH_LEGACY is set, do not convert the value returned
8516e91bba0SGirish Moodalbail 		 * from kernel,
8526e91bba0SGirish Moodalbail 		 */
8536e91bba0SGirish Moodalbail 		if (iph->iph_flags & IPH_LEGACY)
8546e91bba0SGirish Moodalbail 			goto ret;
8556e91bba0SGirish Moodalbail 		if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
8566e91bba0SGirish Moodalbail 		    valtype == MOD_PROP_DEFAULT)) {
8576e91bba0SGirish Moodalbail 			uint_t	val = atoi(buf);
8586e91bba0SGirish Moodalbail 
8596e91bba0SGirish Moodalbail 			(void) snprintf(buf, *bufsize,
8606e91bba0SGirish Moodalbail 			    (val == 1 ? IPADM_ONSTR : IPADM_OFFSTR));
8616e91bba0SGirish Moodalbail 		}
8626e91bba0SGirish Moodalbail 	}
8636e91bba0SGirish Moodalbail 
8646e91bba0SGirish Moodalbail ret:
8656e91bba0SGirish Moodalbail 	return (status);
8666e91bba0SGirish Moodalbail }
8676e91bba0SGirish Moodalbail 
8686e91bba0SGirish Moodalbail /* ARGSUSED */
8696e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_mtu(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)8706e91bba0SGirish Moodalbail i_ipadm_get_mtu(ipadm_handle_t iph, const void *arg,
8716e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
8726e91bba0SGirish Moodalbail     uint_t valtype)
8736e91bba0SGirish Moodalbail {
8746e91bba0SGirish Moodalbail 	struct lifreq	lifr;
8756e91bba0SGirish Moodalbail 	const char	*ifname = arg;
8766e91bba0SGirish Moodalbail 	size_t		nbytes;
8776e91bba0SGirish Moodalbail 	int		s;
8786e91bba0SGirish Moodalbail 
8796e91bba0SGirish Moodalbail 	switch (valtype) {
8806e91bba0SGirish Moodalbail 	case MOD_PROP_PERM:
8816e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
8826e91bba0SGirish Moodalbail 		break;
8836e91bba0SGirish Moodalbail 	case MOD_PROP_DEFAULT:
8846e91bba0SGirish Moodalbail 	case MOD_PROP_POSSIBLE:
8856e91bba0SGirish Moodalbail 		return (i_ipadm_get_prop(iph, arg, pdp, buf, bufsize,
8866e91bba0SGirish Moodalbail 		    proto, valtype));
8876e91bba0SGirish Moodalbail 	case MOD_PROP_ACTIVE:
8886e91bba0SGirish Moodalbail 		bzero(&lifr, sizeof (lifr));
8896e91bba0SGirish Moodalbail 		(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
8906e91bba0SGirish Moodalbail 		s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
8916e91bba0SGirish Moodalbail 
8926e91bba0SGirish Moodalbail 		if (ioctl(s, SIOCGLIFMTU, (caddr_t)&lifr) < 0)
8936e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
8946e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%u", lifr.lifr_mtu);
8956e91bba0SGirish Moodalbail 		break;
8966e91bba0SGirish Moodalbail 	default:
8976e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
8986e91bba0SGirish Moodalbail 	}
8996e91bba0SGirish Moodalbail 	if (nbytes >= *bufsize) {
9006e91bba0SGirish Moodalbail 		/* insufficient buffer space */
9016e91bba0SGirish Moodalbail 		*bufsize = nbytes + 1;
9026e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
9036e91bba0SGirish Moodalbail 	}
9046e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
9056e91bba0SGirish Moodalbail }
9066e91bba0SGirish Moodalbail 
9076e91bba0SGirish Moodalbail /* ARGSUSED */
9086e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_metric(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)9096e91bba0SGirish Moodalbail i_ipadm_get_metric(ipadm_handle_t iph, const void *arg,
9106e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
9116e91bba0SGirish Moodalbail     uint_t valtype)
9126e91bba0SGirish Moodalbail {
9136e91bba0SGirish Moodalbail 	struct lifreq	lifr;
9146e91bba0SGirish Moodalbail 	const char	*ifname = arg;
9156e91bba0SGirish Moodalbail 	size_t		nbytes;
9166e91bba0SGirish Moodalbail 	int		s, val;
9176e91bba0SGirish Moodalbail 
9186e91bba0SGirish Moodalbail 	switch (valtype) {
9196e91bba0SGirish Moodalbail 	case MOD_PROP_PERM:
9206e91bba0SGirish Moodalbail 		val = MOD_PROP_PERM_RW;
9216e91bba0SGirish Moodalbail 		break;
9226e91bba0SGirish Moodalbail 	case MOD_PROP_DEFAULT:
9236e91bba0SGirish Moodalbail 		val = DEF_METRIC_VAL;
9246e91bba0SGirish Moodalbail 		break;
9256e91bba0SGirish Moodalbail 	case MOD_PROP_ACTIVE:
9266e91bba0SGirish Moodalbail 		bzero(&lifr, sizeof (lifr));
9276e91bba0SGirish Moodalbail 		(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
9286e91bba0SGirish Moodalbail 
9296e91bba0SGirish Moodalbail 		s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
9306e91bba0SGirish Moodalbail 		if (ioctl(s, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0)
9316e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
9326e91bba0SGirish Moodalbail 		val = lifr.lifr_metric;
9336e91bba0SGirish Moodalbail 		break;
9346e91bba0SGirish Moodalbail 	default:
9356e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
9366e91bba0SGirish Moodalbail 	}
9376e91bba0SGirish Moodalbail 	nbytes = snprintf(buf, *bufsize, "%d", val);
9386e91bba0SGirish Moodalbail 	if (nbytes >= *bufsize) {
9396e91bba0SGirish Moodalbail 		/* insufficient buffer space */
9406e91bba0SGirish Moodalbail 		*bufsize = nbytes + 1;
9416e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
9426e91bba0SGirish Moodalbail 	}
9436e91bba0SGirish Moodalbail 
9446e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
9456e91bba0SGirish Moodalbail }
9466e91bba0SGirish Moodalbail 
9476e91bba0SGirish Moodalbail /* ARGSUSED */
9486e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_usesrc(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * ipd,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)9496e91bba0SGirish Moodalbail i_ipadm_get_usesrc(ipadm_handle_t iph, const void *arg,
9506e91bba0SGirish Moodalbail     ipadm_prop_desc_t *ipd, char *buf, uint_t *bufsize, uint_t proto,
9516e91bba0SGirish Moodalbail     uint_t valtype)
9526e91bba0SGirish Moodalbail {
9536e91bba0SGirish Moodalbail 	struct lifreq	lifr;
9546e91bba0SGirish Moodalbail 	const char	*ifname = arg;
9556e91bba0SGirish Moodalbail 	int		s;
956*a73be61aSHans Rosenfeld 	char		if_name[IF_NAMESIZE];
9576e91bba0SGirish Moodalbail 	size_t		nbytes;
9586e91bba0SGirish Moodalbail 
9596e91bba0SGirish Moodalbail 	switch (valtype) {
9606e91bba0SGirish Moodalbail 	case MOD_PROP_PERM:
9616e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
9626e91bba0SGirish Moodalbail 		break;
9636e91bba0SGirish Moodalbail 	case MOD_PROP_DEFAULT:
9646e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%s", IPADM_NONESTR);
9656e91bba0SGirish Moodalbail 		break;
9666e91bba0SGirish Moodalbail 	case MOD_PROP_ACTIVE:
9676e91bba0SGirish Moodalbail 		bzero(&lifr, sizeof (lifr));
9686e91bba0SGirish Moodalbail 		(void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
9696e91bba0SGirish Moodalbail 
9706e91bba0SGirish Moodalbail 		s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
9716e91bba0SGirish Moodalbail 		if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
9726e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
9736e91bba0SGirish Moodalbail 		if (lifr.lifr_index == 0) {
9746e91bba0SGirish Moodalbail 			/* no src address was set, so print 'none' */
9756e91bba0SGirish Moodalbail 			(void) strlcpy(if_name, IPADM_NONESTR,
9766e91bba0SGirish Moodalbail 			    sizeof (if_name));
9776e91bba0SGirish Moodalbail 		} else if (if_indextoname(lifr.lifr_index, if_name) == NULL) {
9786e91bba0SGirish Moodalbail 			return (ipadm_errno2status(errno));
9796e91bba0SGirish Moodalbail 		}
9806e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%s", if_name);
9816e91bba0SGirish Moodalbail 		break;
9826e91bba0SGirish Moodalbail 	default:
9836e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
9846e91bba0SGirish Moodalbail 	}
9856e91bba0SGirish Moodalbail 	if (nbytes >= *bufsize) {
9866e91bba0SGirish Moodalbail 		/* insufficient buffer space */
9876e91bba0SGirish Moodalbail 		*bufsize = nbytes + 1;
9886e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
9896e91bba0SGirish Moodalbail 	}
9906e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
9916e91bba0SGirish Moodalbail }
9926e91bba0SGirish Moodalbail 
9936e91bba0SGirish Moodalbail /* ARGSUSED */
9946e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_ifprop_flags(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)9956e91bba0SGirish Moodalbail i_ipadm_get_ifprop_flags(ipadm_handle_t iph, const void *arg,
9966e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
9976e91bba0SGirish Moodalbail     uint_t valtype)
9986e91bba0SGirish Moodalbail {
999*a73be61aSHans Rosenfeld 	uint64_t	intf_flags;
1000*a73be61aSHans Rosenfeld 	char		*val;
10016e91bba0SGirish Moodalbail 	size_t		nbytes;
10026e91bba0SGirish Moodalbail 	const char	*ifname = arg;
10036e91bba0SGirish Moodalbail 	sa_family_t	af;
10046e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
10056e91bba0SGirish Moodalbail 
10066e91bba0SGirish Moodalbail 	switch (valtype) {
10076e91bba0SGirish Moodalbail 	case MOD_PROP_PERM:
10086e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
10096e91bba0SGirish Moodalbail 		break;
10106e91bba0SGirish Moodalbail 	case MOD_PROP_DEFAULT:
10116e91bba0SGirish Moodalbail 		if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
10126e91bba0SGirish Moodalbail 		    strcmp(pdp->ipd_name, "arp") == 0 ||
10136e91bba0SGirish Moodalbail 		    strcmp(pdp->ipd_name, "nud") == 0) {
10146e91bba0SGirish Moodalbail 			val = IPADM_ONSTR;
1015*a73be61aSHans Rosenfeld 		} else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
1016*a73be61aSHans Rosenfeld 		    strcmp(pdp->ipd_name, "standby") == 0) {
10176e91bba0SGirish Moodalbail 			val = IPADM_OFFSTR;
10186e91bba0SGirish Moodalbail 		} else {
10196e91bba0SGirish Moodalbail 			return (IPADM_PROP_UNKNOWN);
10206e91bba0SGirish Moodalbail 		}
10216e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%s", val);
10226e91bba0SGirish Moodalbail 		break;
10236e91bba0SGirish Moodalbail 	case MOD_PROP_ACTIVE:
10246e91bba0SGirish Moodalbail 		af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
10256e91bba0SGirish Moodalbail 		status = i_ipadm_get_flags(iph, ifname, af, &intf_flags);
10266e91bba0SGirish Moodalbail 		if (status != IPADM_SUCCESS)
10276e91bba0SGirish Moodalbail 			return (status);
10286e91bba0SGirish Moodalbail 
10296e91bba0SGirish Moodalbail 		val = IPADM_OFFSTR;
10306e91bba0SGirish Moodalbail 		if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
10316e91bba0SGirish Moodalbail 			if (!(intf_flags & IFF_NORTEXCH))
10326e91bba0SGirish Moodalbail 				val = IPADM_ONSTR;
10336e91bba0SGirish Moodalbail 		} else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
10346e91bba0SGirish Moodalbail 			if (intf_flags & IFF_ROUTER)
10356e91bba0SGirish Moodalbail 				val = IPADM_ONSTR;
10366e91bba0SGirish Moodalbail 		} else if (strcmp(pdp->ipd_name, "arp") == 0) {
10376e91bba0SGirish Moodalbail 			if (!(intf_flags & IFF_NOARP))
10386e91bba0SGirish Moodalbail 				val = IPADM_ONSTR;
10396e91bba0SGirish Moodalbail 		} else if (strcmp(pdp->ipd_name, "nud") == 0) {
10406e91bba0SGirish Moodalbail 			if (!(intf_flags & IFF_NONUD))
10416e91bba0SGirish Moodalbail 				val = IPADM_ONSTR;
1042*a73be61aSHans Rosenfeld 		} else if (strcmp(pdp->ipd_name, "standby") == 0) {
1043*a73be61aSHans Rosenfeld 			if (intf_flags & IFF_STANDBY)
1044*a73be61aSHans Rosenfeld 				val = IPADM_ONSTR;
10456e91bba0SGirish Moodalbail 		}
10466e91bba0SGirish Moodalbail 		nbytes = snprintf(buf, *bufsize, "%s", val);
10476e91bba0SGirish Moodalbail 		break;
10486e91bba0SGirish Moodalbail 	default:
10496e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
10506e91bba0SGirish Moodalbail 	}
10516e91bba0SGirish Moodalbail 	if (nbytes >= *bufsize) {
10526e91bba0SGirish Moodalbail 		/* insufficient buffer space */
10536e91bba0SGirish Moodalbail 		*bufsize = nbytes + 1;
10546e91bba0SGirish Moodalbail 		status = IPADM_NO_BUFS;
10556e91bba0SGirish Moodalbail 	}
10566e91bba0SGirish Moodalbail 
10576e91bba0SGirish Moodalbail 	return (status);
10586e91bba0SGirish Moodalbail }
10596e91bba0SGirish Moodalbail 
10606e91bba0SGirish Moodalbail static void
i_ipadm_perm2str(char * buf,uint_t * bufsize)10616e91bba0SGirish Moodalbail i_ipadm_perm2str(char *buf, uint_t *bufsize)
10626e91bba0SGirish Moodalbail {
10636e91bba0SGirish Moodalbail 	uint_t perm = atoi(buf);
10646e91bba0SGirish Moodalbail 
10656e91bba0SGirish Moodalbail 	(void) snprintf(buf, *bufsize, "%c%c",
10666e91bba0SGirish Moodalbail 	    ((perm & MOD_PROP_PERM_READ) != 0) ? 'r' : '-',
10676e91bba0SGirish Moodalbail 	    ((perm & MOD_PROP_PERM_WRITE) != 0) ? 'w' : '-');
10686e91bba0SGirish Moodalbail }
10696e91bba0SGirish Moodalbail 
10706e91bba0SGirish Moodalbail /* ARGSUSED */
10716e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_get_prop(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)10726e91bba0SGirish Moodalbail i_ipadm_get_prop(ipadm_handle_t iph, const void *arg,
10736e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
10746e91bba0SGirish Moodalbail     uint_t valtype)
10756e91bba0SGirish Moodalbail {
10766e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
10776e91bba0SGirish Moodalbail 	const char	*ifname = arg;
10786e91bba0SGirish Moodalbail 	mod_ioc_prop_t	*mip;
1079*a73be61aSHans Rosenfeld 	char		*pname = pdp->ipd_name;
10806e91bba0SGirish Moodalbail 	uint_t		iocsize;
10816e91bba0SGirish Moodalbail 
10826e91bba0SGirish Moodalbail 	/* allocate sufficient ioctl buffer to retrieve value */
10836e91bba0SGirish Moodalbail 	iocsize = sizeof (mod_ioc_prop_t) + *bufsize - 1;
10846e91bba0SGirish Moodalbail 	if ((mip = calloc(1, iocsize)) == NULL)
10856e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
10866e91bba0SGirish Moodalbail 
10876e91bba0SGirish Moodalbail 	mip->mpr_version = MOD_PROP_VERSION;
10886e91bba0SGirish Moodalbail 	mip->mpr_flags = valtype;
10896e91bba0SGirish Moodalbail 	mip->mpr_proto = proto;
10906e91bba0SGirish Moodalbail 	if (ifname != NULL) {
10916e91bba0SGirish Moodalbail 		(void) strlcpy(mip->mpr_ifname, ifname,
10926e91bba0SGirish Moodalbail 		    sizeof (mip->mpr_ifname));
10936e91bba0SGirish Moodalbail 	}
10946e91bba0SGirish Moodalbail 	(void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
10956e91bba0SGirish Moodalbail 	mip->mpr_valsize = *bufsize;
10966e91bba0SGirish Moodalbail 
10976e91bba0SGirish Moodalbail 	if (i_ipadm_strioctl(iph->iph_sock, SIOCGETPROP, (char *)mip,
10986e91bba0SGirish Moodalbail 	    iocsize) < 0) {
10996e91bba0SGirish Moodalbail 		if (errno == ENOENT)
11006e91bba0SGirish Moodalbail 			status = IPADM_PROP_UNKNOWN;
11016e91bba0SGirish Moodalbail 		else
11026e91bba0SGirish Moodalbail 			status = ipadm_errno2status(errno);
11036e91bba0SGirish Moodalbail 	} else {
11046e91bba0SGirish Moodalbail 		bcopy(mip->mpr_val, buf, *bufsize);
11056e91bba0SGirish Moodalbail 	}
11066e91bba0SGirish Moodalbail 
11076e91bba0SGirish Moodalbail 	free(mip);
11086e91bba0SGirish Moodalbail 	return (status);
11096e91bba0SGirish Moodalbail }
11106e91bba0SGirish Moodalbail 
11116e91bba0SGirish Moodalbail /*
11128887b57dSGirish Moodalbail  * Populates the ipmgmt_prop_arg_t based on the class of property.
11138887b57dSGirish Moodalbail  *
11148887b57dSGirish Moodalbail  * For private protocol properties, while persisting information in ipadm
11158887b57dSGirish Moodalbail  * data store, to ensure there is no collision of namespace between ipadm
11168887b57dSGirish Moodalbail  * private nvpair names (which also starts with '_', see ipadm_ipmgmt.h)
11178887b57dSGirish Moodalbail  * and private protocol property names, we will prepend IPADM_PRIV_PROP_PREFIX
11188887b57dSGirish Moodalbail  * to property names.
11196e91bba0SGirish Moodalbail  */
11206e91bba0SGirish Moodalbail static void
i_ipadm_populate_proparg(ipmgmt_prop_arg_t * pargp,ipadm_prop_desc_t * pdp,const char * pval,const void * object)11216e91bba0SGirish Moodalbail i_ipadm_populate_proparg(ipmgmt_prop_arg_t *pargp, ipadm_prop_desc_t *pdp,
11226e91bba0SGirish Moodalbail     const char *pval, const void *object)
11236e91bba0SGirish Moodalbail {
11246e91bba0SGirish Moodalbail 	const struct ipadm_addrobj_s *ipaddr;
11256e91bba0SGirish Moodalbail 	uint_t		class = pdp->ipd_class;
11266e91bba0SGirish Moodalbail 	uint_t		proto = pdp->ipd_proto;
11276e91bba0SGirish Moodalbail 
11286e91bba0SGirish Moodalbail 	(void) strlcpy(pargp->ia_pname, pdp->ipd_name,
11296e91bba0SGirish Moodalbail 	    sizeof (pargp->ia_pname));
11306e91bba0SGirish Moodalbail 	if (pval != NULL)
11316e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_pval, pval, sizeof (pargp->ia_pval));
11326e91bba0SGirish Moodalbail 
11336e91bba0SGirish Moodalbail 	switch (class) {
11346e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_MODULE:
11358887b57dSGirish Moodalbail 		/* if it's a private property then add the prefix. */
11368887b57dSGirish Moodalbail 		if (pdp->ipd_name[0] == '_') {
11378887b57dSGirish Moodalbail 			(void) snprintf(pargp->ia_pname,
11388887b57dSGirish Moodalbail 			    sizeof (pargp->ia_pname), "_%s", pdp->ipd_name);
11398887b57dSGirish Moodalbail 		}
11406e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_module, object,
11416e91bba0SGirish Moodalbail 		    sizeof (pargp->ia_module));
11426e91bba0SGirish Moodalbail 		break;
11436e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_MODIF:
11446e91bba0SGirish Moodalbail 		/* check if object is protostr or an ifname */
11456e91bba0SGirish Moodalbail 		if (ipadm_str2proto(object) != MOD_PROTO_NONE) {
11466e91bba0SGirish Moodalbail 			(void) strlcpy(pargp->ia_module, object,
11476e91bba0SGirish Moodalbail 			    sizeof (pargp->ia_module));
11486e91bba0SGirish Moodalbail 			break;
11496e91bba0SGirish Moodalbail 		}
11506e91bba0SGirish Moodalbail 		/* it's an interface property, fall through */
11516e91bba0SGirish Moodalbail 		/* FALLTHRU */
11526e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_IF:
11536e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_ifname, object,
11546e91bba0SGirish Moodalbail 		    sizeof (pargp->ia_ifname));
11556e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_module, ipadm_proto2str(proto),
11566e91bba0SGirish Moodalbail 		    sizeof (pargp->ia_module));
11576e91bba0SGirish Moodalbail 		break;
11586e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_ADDR:
11596e91bba0SGirish Moodalbail 		ipaddr = object;
11606e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_ifname, ipaddr->ipadm_ifname,
11616e91bba0SGirish Moodalbail 		    sizeof (pargp->ia_ifname));
11626e91bba0SGirish Moodalbail 		(void) strlcpy(pargp->ia_aobjname, ipaddr->ipadm_aobjname,
11636e91bba0SGirish Moodalbail 		    sizeof (pargp->ia_aobjname));
11646e91bba0SGirish Moodalbail 		break;
11656e91bba0SGirish Moodalbail 	}
11666e91bba0SGirish Moodalbail }
11676e91bba0SGirish Moodalbail 
11686e91bba0SGirish Moodalbail /*
11696e91bba0SGirish Moodalbail  * Common function to retrieve property value for a given interface `ifname' or
11706e91bba0SGirish Moodalbail  * for a given protocol `proto'. The property name is in `pname'.
11716e91bba0SGirish Moodalbail  *
11726e91bba0SGirish Moodalbail  * `valtype' determines the type of value that will be retrieved.
1173*a73be61aSHans Rosenfeld  *	IPADM_OPT_ACTIVE -	current value of the property (active config)
11746e91bba0SGirish Moodalbail  *	IPADM_OPT_PERSIST -	value of the property from persistent store
11756e91bba0SGirish Moodalbail  *	IPADM_OPT_DEFAULT -	default hard coded value (boot-time value)
11766e91bba0SGirish Moodalbail  *	IPADM_OPT_PERM -	read/write permissions for the value
11776e91bba0SGirish Moodalbail  *	IPADM_OPT_POSSIBLE -	range of values
11786e91bba0SGirish Moodalbail  */
11796e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_getprop_common(ipadm_handle_t iph,const char * ifname,const char * pname,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)11806e91bba0SGirish Moodalbail i_ipadm_getprop_common(ipadm_handle_t iph, const char *ifname,
11816e91bba0SGirish Moodalbail     const char *pname, char *buf, uint_t *bufsize, uint_t proto,
11826e91bba0SGirish Moodalbail     uint_t valtype)
11836e91bba0SGirish Moodalbail {
11846e91bba0SGirish Moodalbail 	ipadm_status_t		status = IPADM_SUCCESS;
11858887b57dSGirish Moodalbail 	ipadm_prop_desc_t	*pdp;
11866e91bba0SGirish Moodalbail 	char			priv_propname[MAXPROPNAMELEN];
11876e91bba0SGirish Moodalbail 	boolean_t		is_if = (ifname != NULL);
11888887b57dSGirish Moodalbail 	int			err = 0;
11896e91bba0SGirish Moodalbail 
11908887b57dSGirish Moodalbail 	pdp = i_ipadm_get_prop_desc(pname, proto, &err);
11918887b57dSGirish Moodalbail 	if (err == EPROTO)
11928887b57dSGirish Moodalbail 		return (IPADM_BAD_PROTOCOL);
11938887b57dSGirish Moodalbail 	/* there are no private interface properties */
11948887b57dSGirish Moodalbail 	if (is_if && err == ENOENT)
11958887b57dSGirish Moodalbail 		return (IPADM_PROP_UNKNOWN);
11966e91bba0SGirish Moodalbail 
11978887b57dSGirish Moodalbail 	if (pdp != NULL) {
11986e91bba0SGirish Moodalbail 		/*
11996e91bba0SGirish Moodalbail 		 * check whether the property can be
12006e91bba0SGirish Moodalbail 		 * applied on an interface
12016e91bba0SGirish Moodalbail 		 */
12026e91bba0SGirish Moodalbail 		if (is_if && !(pdp->ipd_class & IPADMPROP_CLASS_IF))
12036e91bba0SGirish Moodalbail 			return (IPADM_INVALID_ARG);
12046e91bba0SGirish Moodalbail 		/*
12056e91bba0SGirish Moodalbail 		 * check whether the property can be
12066e91bba0SGirish Moodalbail 		 * applied on a module
12076e91bba0SGirish Moodalbail 		 */
12086e91bba0SGirish Moodalbail 		if (!is_if && !(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
12096e91bba0SGirish Moodalbail 			return (IPADM_INVALID_ARG);
12106e91bba0SGirish Moodalbail 
12116e91bba0SGirish Moodalbail 	} else {
12126e91bba0SGirish Moodalbail 		/* private protocol properties, pass it to kernel directly */
12136e91bba0SGirish Moodalbail 		pdp = &ipadm_privprop;
12146e91bba0SGirish Moodalbail 		(void) strlcpy(priv_propname, pname, sizeof (priv_propname));
12156e91bba0SGirish Moodalbail 		pdp->ipd_name = priv_propname;
12166e91bba0SGirish Moodalbail 	}
12176e91bba0SGirish Moodalbail 
12186e91bba0SGirish Moodalbail 	switch (valtype) {
12196e91bba0SGirish Moodalbail 	case IPADM_OPT_PERM:
12206e91bba0SGirish Moodalbail 		status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
12216e91bba0SGirish Moodalbail 		    MOD_PROP_PERM);
12226e91bba0SGirish Moodalbail 		if (status == IPADM_SUCCESS)
12236e91bba0SGirish Moodalbail 			i_ipadm_perm2str(buf, bufsize);
12246e91bba0SGirish Moodalbail 		break;
12256e91bba0SGirish Moodalbail 	case IPADM_OPT_ACTIVE:
12266e91bba0SGirish Moodalbail 		status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
12276e91bba0SGirish Moodalbail 		    MOD_PROP_ACTIVE);
12286e91bba0SGirish Moodalbail 		break;
12296e91bba0SGirish Moodalbail 	case IPADM_OPT_DEFAULT:
12306e91bba0SGirish Moodalbail 		status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
12316e91bba0SGirish Moodalbail 		    MOD_PROP_DEFAULT);
12326e91bba0SGirish Moodalbail 		break;
12336e91bba0SGirish Moodalbail 	case IPADM_OPT_POSSIBLE:
12346e91bba0SGirish Moodalbail 		if (pdp->ipd_get_range != NULL) {
12356e91bba0SGirish Moodalbail 			status = pdp->ipd_get_range(iph, ifname, pdp, buf,
12366e91bba0SGirish Moodalbail 			    bufsize, proto, MOD_PROP_POSSIBLE);
12376e91bba0SGirish Moodalbail 			break;
12386e91bba0SGirish Moodalbail 		}
12396e91bba0SGirish Moodalbail 		buf[0] = '\0';
12406e91bba0SGirish Moodalbail 		break;
12416e91bba0SGirish Moodalbail 	case IPADM_OPT_PERSIST:
12426e91bba0SGirish Moodalbail 		/* retrieve from database */
12436e91bba0SGirish Moodalbail 		if (is_if)
12446e91bba0SGirish Moodalbail 			status = i_ipadm_get_persist_propval(iph, pdp, buf,
12456e91bba0SGirish Moodalbail 			    bufsize, ifname);
12466e91bba0SGirish Moodalbail 		else
12476e91bba0SGirish Moodalbail 			status = i_ipadm_get_persist_propval(iph, pdp, buf,
12486e91bba0SGirish Moodalbail 			    bufsize, ipadm_proto2str(proto));
12496e91bba0SGirish Moodalbail 		break;
12506e91bba0SGirish Moodalbail 	default:
12516e91bba0SGirish Moodalbail 		status = IPADM_INVALID_ARG;
12526e91bba0SGirish Moodalbail 		break;
12536e91bba0SGirish Moodalbail 	}
12546e91bba0SGirish Moodalbail 	return (status);
12556e91bba0SGirish Moodalbail }
12566e91bba0SGirish Moodalbail 
12576e91bba0SGirish Moodalbail /*
12586e91bba0SGirish Moodalbail  * Get protocol property of the specified protocol.
12596e91bba0SGirish Moodalbail  */
12606e91bba0SGirish Moodalbail ipadm_status_t
ipadm_get_prop(ipadm_handle_t iph,const char * pname,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)12616e91bba0SGirish Moodalbail ipadm_get_prop(ipadm_handle_t iph, const char *pname, char *buf,
12626e91bba0SGirish Moodalbail     uint_t *bufsize, uint_t proto, uint_t valtype)
12636e91bba0SGirish Moodalbail {
12646e91bba0SGirish Moodalbail 	/*
12656e91bba0SGirish Moodalbail 	 * validate the arguments of the function.
12666e91bba0SGirish Moodalbail 	 */
12676e91bba0SGirish Moodalbail 	if (iph == NULL || pname == NULL || buf == NULL ||
12686e91bba0SGirish Moodalbail 	    bufsize == NULL || *bufsize == 0) {
12696e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
12706e91bba0SGirish Moodalbail 	}
12716e91bba0SGirish Moodalbail 	/*
12726e91bba0SGirish Moodalbail 	 * Do we support this proto, if not return error.
12736e91bba0SGirish Moodalbail 	 */
12746e91bba0SGirish Moodalbail 	if (ipadm_proto2str(proto) == NULL)
12756e91bba0SGirish Moodalbail 		return (IPADM_NOTSUP);
12766e91bba0SGirish Moodalbail 
12776e91bba0SGirish Moodalbail 	return (i_ipadm_getprop_common(iph, NULL, pname, buf, bufsize,
12786e91bba0SGirish Moodalbail 	    proto, valtype));
12796e91bba0SGirish Moodalbail }
12806e91bba0SGirish Moodalbail 
12816e91bba0SGirish Moodalbail /*
12826e91bba0SGirish Moodalbail  * Get interface property of the specified interface.
12836e91bba0SGirish Moodalbail  */
12846e91bba0SGirish Moodalbail ipadm_status_t
ipadm_get_ifprop(ipadm_handle_t iph,const char * ifname,const char * pname,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)12856e91bba0SGirish Moodalbail ipadm_get_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
12866e91bba0SGirish Moodalbail     char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
12876e91bba0SGirish Moodalbail {
12886e91bba0SGirish Moodalbail 	/* validate the arguments of the function. */
12896e91bba0SGirish Moodalbail 	if (iph == NULL || pname == NULL || buf == NULL ||
12906e91bba0SGirish Moodalbail 	    bufsize == NULL || *bufsize == 0) {
12916e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
12926e91bba0SGirish Moodalbail 	}
12936e91bba0SGirish Moodalbail 
12946e91bba0SGirish Moodalbail 	/* Do we support this proto, if not return error. */
12956e91bba0SGirish Moodalbail 	if (ipadm_proto2str(proto) == NULL)
12966e91bba0SGirish Moodalbail 		return (IPADM_NOTSUP);
12976e91bba0SGirish Moodalbail 
12986e91bba0SGirish Moodalbail 	/*
12996e91bba0SGirish Moodalbail 	 * check if interface name is provided for interface property and
13006e91bba0SGirish Moodalbail 	 * is valid.
13016e91bba0SGirish Moodalbail 	 */
13026e91bba0SGirish Moodalbail 	if (!i_ipadm_validate_ifname(iph, ifname))
13036e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
13046e91bba0SGirish Moodalbail 
13056e91bba0SGirish Moodalbail 	return (i_ipadm_getprop_common(iph, ifname, pname, buf, bufsize,
13066e91bba0SGirish Moodalbail 	    proto, valtype));
13076e91bba0SGirish Moodalbail }
13086e91bba0SGirish Moodalbail 
13096e91bba0SGirish Moodalbail /*
13106e91bba0SGirish Moodalbail  * Allocates sufficient ioctl buffers and copies property name and the
13116e91bba0SGirish Moodalbail  * value, among other things. If the flag IPADM_OPT_DEFAULT is set, then
13126e91bba0SGirish Moodalbail  * `pval' will be NULL and it instructs the kernel to reset the current
13136e91bba0SGirish Moodalbail  * value to property's default value.
13146e91bba0SGirish Moodalbail  */
13156e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_set_prop(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * pdp,const void * pval,uint_t proto,uint_t flags)13166e91bba0SGirish Moodalbail i_ipadm_set_prop(ipadm_handle_t iph, const void *arg,
13176e91bba0SGirish Moodalbail     ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
13186e91bba0SGirish Moodalbail {
13196e91bba0SGirish Moodalbail 	ipadm_status_t	status = IPADM_SUCCESS;
13206e91bba0SGirish Moodalbail 	const char	*ifname = arg;
1321*a73be61aSHans Rosenfeld 	mod_ioc_prop_t	*mip;
1322*a73be61aSHans Rosenfeld 	char		*pname = pdp->ipd_name;
1323*a73be61aSHans Rosenfeld 	uint_t		valsize, iocsize;
13246e91bba0SGirish Moodalbail 	uint_t		iocflags = 0;
13256e91bba0SGirish Moodalbail 
13266e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_DEFAULT) {
13276e91bba0SGirish Moodalbail 		iocflags |= MOD_PROP_DEFAULT;
13286e91bba0SGirish Moodalbail 	} else if (flags & IPADM_OPT_ACTIVE) {
13296e91bba0SGirish Moodalbail 		iocflags |= MOD_PROP_ACTIVE;
13306e91bba0SGirish Moodalbail 		if (flags & IPADM_OPT_APPEND)
13316e91bba0SGirish Moodalbail 			iocflags |= MOD_PROP_APPEND;
13326e91bba0SGirish Moodalbail 		else if (flags & IPADM_OPT_REMOVE)
13336e91bba0SGirish Moodalbail 			iocflags |= MOD_PROP_REMOVE;
13346e91bba0SGirish Moodalbail 	}
13356e91bba0SGirish Moodalbail 
13366e91bba0SGirish Moodalbail 	if (pval != NULL) {
13376e91bba0SGirish Moodalbail 		valsize = strlen(pval);
13386e91bba0SGirish Moodalbail 		iocsize = sizeof (mod_ioc_prop_t) + valsize - 1;
13396e91bba0SGirish Moodalbail 	} else {
13406e91bba0SGirish Moodalbail 		valsize = 0;
13416e91bba0SGirish Moodalbail 		iocsize = sizeof (mod_ioc_prop_t);
13426e91bba0SGirish Moodalbail 	}
13436e91bba0SGirish Moodalbail 
13446e91bba0SGirish Moodalbail 	if ((mip = calloc(1, iocsize)) == NULL)
13456e91bba0SGirish Moodalbail 		return (IPADM_NO_BUFS);
13466e91bba0SGirish Moodalbail 
13476e91bba0SGirish Moodalbail 	mip->mpr_version = MOD_PROP_VERSION;
13486e91bba0SGirish Moodalbail 	mip->mpr_flags = iocflags;
13496e91bba0SGirish Moodalbail 	mip->mpr_proto = proto;
13506e91bba0SGirish Moodalbail 	if (ifname != NULL) {
13516e91bba0SGirish Moodalbail 		(void) strlcpy(mip->mpr_ifname, ifname,
13526e91bba0SGirish Moodalbail 		    sizeof (mip->mpr_ifname));
13536e91bba0SGirish Moodalbail 	}
13546e91bba0SGirish Moodalbail 
13556e91bba0SGirish Moodalbail 	(void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
13566e91bba0SGirish Moodalbail 	mip->mpr_valsize = valsize;
13576e91bba0SGirish Moodalbail 	if (pval != NULL)
13586e91bba0SGirish Moodalbail 		bcopy(pval, mip->mpr_val, valsize);
13596e91bba0SGirish Moodalbail 
13606e91bba0SGirish Moodalbail 	if (i_ipadm_strioctl(iph->iph_sock, SIOCSETPROP, (char *)mip,
13616e91bba0SGirish Moodalbail 	    iocsize) < 0) {
13626e91bba0SGirish Moodalbail 		if (errno == ENOENT)
13636e91bba0SGirish Moodalbail 			status = IPADM_PROP_UNKNOWN;
13646e91bba0SGirish Moodalbail 		else
13656e91bba0SGirish Moodalbail 			status = ipadm_errno2status(errno);
13666e91bba0SGirish Moodalbail 	}
13676e91bba0SGirish Moodalbail 	free(mip);
13686e91bba0SGirish Moodalbail 	return (status);
13696e91bba0SGirish Moodalbail }
13706e91bba0SGirish Moodalbail 
13716e91bba0SGirish Moodalbail /*
13726e91bba0SGirish Moodalbail  * Common function for modifying both protocol/interface property.
13736e91bba0SGirish Moodalbail  *
13746e91bba0SGirish Moodalbail  * If:
13756e91bba0SGirish Moodalbail  *   IPADM_OPT_PERSIST is set then the value is persisted.
13766e91bba0SGirish Moodalbail  *   IPADM_OPT_DEFAULT is set then the default value for the property will
13776e91bba0SGirish Moodalbail  *		       be applied.
13786e91bba0SGirish Moodalbail  */
13796e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_setprop_common(ipadm_handle_t iph,const char * ifname,const char * pname,const char * buf,uint_t proto,uint_t pflags)13806e91bba0SGirish Moodalbail i_ipadm_setprop_common(ipadm_handle_t iph, const char *ifname,
13816e91bba0SGirish Moodalbail     const char *pname, const char *buf, uint_t proto, uint_t pflags)
13826e91bba0SGirish Moodalbail {
13836e91bba0SGirish Moodalbail 	ipadm_status_t		status = IPADM_SUCCESS;
1384*a73be61aSHans Rosenfeld 	boolean_t		persist = (pflags & IPADM_OPT_PERSIST);
13856e91bba0SGirish Moodalbail 	boolean_t		reset = (pflags & IPADM_OPT_DEFAULT);
13868887b57dSGirish Moodalbail 	ipadm_prop_desc_t	*pdp;
13876e91bba0SGirish Moodalbail 	boolean_t		is_if = (ifname != NULL);
13886e91bba0SGirish Moodalbail 	char			priv_propname[MAXPROPNAMELEN];
13898887b57dSGirish Moodalbail 	int			err = 0;
13906e91bba0SGirish Moodalbail 
13916e91bba0SGirish Moodalbail 	/* Check that property value is within the allowed size */
13926e91bba0SGirish Moodalbail 	if (!reset && strnlen(buf, MAXPROPVALLEN) >= MAXPROPVALLEN)
13936e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
13946e91bba0SGirish Moodalbail 
13958887b57dSGirish Moodalbail 	pdp = i_ipadm_get_prop_desc(pname, proto, &err);
13968887b57dSGirish Moodalbail 	if (err == EPROTO)
13978887b57dSGirish Moodalbail 		return (IPADM_BAD_PROTOCOL);
13988887b57dSGirish Moodalbail 	/* there are no private interface properties */
13998887b57dSGirish Moodalbail 	if (is_if && err == ENOENT)
14008887b57dSGirish Moodalbail 		return (IPADM_PROP_UNKNOWN);
14016e91bba0SGirish Moodalbail 
14028887b57dSGirish Moodalbail 	if (pdp != NULL) {
14036e91bba0SGirish Moodalbail 		/* do some sanity checks */
14046e91bba0SGirish Moodalbail 		if (is_if) {
14056e91bba0SGirish Moodalbail 			if (!(pdp->ipd_class & IPADMPROP_CLASS_IF))
14066e91bba0SGirish Moodalbail 				return (IPADM_INVALID_ARG);
14076e91bba0SGirish Moodalbail 		} else {
14086e91bba0SGirish Moodalbail 			if (!(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
14096e91bba0SGirish Moodalbail 				return (IPADM_INVALID_ARG);
14106e91bba0SGirish Moodalbail 		}
14118b88711aSGirish Moodalbail 		/*
14128b88711aSGirish Moodalbail 		 * if the property is not multi-valued and IPADM_OPT_APPEND or
14138b88711aSGirish Moodalbail 		 * IPADM_OPT_REMOVE is specified, return IPADM_INVALID_ARG.
14148b88711aSGirish Moodalbail 		 */
14158b88711aSGirish Moodalbail 		if (!(pdp->ipd_flags & IPADMPROP_MULVAL) && (pflags &
14168b88711aSGirish Moodalbail 		    (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
14178b88711aSGirish Moodalbail 			return (IPADM_INVALID_ARG);
14188b88711aSGirish Moodalbail 		}
14196e91bba0SGirish Moodalbail 	} else {
14208887b57dSGirish Moodalbail 		/* private protocol property, pass it to kernel directly */
14216e91bba0SGirish Moodalbail 		pdp = &ipadm_privprop;
14226e91bba0SGirish Moodalbail 		(void) strlcpy(priv_propname, pname, sizeof (priv_propname));
14236e91bba0SGirish Moodalbail 		pdp->ipd_name = priv_propname;
14246e91bba0SGirish Moodalbail 	}
14256e91bba0SGirish Moodalbail 
14266e91bba0SGirish Moodalbail 	status = pdp->ipd_set(iph, ifname, pdp, buf, proto, pflags);
14276e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
14286e91bba0SGirish Moodalbail 		return (status);
14296e91bba0SGirish Moodalbail 
14306e91bba0SGirish Moodalbail 	if (persist) {
14316e91bba0SGirish Moodalbail 		if (is_if)
14326e91bba0SGirish Moodalbail 			status = i_ipadm_persist_propval(iph, pdp, buf, ifname,
14336e91bba0SGirish Moodalbail 			    pflags);
14346e91bba0SGirish Moodalbail 		else
14356e91bba0SGirish Moodalbail 			status = i_ipadm_persist_propval(iph, pdp, buf,
14366e91bba0SGirish Moodalbail 			    ipadm_proto2str(proto), pflags);
14376e91bba0SGirish Moodalbail 	}
14386e91bba0SGirish Moodalbail 	return (status);
14396e91bba0SGirish Moodalbail }
14406e91bba0SGirish Moodalbail 
14416e91bba0SGirish Moodalbail /*
14426e91bba0SGirish Moodalbail  * Sets the property value of the specified interface
14436e91bba0SGirish Moodalbail  */
14446e91bba0SGirish Moodalbail ipadm_status_t
ipadm_set_ifprop(ipadm_handle_t iph,const char * ifname,const char * pname,const char * buf,uint_t proto,uint_t pflags)14456e91bba0SGirish Moodalbail ipadm_set_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
14466e91bba0SGirish Moodalbail     const char *buf, uint_t proto, uint_t pflags)
14476e91bba0SGirish Moodalbail {
14486e91bba0SGirish Moodalbail 	boolean_t	reset = (pflags & IPADM_OPT_DEFAULT);
14496e91bba0SGirish Moodalbail 	ipadm_status_t	status;
14506e91bba0SGirish Moodalbail 
14516e91bba0SGirish Moodalbail 	/* check for solaris.network.interface.config authorization */
14526e91bba0SGirish Moodalbail 	if (!ipadm_check_auth())
14536e91bba0SGirish Moodalbail 		return (IPADM_EAUTH);
14546e91bba0SGirish Moodalbail 	/*
14556e91bba0SGirish Moodalbail 	 * validate the arguments of the function.
14566e91bba0SGirish Moodalbail 	 */
14576e91bba0SGirish Moodalbail 	if (iph == NULL || pname == NULL || (!reset && buf == NULL) ||
14586e91bba0SGirish Moodalbail 	    pflags == 0 || pflags == IPADM_OPT_PERSIST ||
14596e91bba0SGirish Moodalbail 	    (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT))) {
14606e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
14616e91bba0SGirish Moodalbail 	}
14626e91bba0SGirish Moodalbail 
14636e91bba0SGirish Moodalbail 	/*
14646e91bba0SGirish Moodalbail 	 * Do we support this protocol, if not return error.
14656e91bba0SGirish Moodalbail 	 */
14666e91bba0SGirish Moodalbail 	if (ipadm_proto2str(proto) == NULL)
14676e91bba0SGirish Moodalbail 		return (IPADM_NOTSUP);
14686e91bba0SGirish Moodalbail 
14696e91bba0SGirish Moodalbail 	/*
14706e91bba0SGirish Moodalbail 	 * Validate the interface and check if a persistent
14716e91bba0SGirish Moodalbail 	 * operation is performed on a temporary object.
14726e91bba0SGirish Moodalbail 	 */
14736e91bba0SGirish Moodalbail 	status = i_ipadm_validate_if(iph, ifname, proto, pflags);
14746e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
14756e91bba0SGirish Moodalbail 		return (status);
14766e91bba0SGirish Moodalbail 
14776e91bba0SGirish Moodalbail 	return (i_ipadm_setprop_common(iph, ifname, pname, buf, proto,
14786e91bba0SGirish Moodalbail 	    pflags));
14796e91bba0SGirish Moodalbail }
14806e91bba0SGirish Moodalbail 
14816e91bba0SGirish Moodalbail /*
14826e91bba0SGirish Moodalbail  * Sets the property value of the specified protocol.
14836e91bba0SGirish Moodalbail  */
14846e91bba0SGirish Moodalbail ipadm_status_t
ipadm_set_prop(ipadm_handle_t iph,const char * pname,const char * buf,uint_t proto,uint_t pflags)14856e91bba0SGirish Moodalbail ipadm_set_prop(ipadm_handle_t iph, const char *pname, const char *buf,
14866e91bba0SGirish Moodalbail     uint_t proto, uint_t pflags)
14876e91bba0SGirish Moodalbail {
14886e91bba0SGirish Moodalbail 	boolean_t	reset = (pflags & IPADM_OPT_DEFAULT);
14896e91bba0SGirish Moodalbail 
14906e91bba0SGirish Moodalbail 	/* check for solaris.network.interface.config authorization */
14916e91bba0SGirish Moodalbail 	if (!ipadm_check_auth())
14926e91bba0SGirish Moodalbail 		return (IPADM_EAUTH);
14936e91bba0SGirish Moodalbail 	/*
14946e91bba0SGirish Moodalbail 	 * validate the arguments of the function.
14956e91bba0SGirish Moodalbail 	 */
14966e91bba0SGirish Moodalbail 	if (iph == NULL || pname == NULL ||(!reset && buf == NULL) ||
14976e91bba0SGirish Moodalbail 	    pflags == 0 || pflags == IPADM_OPT_PERSIST ||
14986e91bba0SGirish Moodalbail 	    (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT|
14996e91bba0SGirish Moodalbail 	    IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
15006e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
15016e91bba0SGirish Moodalbail 	}
15026e91bba0SGirish Moodalbail 
15036e91bba0SGirish Moodalbail 	/*
15046e91bba0SGirish Moodalbail 	 * Do we support this proto, if not return error.
15056e91bba0SGirish Moodalbail 	 */
15066e91bba0SGirish Moodalbail 	if (ipadm_proto2str(proto) == NULL)
15076e91bba0SGirish Moodalbail 		return (IPADM_NOTSUP);
15086e91bba0SGirish Moodalbail 
15096e91bba0SGirish Moodalbail 	return (i_ipadm_setprop_common(iph, NULL, pname, buf, proto,
15106e91bba0SGirish Moodalbail 	    pflags));
15116e91bba0SGirish Moodalbail }
15126e91bba0SGirish Moodalbail 
15136e91bba0SGirish Moodalbail /* helper function for ipadm_walk_proptbl */
15146e91bba0SGirish Moodalbail static void
i_ipadm_walk_proptbl(ipadm_prop_desc_t * pdtbl,uint_t proto,uint_t class,ipadm_prop_wfunc_t * func,void * arg)15156e91bba0SGirish Moodalbail i_ipadm_walk_proptbl(ipadm_prop_desc_t *pdtbl, uint_t proto, uint_t class,
15166e91bba0SGirish Moodalbail     ipadm_prop_wfunc_t *func, void *arg)
15176e91bba0SGirish Moodalbail {
15186e91bba0SGirish Moodalbail 	ipadm_prop_desc_t	*pdp;
15196e91bba0SGirish Moodalbail 
15206e91bba0SGirish Moodalbail 	for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
15216e91bba0SGirish Moodalbail 		if (!(pdp->ipd_class & class))
15226e91bba0SGirish Moodalbail 			continue;
15236e91bba0SGirish Moodalbail 
15246e91bba0SGirish Moodalbail 		if (proto != MOD_PROTO_NONE && !(pdp->ipd_proto & proto))
15256e91bba0SGirish Moodalbail 			continue;
15266e91bba0SGirish Moodalbail 
15276e91bba0SGirish Moodalbail 		/*
15286e91bba0SGirish Moodalbail 		 * we found a class specific match, call the
15296e91bba0SGirish Moodalbail 		 * user callback function.
15306e91bba0SGirish Moodalbail 		 */
15316e91bba0SGirish Moodalbail 		if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
15326e91bba0SGirish Moodalbail 			break;
15336e91bba0SGirish Moodalbail 	}
15346e91bba0SGirish Moodalbail }
15356e91bba0SGirish Moodalbail 
15366e91bba0SGirish Moodalbail /*
15376e91bba0SGirish Moodalbail  * Walks through all the properties, for a given protocol and property class
15386e91bba0SGirish Moodalbail  * (protocol or interface).
15396e91bba0SGirish Moodalbail  *
15406e91bba0SGirish Moodalbail  * Further if proto == MOD_PROTO_NONE, then it walks through all the supported
15416e91bba0SGirish Moodalbail  * protocol property tables.
15426e91bba0SGirish Moodalbail  */
15436e91bba0SGirish Moodalbail ipadm_status_t
ipadm_walk_proptbl(uint_t proto,uint_t class,ipadm_prop_wfunc_t * func,void * arg)15446e91bba0SGirish Moodalbail ipadm_walk_proptbl(uint_t proto, uint_t class, ipadm_prop_wfunc_t *func,
15456e91bba0SGirish Moodalbail     void *arg)
15466e91bba0SGirish Moodalbail {
15476e91bba0SGirish Moodalbail 	ipadm_prop_desc_t	*pdtbl;
15486e91bba0SGirish Moodalbail 	ipadm_status_t		status = IPADM_SUCCESS;
15496e91bba0SGirish Moodalbail 	int			i;
15506e91bba0SGirish Moodalbail 	int			count = A_CNT(protocols);
15516e91bba0SGirish Moodalbail 
15526e91bba0SGirish Moodalbail 	if (func == NULL)
15536e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
15546e91bba0SGirish Moodalbail 
15556e91bba0SGirish Moodalbail 	switch (class) {
15566e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_ADDR:
15576e91bba0SGirish Moodalbail 		pdtbl = ipadm_addrprop_table;
15586e91bba0SGirish Moodalbail 		break;
15596e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_IF:
15606e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_MODULE:
15616e91bba0SGirish Moodalbail 		pdtbl = i_ipadm_get_propdesc_table(proto);
15626e91bba0SGirish Moodalbail 		if (pdtbl == NULL && proto != MOD_PROTO_NONE)
15636e91bba0SGirish Moodalbail 			return (IPADM_INVALID_ARG);
15646e91bba0SGirish Moodalbail 		break;
15656e91bba0SGirish Moodalbail 	default:
15666e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
15676e91bba0SGirish Moodalbail 	}
15686e91bba0SGirish Moodalbail 
15696e91bba0SGirish Moodalbail 	if (pdtbl != NULL) {
15706e91bba0SGirish Moodalbail 		/*
15716e91bba0SGirish Moodalbail 		 * proto will be MOD_PROTO_NONE in the case of
15726e91bba0SGirish Moodalbail 		 * IPADMPROP_CLASS_ADDR.
15736e91bba0SGirish Moodalbail 		 */
15746e91bba0SGirish Moodalbail 		i_ipadm_walk_proptbl(pdtbl, proto, class, func, arg);
15756e91bba0SGirish Moodalbail 	} else {
15766e91bba0SGirish Moodalbail 		/* Walk thru all the protocol tables, we support */
15776e91bba0SGirish Moodalbail 		for (i = 0; i < count; i++) {
15786e91bba0SGirish Moodalbail 			pdtbl = i_ipadm_get_propdesc_table(protocols[i]);
15796e91bba0SGirish Moodalbail 			i_ipadm_walk_proptbl(pdtbl, protocols[i], class, func,
15806e91bba0SGirish Moodalbail 			    arg);
15816e91bba0SGirish Moodalbail 		}
15826e91bba0SGirish Moodalbail 	}
15836e91bba0SGirish Moodalbail 	return (status);
15846e91bba0SGirish Moodalbail }
15856e91bba0SGirish Moodalbail 
15866e91bba0SGirish Moodalbail /*
15876e91bba0SGirish Moodalbail  * Given a property name, walks through all the instances of a property name.
15886e91bba0SGirish Moodalbail  * Some properties have two instances one for v4 interfaces and another for v6
15896e91bba0SGirish Moodalbail  * interfaces. For example: MTU. MTU can have different values for v4 and v6.
15906e91bba0SGirish Moodalbail  * Therefore there are two properties for 'MTU'.
15916e91bba0SGirish Moodalbail  *
15926e91bba0SGirish Moodalbail  * This function invokes `func' for every instance of property `pname'
15936e91bba0SGirish Moodalbail  */
15946e91bba0SGirish Moodalbail ipadm_status_t
ipadm_walk_prop(const char * pname,uint_t proto,uint_t class,ipadm_prop_wfunc_t * func,void * arg)15956e91bba0SGirish Moodalbail ipadm_walk_prop(const char *pname, uint_t proto, uint_t class,
15966e91bba0SGirish Moodalbail     ipadm_prop_wfunc_t *func, void *arg)
15976e91bba0SGirish Moodalbail {
15986e91bba0SGirish Moodalbail 	ipadm_prop_desc_t	*pdtbl, *pdp;
15996e91bba0SGirish Moodalbail 	ipadm_status_t		status = IPADM_SUCCESS;
16006e91bba0SGirish Moodalbail 	boolean_t		matched = B_FALSE;
16016e91bba0SGirish Moodalbail 
16026e91bba0SGirish Moodalbail 	if (pname == NULL || func == NULL)
16036e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
16046e91bba0SGirish Moodalbail 
16056e91bba0SGirish Moodalbail 	switch (class) {
16066e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_ADDR:
16076e91bba0SGirish Moodalbail 		pdtbl = ipadm_addrprop_table;
16086e91bba0SGirish Moodalbail 		break;
16096e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_IF:
16106e91bba0SGirish Moodalbail 	case IPADMPROP_CLASS_MODULE:
16116e91bba0SGirish Moodalbail 		pdtbl = i_ipadm_get_propdesc_table(proto);
16126e91bba0SGirish Moodalbail 		break;
16136e91bba0SGirish Moodalbail 	default:
16146e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
16156e91bba0SGirish Moodalbail 	}
16166e91bba0SGirish Moodalbail 
16176e91bba0SGirish Moodalbail 	if (pdtbl == NULL)
16186e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
16196e91bba0SGirish Moodalbail 
16206e91bba0SGirish Moodalbail 	for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
16216e91bba0SGirish Moodalbail 		if (strcmp(pname, pdp->ipd_name) != 0)
16226e91bba0SGirish Moodalbail 			continue;
16236e91bba0SGirish Moodalbail 		if (!(pdp->ipd_proto & proto))
16246e91bba0SGirish Moodalbail 			continue;
16256e91bba0SGirish Moodalbail 		matched = B_TRUE;
16266e91bba0SGirish Moodalbail 		/* we found a match, call the callback function */
16276e91bba0SGirish Moodalbail 		if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
16286e91bba0SGirish Moodalbail 			break;
16296e91bba0SGirish Moodalbail 	}
16306e91bba0SGirish Moodalbail 	if (!matched)
16316e91bba0SGirish Moodalbail 		status = IPADM_PROP_UNKNOWN;
16326e91bba0SGirish Moodalbail 	return (status);
16336e91bba0SGirish Moodalbail }
16346e91bba0SGirish Moodalbail 
16356e91bba0SGirish Moodalbail /* ARGSUSED */
16366e91bba0SGirish Moodalbail ipadm_status_t
i_ipadm_get_onoff(ipadm_handle_t iph,const void * arg,ipadm_prop_desc_t * dp,char * buf,uint_t * bufsize,uint_t proto,uint_t valtype)16376e91bba0SGirish Moodalbail i_ipadm_get_onoff(ipadm_handle_t iph, const void *arg, ipadm_prop_desc_t *dp,
16386e91bba0SGirish Moodalbail     char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
16396e91bba0SGirish Moodalbail {
16406e91bba0SGirish Moodalbail 	(void) snprintf(buf, *bufsize, "%s,%s", IPADM_ONSTR, IPADM_OFFSTR);
16416e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
16426e91bba0SGirish Moodalbail }
16436e91bba0SGirish Moodalbail 
16446e91bba0SGirish Moodalbail /*
16456e91bba0SGirish Moodalbail  * Makes a door call to ipmgmtd to retrieve the persisted property value
16466e91bba0SGirish Moodalbail  */
16476e91bba0SGirish Moodalbail ipadm_status_t
i_ipadm_get_persist_propval(ipadm_handle_t iph,ipadm_prop_desc_t * pdp,char * gbuf,uint_t * gbufsize,const void * object)16486e91bba0SGirish Moodalbail i_ipadm_get_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
16496e91bba0SGirish Moodalbail     char *gbuf, uint_t *gbufsize, const void *object)
16506e91bba0SGirish Moodalbail {
16516e91bba0SGirish Moodalbail 	ipmgmt_prop_arg_t	parg;
16526e91bba0SGirish Moodalbail 	ipmgmt_getprop_rval_t	rval, *rvalp;
16536e91bba0SGirish Moodalbail 	size_t			nbytes;
16546e91bba0SGirish Moodalbail 	int			err = 0;
16556e91bba0SGirish Moodalbail 
16566e91bba0SGirish Moodalbail 	bzero(&parg, sizeof (parg));
16576e91bba0SGirish Moodalbail 	parg.ia_cmd = IPMGMT_CMD_GETPROP;
16586e91bba0SGirish Moodalbail 	i_ipadm_populate_proparg(&parg, pdp, NULL, object);
16596e91bba0SGirish Moodalbail 
16606e91bba0SGirish Moodalbail 	rvalp = &rval;
16616e91bba0SGirish Moodalbail 	err = ipadm_door_call(iph, &parg, sizeof (parg), (void **)&rvalp,
16626e91bba0SGirish Moodalbail 	    sizeof (rval), B_FALSE);
16636e91bba0SGirish Moodalbail 	if (err == 0) {
16646e91bba0SGirish Moodalbail 		/* assert that rvalp was not reallocated */
16656e91bba0SGirish Moodalbail 		assert(rvalp == &rval);
16666e91bba0SGirish Moodalbail 
16676e91bba0SGirish Moodalbail 		/* `ir_pval' contains the property value */
16686e91bba0SGirish Moodalbail 		nbytes = snprintf(gbuf, *gbufsize, "%s", rvalp->ir_pval);
16696e91bba0SGirish Moodalbail 		if (nbytes >= *gbufsize) {
16706e91bba0SGirish Moodalbail 			/* insufficient buffer space */
16716e91bba0SGirish Moodalbail 			*gbufsize = nbytes + 1;
16726e91bba0SGirish Moodalbail 			err = ENOBUFS;
16736e91bba0SGirish Moodalbail 		}
16746e91bba0SGirish Moodalbail 	}
16756e91bba0SGirish Moodalbail 	return (ipadm_errno2status(err));
16766e91bba0SGirish Moodalbail }
16776e91bba0SGirish Moodalbail 
16786e91bba0SGirish Moodalbail /*
16796e91bba0SGirish Moodalbail  * Persists the property value for a given property in the data store
16806e91bba0SGirish Moodalbail  */
16816e91bba0SGirish Moodalbail ipadm_status_t
i_ipadm_persist_propval(ipadm_handle_t iph,ipadm_prop_desc_t * pdp,const char * pval,const void * object,uint_t flags)16826e91bba0SGirish Moodalbail i_ipadm_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
16836e91bba0SGirish Moodalbail     const char *pval, const void *object, uint_t flags)
16846e91bba0SGirish Moodalbail {
16856e91bba0SGirish Moodalbail 	ipmgmt_prop_arg_t	parg;
16866e91bba0SGirish Moodalbail 	int			err = 0;
16876e91bba0SGirish Moodalbail 
16886e91bba0SGirish Moodalbail 	bzero(&parg, sizeof (parg));
16896e91bba0SGirish Moodalbail 	i_ipadm_populate_proparg(&parg, pdp, pval, object);
16906e91bba0SGirish Moodalbail 	/*
16916e91bba0SGirish Moodalbail 	 * Check if value to be persisted need to be appended or removed. This
16926e91bba0SGirish Moodalbail 	 * is required for multi-valued property.
16936e91bba0SGirish Moodalbail 	 */
16946e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_APPEND)
16956e91bba0SGirish Moodalbail 		parg.ia_flags |= IPMGMT_APPEND;
16966e91bba0SGirish Moodalbail 	if (flags & IPADM_OPT_REMOVE)
16976e91bba0SGirish Moodalbail 		parg.ia_flags |= IPMGMT_REMOVE;
16986e91bba0SGirish Moodalbail 
16996e91bba0SGirish Moodalbail 	if (flags & (IPADM_OPT_DEFAULT|IPADM_OPT_REMOVE))
17006e91bba0SGirish Moodalbail 		parg.ia_cmd = IPMGMT_CMD_RESETPROP;
17016e91bba0SGirish Moodalbail 	else
17026e91bba0SGirish Moodalbail 		parg.ia_cmd = IPMGMT_CMD_SETPROP;
17036e91bba0SGirish Moodalbail 
17046e91bba0SGirish Moodalbail 	err = ipadm_door_call(iph, &parg, sizeof (parg), NULL, 0, B_FALSE);
17056e91bba0SGirish Moodalbail 
17066e91bba0SGirish Moodalbail 	/*
17076e91bba0SGirish Moodalbail 	 * its fine if there were no entry in the DB to delete. The user
17086e91bba0SGirish Moodalbail 	 * might be changing property value, which was not changed
17096e91bba0SGirish Moodalbail 	 * persistently.
17106e91bba0SGirish Moodalbail 	 */
17116e91bba0SGirish Moodalbail 	if (err == ENOENT)
17126e91bba0SGirish Moodalbail 		err = 0;
17136e91bba0SGirish Moodalbail 	return (ipadm_errno2status(err));
17146e91bba0SGirish Moodalbail }
17156e91bba0SGirish Moodalbail 
17166e91bba0SGirish Moodalbail /*
17176e91bba0SGirish Moodalbail  * This is called from ipadm_set_ifprop() to validate the set operation.
17186e91bba0SGirish Moodalbail  * It does the following steps:
17196e91bba0SGirish Moodalbail  * 1. Validates the interface name.
1720*a73be61aSHans Rosenfeld  * 2. In case of a persistent operation, verifies that the
17216e91bba0SGirish Moodalbail  *	interface is persistent.
17226e91bba0SGirish Moodalbail  */
17236e91bba0SGirish Moodalbail static ipadm_status_t
i_ipadm_validate_if(ipadm_handle_t iph,const char * ifname,uint_t proto,uint_t flags)17246e91bba0SGirish Moodalbail i_ipadm_validate_if(ipadm_handle_t iph, const char *ifname,
17256e91bba0SGirish Moodalbail     uint_t proto, uint_t flags)
17266e91bba0SGirish Moodalbail {
17276e91bba0SGirish Moodalbail 	sa_family_t	af, other_af;
17286e91bba0SGirish Moodalbail 	ipadm_status_t	status;
17296e91bba0SGirish Moodalbail 	boolean_t	p_exists;
17306e91bba0SGirish Moodalbail 	boolean_t	af_exists, other_af_exists, a_exists;
17316e91bba0SGirish Moodalbail 
17326e91bba0SGirish Moodalbail 	/* Check if the interface name is valid. */
17336e91bba0SGirish Moodalbail 	if (!i_ipadm_validate_ifname(iph, ifname))
17346e91bba0SGirish Moodalbail 		return (IPADM_INVALID_ARG);
17356e91bba0SGirish Moodalbail 
17366e91bba0SGirish Moodalbail 	af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
17376e91bba0SGirish Moodalbail 
17386e91bba0SGirish Moodalbail 	/* Check if interface exists in the persistent configuration. */
17396e91bba0SGirish Moodalbail 	status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
17406e91bba0SGirish Moodalbail 	if (status != IPADM_SUCCESS)
17416e91bba0SGirish Moodalbail 		return (status);
17426e91bba0SGirish Moodalbail 
17436e91bba0SGirish Moodalbail 	/* Check if interface exists in the active configuration. */
17446e91bba0SGirish Moodalbail 	af_exists = ipadm_if_enabled(iph, ifname, af);
17456e91bba0SGirish Moodalbail 	other_af = (af == AF_INET ? AF_INET6 : AF_INET);
17466e91bba0SGirish Moodalbail 	other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
17476e91bba0SGirish Moodalbail 	a_exists = (af_exists || other_af_exists);
17486e91bba0SGirish Moodalbail 	if (!a_exists && p_exists)
17496e91bba0SGirish Moodalbail 		return (IPADM_OP_DISABLE_OBJ);
17506e91bba0SGirish Moodalbail 	if (!af_exists)
17516e91bba0SGirish Moodalbail 		return (IPADM_ENXIO);
17526e91bba0SGirish Moodalbail 
17536e91bba0SGirish Moodalbail 	/*
17546e91bba0SGirish Moodalbail 	 * If a persistent operation is requested, check if the underlying
17556e91bba0SGirish Moodalbail 	 * IP interface is persistent.
17566e91bba0SGirish Moodalbail 	 */
17576e91bba0SGirish Moodalbail 	if ((flags & IPADM_OPT_PERSIST) && !p_exists)
17586e91bba0SGirish Moodalbail 		return (IPADM_TEMPORARY_OBJ);
17596e91bba0SGirish Moodalbail 	return (IPADM_SUCCESS);
17606e91bba0SGirish Moodalbail }
17618887b57dSGirish Moodalbail 
17628887b57dSGirish Moodalbail /*
17638887b57dSGirish Moodalbail  * Private protocol properties namespace scheme:
17648887b57dSGirish Moodalbail  *
17658887b57dSGirish Moodalbail  * PSARC 2010/080 identified the private protocol property names to be the
17668887b57dSGirish Moodalbail  * leading protocol names. For e.g. tcp_strong_iss, ip_strict_src_multihoming,
17678887b57dSGirish Moodalbail  * et al,. However to be consistent with private data-link property names,
17688887b57dSGirish Moodalbail  * which starts with '_', private protocol property names will start with '_'.
17698887b57dSGirish Moodalbail  * For e.g. _strong_iss, _strict_src_multihoming, et al,.
17708887b57dSGirish Moodalbail  */
17718887b57dSGirish Moodalbail 
17728887b57dSGirish Moodalbail /* maps new private protocol property name to the old private property name */
17738887b57dSGirish Moodalbail typedef struct ipadm_oname2nname_map {
17748887b57dSGirish Moodalbail 	char	*iom_oname;
17758887b57dSGirish Moodalbail 	char	*iom_nname;
17768887b57dSGirish Moodalbail 	uint_t	iom_proto;
17778887b57dSGirish Moodalbail } ipadm_oname2nname_map_t;
17788887b57dSGirish Moodalbail 
17798887b57dSGirish Moodalbail /*
17808887b57dSGirish Moodalbail  * IP is a special case. It isn't straight forward to derive the legacy name
17818887b57dSGirish Moodalbail  * from the new name and vice versa. No set standard was followed in naming
17828887b57dSGirish Moodalbail  * the properties and hence we need a table to capture the mapping.
17838887b57dSGirish Moodalbail  */
17848887b57dSGirish Moodalbail static ipadm_oname2nname_map_t name_map[] = {
17858887b57dSGirish Moodalbail 	{ "arp_probe_delay",		"_arp_probe_delay",
17868887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17878887b57dSGirish Moodalbail 	{ "arp_fastprobe_delay",	"_arp_fastprobe_delay",
17888887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17898887b57dSGirish Moodalbail 	{ "arp_probe_interval",		"_arp_probe_interval",
17908887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17918887b57dSGirish Moodalbail 	{ "arp_fastprobe_interval",	"_arp_fastprobe_interval",
17928887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17938887b57dSGirish Moodalbail 	{ "arp_probe_count",		"_arp_probe_count",
17948887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17958887b57dSGirish Moodalbail 	{ "arp_fastprobe_count",	"_arp_fastprobe_count",
17968887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17978887b57dSGirish Moodalbail 	{ "arp_defend_interval",	"_arp_defend_interval",
17988887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
17998887b57dSGirish Moodalbail 	{ "arp_defend_rate",		"_arp_defend_rate",
18008887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18018887b57dSGirish Moodalbail 	{ "arp_defend_period",		"_arp_defend_period",
18028887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18038887b57dSGirish Moodalbail 	{ "ndp_defend_interval",	"_ndp_defend_interval",
18048887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18058887b57dSGirish Moodalbail 	{ "ndp_defend_rate",		"_ndp_defend_rate",
18068887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18078887b57dSGirish Moodalbail 	{ "ndp_defend_period",		"_ndp_defend_period",
18088887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18098887b57dSGirish Moodalbail 	{ "igmp_max_version",		"_igmp_max_version",
18108887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18118887b57dSGirish Moodalbail 	{ "mld_max_version",		"_mld_max_version",
18128887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18138887b57dSGirish Moodalbail 	{ "ipsec_override_persocket_policy", "_ipsec_override_persocket_policy",
18148887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18158887b57dSGirish Moodalbail 	{ "ipsec_policy_log_interval",	"_ipsec_policy_log_interval",
18168887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18178887b57dSGirish Moodalbail 	{ "icmp_accept_clear_messages",	"_icmp_accept_clear_messages",
18188887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18198887b57dSGirish Moodalbail 	{ "igmp_accept_clear_messages",	"_igmp_accept_clear_messages",
18208887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18218887b57dSGirish Moodalbail 	{ "pim_accept_clear_messages",	"_pim_accept_clear_messages",
18228887b57dSGirish Moodalbail 	    MOD_PROTO_IP },
18238887b57dSGirish Moodalbail 	{ "ip_respond_to_echo_multicast", "_respond_to_echo_multicast",
18248887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18258887b57dSGirish Moodalbail 	{ "ip_send_redirects",		"_send_redirects",
18268887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18278887b57dSGirish Moodalbail 	{ "ip_forward_src_routed",	"_forward_src_routed",
18288887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18298887b57dSGirish Moodalbail 	{ "ip_icmp_return_data_bytes",	"_icmp_return_data_bytes",
18308887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18318887b57dSGirish Moodalbail 	{ "ip_ignore_redirect",		"_ignore_redirect",
18328887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18338887b57dSGirish Moodalbail 	{ "ip_strict_dst_multihoming",	"_strict_dst_multihoming",
18348887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18358887b57dSGirish Moodalbail 	{ "ip_reasm_timeout",		"_reasm_timeout",
18368887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18378887b57dSGirish Moodalbail 	{ "ip_strict_src_multihoming",	"_strict_src_multihoming",
18388887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18398887b57dSGirish Moodalbail 	{ "ipv4_dad_announce_interval",	"_dad_announce_interval",
18408887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18418887b57dSGirish Moodalbail 	{ "ipv4_icmp_return_pmtu",	"_icmp_return_pmtu",
18428887b57dSGirish Moodalbail 	    MOD_PROTO_IPV4 },
18438887b57dSGirish Moodalbail 	{ "ipv6_dad_announce_interval",	"_dad_announce_interval",
18448887b57dSGirish Moodalbail 	    MOD_PROTO_IPV6 },
18458887b57dSGirish Moodalbail 	{ "ipv6_icmp_return_pmtu",	"_icmp_return_pmtu",
18468887b57dSGirish Moodalbail 	    MOD_PROTO_IPV6 },
18478887b57dSGirish Moodalbail 	{ NULL, NULL, MOD_PROTO_NONE }
18488887b57dSGirish Moodalbail };
18498887b57dSGirish Moodalbail 
18508887b57dSGirish Moodalbail /*
18518887b57dSGirish Moodalbail  * Following API returns a new property name in `nname' for the given legacy
18528887b57dSGirish Moodalbail  * property name in `oname'.
18538887b57dSGirish Moodalbail  */
18548887b57dSGirish Moodalbail int
ipadm_legacy2new_propname(const char * oname,char * nname,uint_t nnamelen,uint_t * proto)18558887b57dSGirish Moodalbail ipadm_legacy2new_propname(const char *oname, char *nname, uint_t nnamelen,
18568887b57dSGirish Moodalbail     uint_t *proto)
18578887b57dSGirish Moodalbail {
18588887b57dSGirish Moodalbail 	const char	*str;
18598887b57dSGirish Moodalbail 	ipadm_oname2nname_map_t *ionmp;
18608887b57dSGirish Moodalbail 
18618887b57dSGirish Moodalbail 	/* if it's a public property, there is nothing to return */
18628887b57dSGirish Moodalbail 	if (i_ipadm_get_prop_desc(oname, *proto, NULL) != NULL)
18638887b57dSGirish Moodalbail 		return (-1);
18648887b57dSGirish Moodalbail 
18658887b57dSGirish Moodalbail 	/*
18668887b57dSGirish Moodalbail 	 * we didn't find the `oname' in the table, check if the property
18678887b57dSGirish Moodalbail 	 * name begins with a leading protocol.
18688887b57dSGirish Moodalbail 	 */
18698887b57dSGirish Moodalbail 	str = oname;
18708887b57dSGirish Moodalbail 	switch (*proto) {
18718887b57dSGirish Moodalbail 	case MOD_PROTO_TCP:
18728887b57dSGirish Moodalbail 		if (strstr(oname, "tcp_") == oname)
18738887b57dSGirish Moodalbail 			str += strlen("tcp");
18748887b57dSGirish Moodalbail 		break;
18758887b57dSGirish Moodalbail 	case MOD_PROTO_SCTP:
18768887b57dSGirish Moodalbail 		if (strstr(oname, "sctp_") == oname)
18778887b57dSGirish Moodalbail 			str += strlen("sctp");
18788887b57dSGirish Moodalbail 		break;
18798887b57dSGirish Moodalbail 	case MOD_PROTO_UDP:
18808887b57dSGirish Moodalbail 		if (strstr(oname, "udp_") == oname)
18818887b57dSGirish Moodalbail 			str += strlen("udp");
18828887b57dSGirish Moodalbail 		break;
18838887b57dSGirish Moodalbail 	case MOD_PROTO_RAWIP:
18848887b57dSGirish Moodalbail 		if (strstr(oname, "icmp_") == oname)
18858887b57dSGirish Moodalbail 			str += strlen("icmp");
18868887b57dSGirish Moodalbail 		break;
18878887b57dSGirish Moodalbail 	case MOD_PROTO_IP:
18888887b57dSGirish Moodalbail 	case MOD_PROTO_IPV4:
18898887b57dSGirish Moodalbail 	case MOD_PROTO_IPV6:
18908887b57dSGirish Moodalbail 		if (strstr(oname, "ip6_") == oname) {
18918887b57dSGirish Moodalbail 			*proto = MOD_PROTO_IPV6;
18928887b57dSGirish Moodalbail 			str += strlen("ip6");
18938887b57dSGirish Moodalbail 		} else {
18948887b57dSGirish Moodalbail 			for (ionmp = name_map; ionmp->iom_oname != NULL;
18958887b57dSGirish Moodalbail 			    ionmp++) {
18968887b57dSGirish Moodalbail 				if (strcmp(oname, ionmp->iom_oname) == 0) {
18978887b57dSGirish Moodalbail 					str = ionmp->iom_nname;
18988887b57dSGirish Moodalbail 					*proto = ionmp->iom_proto;
18998887b57dSGirish Moodalbail 					break;
19008887b57dSGirish Moodalbail 				}
19018887b57dSGirish Moodalbail 			}
19028887b57dSGirish Moodalbail 			if (ionmp->iom_oname != NULL)
19038887b57dSGirish Moodalbail 				break;
19048887b57dSGirish Moodalbail 
19058887b57dSGirish Moodalbail 			if (strstr(oname, "ip_") == oname) {
19068887b57dSGirish Moodalbail 				*proto = MOD_PROTO_IP;
19078887b57dSGirish Moodalbail 				str += strlen("ip");
19088887b57dSGirish Moodalbail 			}
19098887b57dSGirish Moodalbail 		}
19108887b57dSGirish Moodalbail 		break;
19118887b57dSGirish Moodalbail 	default:
19128887b57dSGirish Moodalbail 		return (-1);
19138887b57dSGirish Moodalbail 	}
19148887b57dSGirish Moodalbail 	(void) snprintf(nname, nnamelen, "%s", str);
19158887b57dSGirish Moodalbail 	return (0);
19168887b57dSGirish Moodalbail }
19178887b57dSGirish Moodalbail 
19188887b57dSGirish Moodalbail /*
19198887b57dSGirish Moodalbail  * Following API is required for ndd.c alone. To maintain backward
19208887b57dSGirish Moodalbail  * compatibility with ndd output, we need to print the legacy name
19218887b57dSGirish Moodalbail  * for the new name.
19228887b57dSGirish Moodalbail  */
19238887b57dSGirish Moodalbail int
ipadm_new2legacy_propname(const char * oname,char * nname,uint_t nnamelen,uint_t proto)19248887b57dSGirish Moodalbail ipadm_new2legacy_propname(const char *oname, char *nname,
19258887b57dSGirish Moodalbail     uint_t nnamelen, uint_t proto)
19268887b57dSGirish Moodalbail {
19278887b57dSGirish Moodalbail 	char	*prefix;
19288887b57dSGirish Moodalbail 	ipadm_oname2nname_map_t *ionmp;
19298887b57dSGirish Moodalbail 
19308887b57dSGirish Moodalbail 	/* if it's a public property, there is nothing to prepend */
19318887b57dSGirish Moodalbail 	if (i_ipadm_get_prop_desc(oname, proto, NULL) != NULL)
19328887b57dSGirish Moodalbail 		return (-1);
19338887b57dSGirish Moodalbail 
19348887b57dSGirish Moodalbail 	switch (proto) {
19358887b57dSGirish Moodalbail 	case MOD_PROTO_TCP:
19368887b57dSGirish Moodalbail 		prefix = "tcp";
19378887b57dSGirish Moodalbail 		break;
19388887b57dSGirish Moodalbail 	case MOD_PROTO_SCTP:
19398887b57dSGirish Moodalbail 		prefix = "sctp";
19408887b57dSGirish Moodalbail 		break;
19418887b57dSGirish Moodalbail 	case MOD_PROTO_UDP:
19428887b57dSGirish Moodalbail 		prefix = "udp";
19438887b57dSGirish Moodalbail 		break;
19448887b57dSGirish Moodalbail 	case MOD_PROTO_RAWIP:
19458887b57dSGirish Moodalbail 		prefix = "icmp";
19468887b57dSGirish Moodalbail 		break;
19478887b57dSGirish Moodalbail 	case MOD_PROTO_IP:
19488887b57dSGirish Moodalbail 	case MOD_PROTO_IPV4:
19498887b57dSGirish Moodalbail 	case MOD_PROTO_IPV6:
19508887b57dSGirish Moodalbail 		/* handle special case for IP */
19518887b57dSGirish Moodalbail 		for (ionmp = name_map; ionmp->iom_oname != NULL; ionmp++) {
19528887b57dSGirish Moodalbail 			if (strcmp(oname, ionmp->iom_nname) == 0 &&
19538887b57dSGirish Moodalbail 			    ionmp->iom_proto == proto) {
19548887b57dSGirish Moodalbail 				(void) strlcpy(nname, ionmp->iom_oname,
19558887b57dSGirish Moodalbail 				    nnamelen);
19568887b57dSGirish Moodalbail 				return (0);
19578887b57dSGirish Moodalbail 			}
19588887b57dSGirish Moodalbail 		}
19598887b57dSGirish Moodalbail 		if (proto == MOD_PROTO_IPV6)
19608887b57dSGirish Moodalbail 			prefix = "ip6";
19618887b57dSGirish Moodalbail 		else
19628887b57dSGirish Moodalbail 			prefix = "ip";
19638887b57dSGirish Moodalbail 		break;
19648887b57dSGirish Moodalbail 	default:
19658887b57dSGirish Moodalbail 		return (-1);
19668887b57dSGirish Moodalbail 	}
19678887b57dSGirish Moodalbail 	(void) snprintf(nname, nnamelen, "%s%s", prefix, oname);
19688887b57dSGirish Moodalbail 	return (0);
19698887b57dSGirish Moodalbail }
1970