xref: /titanic_52/usr/src/lib/libdladm/common/linkprop.c (revision da14cebe459d3275048785f25bd869cb09b5307f)
10ba2cbe9Sxc151355 /*
20ba2cbe9Sxc151355  * CDDL HEADER START
30ba2cbe9Sxc151355  *
40ba2cbe9Sxc151355  * The contents of this file are subject to the terms of the
50ba2cbe9Sxc151355  * Common Development and Distribution License (the "License").
60ba2cbe9Sxc151355  * You may not use this file except in compliance with the License.
70ba2cbe9Sxc151355  *
80ba2cbe9Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90ba2cbe9Sxc151355  * or http://www.opensolaris.org/os/licensing.
100ba2cbe9Sxc151355  * See the License for the specific language governing permissions
110ba2cbe9Sxc151355  * and limitations under the License.
120ba2cbe9Sxc151355  *
130ba2cbe9Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
140ba2cbe9Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150ba2cbe9Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
160ba2cbe9Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
170ba2cbe9Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
180ba2cbe9Sxc151355  *
190ba2cbe9Sxc151355  * CDDL HEADER END
200ba2cbe9Sxc151355  */
210ba2cbe9Sxc151355 /*
22d62bc4baSyz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230ba2cbe9Sxc151355  * Use is subject to license terms.
240ba2cbe9Sxc151355  */
250ba2cbe9Sxc151355 
260ba2cbe9Sxc151355 #include <stdlib.h>
270ba2cbe9Sxc151355 #include <strings.h>
280ba2cbe9Sxc151355 #include <errno.h>
290ba2cbe9Sxc151355 #include <ctype.h>
30d62bc4baSyz147064 #include <stddef.h>
31f4b3ec61Sdh155122 #include <sys/types.h>
320ba2cbe9Sxc151355 #include <sys/stat.h>
33f4b3ec61Sdh155122 #include <sys/dld.h>
34f4b3ec61Sdh155122 #include <sys/zone.h>
35f4b3ec61Sdh155122 #include <fcntl.h>
36f4b3ec61Sdh155122 #include <unistd.h>
37f4b3ec61Sdh155122 #include <libdevinfo.h>
38f4b3ec61Sdh155122 #include <zone.h>
39f595a68aSyz147064 #include <libdllink.h>
400ba2cbe9Sxc151355 #include <libdladm_impl.h>
41d62bc4baSyz147064 #include <libdlwlan_impl.h>
42f595a68aSyz147064 #include <libdlwlan.h>
43d62bc4baSyz147064 #include <libdlvlan.h>
44*da14cebeSEric Cheng #include <libdlvnic.h>
45*da14cebeSEric Cheng #include <libintl.h>
46f4b3ec61Sdh155122 #include <dlfcn.h>
47f4b3ec61Sdh155122 #include <link.h>
48d62bc4baSyz147064 #include <inet/wifi_ioctl.h>
49e7801d59Ssowmini #include <libdladm.h>
50*da14cebeSEric Cheng #include <libdlstat.h>
51e7801d59Ssowmini #include <sys/param.h>
52*da14cebeSEric Cheng #include <sys/debug.h>
53*da14cebeSEric Cheng #include <sys/dld.h>
54*da14cebeSEric Cheng #include <sys/mac_flow.h>
55e7801d59Ssowmini #include <inttypes.h>
56e7801d59Ssowmini #include <sys/ethernet.h>
57bcb5c89dSSowmini Varadhan #include <net/wpa.h>
58bcb5c89dSSowmini Varadhan #include <sys/sysmacros.h>
59f4b3ec61Sdh155122 
60d62bc4baSyz147064 /*
61d62bc4baSyz147064  * The linkprop get() callback.
62*da14cebeSEric Cheng  * - pd: 	pointer to the prop_desc_t
63d62bc4baSyz147064  * - propstrp:	a property string array to keep the returned property.
64d62bc4baSyz147064  *		Caller allocated.
65d62bc4baSyz147064  * - cntp:	number of returned properties.
66d62bc4baSyz147064  *		Caller also uses it to indicate how many it expects.
67d62bc4baSyz147064  */
68e7801d59Ssowmini struct prop_desc;
69*da14cebeSEric Cheng typedef struct prop_desc prop_desc_t;
70e7801d59Ssowmini 
71*da14cebeSEric Cheng typedef dladm_status_t	pd_getf_t(prop_desc_t *pdp,
726b9e797cSsowmini 			datalink_id_t, char **propstp, uint_t *cntp,
73afdda45fSVasumathi Sundaram - Sun Microsystems 			datalink_media_t, uint_t, uint_t *);
74f4b3ec61Sdh155122 
75d62bc4baSyz147064 /*
76d62bc4baSyz147064  * The linkprop set() callback.
77d62bc4baSyz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
78d62bc4baSyz147064  * - cnt:	number of properties to be set.
79e7801d59Ssowmini  * - flags: 	additional flags passed down the system call.
80e7801d59Ssowmini  *
81e7801d59Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
82e7801d59Ssowmini  * a format suitable for kernel consumption. This may require allocation
83e7801d59Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
84e7801d59Ssowmini  * by all other pd_sets) which invokes the ioctl.
85d62bc4baSyz147064  */
86*da14cebeSEric Cheng typedef dladm_status_t	pd_setf_t(prop_desc_t *, datalink_id_t,
876b9e797cSsowmini 			    val_desc_t *propval, uint_t cnt, uint_t flags,
886b9e797cSsowmini 			    datalink_media_t);
89f4b3ec61Sdh155122 
90d62bc4baSyz147064 /*
91d62bc4baSyz147064  * The linkprop check() callback.
92d62bc4baSyz147064  * - propstrp:	property string array which keeps the property to be checked.
93d62bc4baSyz147064  * - cnt:	number of properties.
94d62bc4baSyz147064  * - propval:	return value; the property values of the given property strings.
95e7801d59Ssowmini  *
96e7801d59Ssowmini  * pd_check checks that the input values are valid. It does so by
97e7801d59Ssowmini  * iteraring through the pd_modval list for the property. If
98e7801d59Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
99e7801d59Ssowmini  * specific to this property can be used. If the input values are
100e7801d59Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
101e7801d59Ssowmini  * with either a val_desc_t found on the pd_modval list or something
102e7801d59Ssowmini  * generated on the fly.
103d62bc4baSyz147064  */
104*da14cebeSEric Cheng typedef dladm_status_t	pd_checkf_t(prop_desc_t *pdp, datalink_id_t,
105*da14cebeSEric Cheng 			    char **propstrp, uint_t cnt, val_desc_t *propval,
1066b9e797cSsowmini 			    datalink_media_t);
107f4b3ec61Sdh155122 
108bcb5c89dSSowmini Varadhan typedef struct link_attr_s {
1093fd94f8cSam223141 	mac_prop_id_t	pp_id;
110e7801d59Ssowmini 	size_t		pp_valsize;
111e7801d59Ssowmini 	char		*pp_name;
112bcb5c89dSSowmini Varadhan } link_attr_t;
113e7801d59Ssowmini 
114bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
115bcb5c89dSSowmini Varadhan 			    const char *, uint_t, dladm_status_t *);
116bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
117*da14cebeSEric Cheng 			    mac_prop_id_t, uint_t, dladm_status_t *);
118*da14cebeSEric Cheng static dld_ioc_macprop_t *i_dladm_get_public_prop(datalink_id_t, char *, uint_t,
119*da14cebeSEric Cheng 			    dladm_status_t *, uint_t *);
120*da14cebeSEric Cheng 
1213bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_set_prop(datalink_id_t, const char *, char **,
122e7801d59Ssowmini 					uint_t, uint_t);
1233bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_get_prop(datalink_id_t, const char *, char **,
1244045d941Ssowmini 					uint_t *, dladm_prop_type_t, uint_t);
125bcb5c89dSSowmini Varadhan static link_attr_t *dladm_name2prop(const char *);
126bcb5c89dSSowmini Varadhan static link_attr_t *dladm_id2prop(mac_prop_id_t);
127*da14cebeSEric Cheng 
128d62bc4baSyz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
129d62bc4baSyz147064 			do_get_rate_prop, do_get_channel_prop,
130e7801d59Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
1313bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_duplex_get, i_dladm_status_get,
1323bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_binary_get, i_dladm_uint32_get,
133*da14cebeSEric Cheng 			i_dladm_flowctl_get, dld_maxbw_get, dld_cpus_get,
134*da14cebeSEric Cheng 			dld_priority_get;
135*da14cebeSEric Cheng 
1363bc21d0aSAruna Ramakrishna - Sun Microsystems static pd_setf_t	do_set_zone, do_set_rate_prop,
137e7801d59Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
138*da14cebeSEric Cheng 			i_dladm_set_public_prop, do_set_res, do_set_cpus;
139f4b3ec61Sdh155122 
140*da14cebeSEric Cheng static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
141*da14cebeSEric Cheng 			i_dladm_defmtu_check, do_check_maxbw, do_check_cpus,
142*da14cebeSEric Cheng 			do_check_priority;
143*da14cebeSEric Cheng 
144*da14cebeSEric Cheng static dladm_status_t	i_dladm_speed_get(prop_desc_t *, datalink_id_t,
145*da14cebeSEric Cheng 			char **, uint_t *, uint_t, uint_t *);
146bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_wlan_get_legacy_ioctl(datalink_id_t, void *,
147bcb5c89dSSowmini Varadhan 			    uint_t, uint_t);
148bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_wlan_set_legacy_ioctl(datalink_id_t, void *,
149bcb5c89dSSowmini Varadhan 			    uint_t, uint_t);
150bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_macprop(void *, boolean_t);
151*da14cebeSEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1526b9e797cSsowmini 
153*da14cebeSEric Cheng struct prop_desc {
154d62bc4baSyz147064 	/*
155d62bc4baSyz147064 	 * link property name
156d62bc4baSyz147064 	 */
157f4b3ec61Sdh155122 	char			*pd_name;
158d62bc4baSyz147064 
159d62bc4baSyz147064 	/*
160d62bc4baSyz147064 	 * default property value, can be set to { "", NULL }
161d62bc4baSyz147064 	 */
162f4b3ec61Sdh155122 	val_desc_t		pd_defval;
163d62bc4baSyz147064 
164d62bc4baSyz147064 	/*
165d62bc4baSyz147064 	 * list of optional property values, can be NULL.
166d62bc4baSyz147064 	 *
167d62bc4baSyz147064 	 * This is set to non-NULL if there is a list of possible property
168d62bc4baSyz147064 	 * values.  pd_optval would point to the array of possible values.
169d62bc4baSyz147064 	 */
170d62bc4baSyz147064 	val_desc_t		*pd_optval;
171d62bc4baSyz147064 
172d62bc4baSyz147064 	/*
173d62bc4baSyz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
174d62bc4baSyz147064 	 */
175d62bc4baSyz147064 	uint_t			pd_noptval;
176d62bc4baSyz147064 
177d62bc4baSyz147064 	/*
178d62bc4baSyz147064 	 * callback to set link property;
179d62bc4baSyz147064 	 * set to NULL if this property is read-only
180d62bc4baSyz147064 	 */
181f4b3ec61Sdh155122 	pd_setf_t		*pd_set;
182d62bc4baSyz147064 
183d62bc4baSyz147064 	/*
184d62bc4baSyz147064 	 * callback to get modifiable link property
185d62bc4baSyz147064 	 */
186f4b3ec61Sdh155122 	pd_getf_t		*pd_getmod;
187d62bc4baSyz147064 
188d62bc4baSyz147064 	/*
189d62bc4baSyz147064 	 * callback to get current link property
190d62bc4baSyz147064 	 */
191f4b3ec61Sdh155122 	pd_getf_t		*pd_get;
192d62bc4baSyz147064 
193d62bc4baSyz147064 	/*
194d62bc4baSyz147064 	 * callback to validate link property value, set to NULL if pd_optval
195d62bc4baSyz147064 	 * is not NULL. In that case, validate the value by comparing it with
196d62bc4baSyz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
197d62bc4baSyz147064 	 * valid.
198d62bc4baSyz147064 	 */
199f4b3ec61Sdh155122 	pd_checkf_t		*pd_check;
200d62bc4baSyz147064 
201d62bc4baSyz147064 	uint_t			pd_flags;
202e7801d59Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
203e7801d59Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
204d62bc4baSyz147064 	/*
205d62bc4baSyz147064 	 * indicate link classes this property applies to.
206d62bc4baSyz147064 	 */
207d62bc4baSyz147064 	datalink_class_t	pd_class;
208d62bc4baSyz147064 
209d62bc4baSyz147064 	/*
210d62bc4baSyz147064 	 * indicate link media type this property applies to.
211d62bc4baSyz147064 	 */
212d62bc4baSyz147064 	datalink_media_t	pd_dmedia;
213*da14cebeSEric Cheng };
214f4b3ec61Sdh155122 
2153fd94f8cSam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
216e7801d59Ssowmini 
217bcb5c89dSSowmini Varadhan /*
218bcb5c89dSSowmini Varadhan  * Supported link properties enumerated in the prop_table[] array are
219bcb5c89dSSowmini Varadhan  * computed using the callback functions in that array. To compute the
220bcb5c89dSSowmini Varadhan  * property value, multiple distinct system calls may be needed (e.g.,
221bcb5c89dSSowmini Varadhan  * for wifi speed, we need to issue system calls to get desired/supported
222bcb5c89dSSowmini Varadhan  * rates). The link_attr[] table enumerates the interfaces to the kernel,
223bcb5c89dSSowmini Varadhan  * and the type/size of the data passed in the user-kernel interface.
224bcb5c89dSSowmini Varadhan  */
225bcb5c89dSSowmini Varadhan static link_attr_t link_attr[] = {
226bcb5c89dSSowmini Varadhan 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
227e7801d59Ssowmini 
228bcb5c89dSSowmini Varadhan 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
229e7801d59Ssowmini 
230bcb5c89dSSowmini Varadhan 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
231e7801d59Ssowmini 
232bcb5c89dSSowmini Varadhan 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
233e7801d59Ssowmini 
234bcb5c89dSSowmini Varadhan 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
235e7801d59Ssowmini 
236bcb5c89dSSowmini Varadhan 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
237e7801d59Ssowmini 
238bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
239e7801d59Ssowmini 
240bcb5c89dSSowmini Varadhan 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2413bc21d0aSAruna Ramakrishna - Sun Microsystems 
242bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2433bc21d0aSAruna Ramakrishna - Sun Microsystems 
244bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
245e7801d59Ssowmini 
246bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
247e7801d59Ssowmini 
248bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
249e7801d59Ssowmini 
250bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
251e7801d59Ssowmini 
252bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
253e7801d59Ssowmini 
254bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
255e7801d59Ssowmini 
256bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
257e7801d59Ssowmini 
258bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
259e7801d59Ssowmini 
260bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
261e7801d59Ssowmini 
262bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
263e7801d59Ssowmini 
264bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
265e7801d59Ssowmini 
266bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
267e7801d59Ssowmini 
268bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
269bcb5c89dSSowmini Varadhan 
270bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
271bcb5c89dSSowmini Varadhan 
272bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
273bcb5c89dSSowmini Varadhan 
274bcb5c89dSSowmini Varadhan 	/* wl_rates_t has variable length */
275bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
276bcb5c89dSSowmini Varadhan 
277bcb5c89dSSowmini Varadhan 	/* wl_rates_t has variable length */
278bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
279bcb5c89dSSowmini Varadhan 
280bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
281bcb5c89dSSowmini Varadhan 
282bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
283bcb5c89dSSowmini Varadhan 
284bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
285bcb5c89dSSowmini Varadhan 
286bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
287bcb5c89dSSowmini Varadhan 
288bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
289bcb5c89dSSowmini Varadhan 
290bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
291bcb5c89dSSowmini Varadhan 
292bcb5c89dSSowmini Varadhan 	/*  wl_wpa_ess_t has variable length */
293bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
294bcb5c89dSSowmini Varadhan 
295bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
296bcb5c89dSSowmini Varadhan 
297bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
298bcb5c89dSSowmini Varadhan 
299bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
300bcb5c89dSSowmini Varadhan 
301bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
302bcb5c89dSSowmini Varadhan 
303bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
304bcb5c89dSSowmini Varadhan 
305bcb5c89dSSowmini Varadhan 	/* wl_wpa_ie_t has variable length */
306bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
307bcb5c89dSSowmini Varadhan 
308bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
309bcb5c89dSSowmini Varadhan 
310bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
311bcb5c89dSSowmini Varadhan 
312bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
313bcb5c89dSSowmini Varadhan 
314*da14cebeSEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
315*da14cebeSEric Cheng 
316*da14cebeSEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
317*da14cebeSEric Cheng 
318*da14cebeSEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
319*da14cebeSEric Cheng 
320bcb5c89dSSowmini Varadhan 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
321*da14cebeSEric Cheng 
322e7801d59Ssowmini };
323e7801d59Ssowmini 
324e7801d59Ssowmini static  val_desc_t	link_duplex_vals[] = {
325e7801d59Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
326e7801d59Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
327e7801d59Ssowmini };
328e7801d59Ssowmini static  val_desc_t	link_status_vals[] = {
329e7801d59Ssowmini 	{ "up",		LINK_STATE_UP		},
330e7801d59Ssowmini 	{ "down",	LINK_STATE_DOWN		}
331e7801d59Ssowmini };
332e7801d59Ssowmini static  val_desc_t	link_01_vals[] = {
333e7801d59Ssowmini 	{ "1",		1			},
334e7801d59Ssowmini 	{ "0",		0			}
335e7801d59Ssowmini };
336e7801d59Ssowmini static  val_desc_t	link_flow_vals[] = {
337e7801d59Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
338e7801d59Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
339e7801d59Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
340e7801d59Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
341e7801d59Ssowmini };
342*da14cebeSEric Cheng static  val_desc_t	link_priority_vals[] = {
343*da14cebeSEric Cheng 	{ "low",	MPL_LOW	},
344*da14cebeSEric Cheng 	{ "medium",	MPL_MEDIUM	},
345*da14cebeSEric Cheng 	{ "high",	MPL_HIGH	}
346*da14cebeSEric Cheng };
347e7801d59Ssowmini 
348d62bc4baSyz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
349d62bc4baSyz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
350d62bc4baSyz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
351d62bc4baSyz147064 };
352d62bc4baSyz147064 
353d62bc4baSyz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
354d62bc4baSyz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
355d62bc4baSyz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
356d62bc4baSyz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
357d62bc4baSyz147064 };
358d62bc4baSyz147064 
359*da14cebeSEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
360*da14cebeSEric Cheng #define	RESET_VAL	((uintptr_t)-1)
361d62bc4baSyz147064 
362*da14cebeSEric Cheng static prop_desc_t	prop_table[] = {
363e7801d59Ssowmini 	{ "channel",	{ NULL, 0 },
364e7801d59Ssowmini 	    NULL, 0, NULL, NULL,
365d62bc4baSyz147064 	    do_get_channel_prop, NULL, 0,
366d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
367d62bc4baSyz147064 
368d62bc4baSyz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
369d62bc4baSyz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
370d62bc4baSyz147064 	    do_set_powermode_prop, NULL,
371d62bc4baSyz147064 	    do_get_powermode_prop, NULL, 0,
372d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
373d62bc4baSyz147064 
374d62bc4baSyz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
375d62bc4baSyz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
376d62bc4baSyz147064 	    do_set_radio_prop, NULL,
377d62bc4baSyz147064 	    do_get_radio_prop, NULL, 0,
378d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
379d62bc4baSyz147064 
380d62bc4baSyz147064 	{ "speed",	{ "", 0 }, NULL, 0,
381d62bc4baSyz147064 	    do_set_rate_prop, do_get_rate_mod,
382d62bc4baSyz147064 	    do_get_rate_prop, do_check_rate, 0,
3836b9e797cSsowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
384d62bc4baSyz147064 
3854045d941Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
3863bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL,
3873bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
388d62bc4baSyz147064 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
389d62bc4baSyz147064 
3904045d941Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
391f4b3ec61Sdh155122 	    do_set_zone, NULL,
3923bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
393e7801d59Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
394e7801d59Ssowmini 
3954045d941Ssowmini 	{ "duplex",	{ "", 0 },
396e7801d59Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
3973bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_duplex_get, NULL,
398e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
399e7801d59Ssowmini 
4006b9e797cSsowmini 	{ "state",	{ "up", LINK_STATE_UP },
401e7801d59Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4023bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_status_get, NULL,
4034045d941Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
404e7801d59Ssowmini 
405e7801d59Ssowmini 	{ "adv_autoneg_cap", { "1", 1 },
406e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4073bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
408e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
409e7801d59Ssowmini 
4104045d941Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4113bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
4123bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL,
4133bc21d0aSAruna Ramakrishna - Sun Microsystems 	    DATALINK_ANY_MEDIATYPE },
414e7801d59Ssowmini 
4154045d941Ssowmini 	{ "flowctrl", { "", 0 },
416e7801d59Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4173bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
418e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
419e7801d59Ssowmini 
4204045d941Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4214045d941Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4223bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
423e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
424e7801d59Ssowmini 
4254045d941Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
426e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4273bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
428e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
429e7801d59Ssowmini 
4304045d941Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
431e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4323bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
433e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
434e7801d59Ssowmini 
4354045d941Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
436e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4373bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
438e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
439e7801d59Ssowmini 
4404045d941Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
441e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4423bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
443e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
444e7801d59Ssowmini 
4454045d941Ssowmini 	{ "en_100fdx_cap", { "", 0 },
446e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4473bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
448e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
449e7801d59Ssowmini 
4504045d941Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
451e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4523bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
453e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
454e7801d59Ssowmini 
4554045d941Ssowmini 	{ "en_100hdx_cap", { "", 0 },
456e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4573bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
458e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
459e7801d59Ssowmini 
4604045d941Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
461e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4623bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
463e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
464e7801d59Ssowmini 
4654045d941Ssowmini 	{ "en_10fdx_cap", { "", 0 },
466e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4673bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
468e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
469e7801d59Ssowmini 
4704045d941Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
471e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4723bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
473e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
474e7801d59Ssowmini 
4754045d941Ssowmini 	{ "en_10hdx_cap", { "", 0 },
476e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4773bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
478*da14cebeSEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
479e7801d59Ssowmini 
480*da14cebeSEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
481*da14cebeSEric Cheng 	    do_set_res, NULL,
482*da14cebeSEric Cheng 	    dld_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
483*da14cebeSEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
484*da14cebeSEric Cheng 
485*da14cebeSEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
486*da14cebeSEric Cheng 	    do_set_cpus, NULL,
487*da14cebeSEric Cheng 	    dld_cpus_get, do_check_cpus, 0,
488*da14cebeSEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
489*da14cebeSEric Cheng 
490*da14cebeSEric Cheng 	{ "priority", { "high", RESET_VAL },
491*da14cebeSEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
492*da14cebeSEric Cheng 	    dld_priority_get, do_check_priority, PD_CHECK_ALLOC,
493*da14cebeSEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
494f4b3ec61Sdh155122 };
495f4b3ec61Sdh155122 
496d62bc4baSyz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
4970ba2cbe9Sxc151355 
498*da14cebeSEric Cheng static resource_prop_t rsrc_prop_table[] = {
499*da14cebeSEric Cheng 	{"maxbw",	do_extract_maxbw},
500*da14cebeSEric Cheng 	{"priority",	do_extract_priority},
501*da14cebeSEric Cheng 	{"cpus",	do_extract_cpus}
502*da14cebeSEric Cheng };
503*da14cebeSEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
504*da14cebeSEric Cheng 	sizeof (resource_prop_t))
505*da14cebeSEric Cheng 
506bcb5c89dSSowmini Varadhan /*
507bcb5c89dSSowmini Varadhan  * when retrieving  private properties, we pass down a buffer with
508bcb5c89dSSowmini Varadhan  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
509bcb5c89dSSowmini Varadhan  */
510bcb5c89dSSowmini Varadhan #define	DLADM_PROP_BUF_CHUNK	1024
511bcb5c89dSSowmini Varadhan 
512d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop_db(datalink_id_t, const char *,
513d62bc4baSyz147064 			    char **, uint_t);
514d62bc4baSyz147064 static dladm_status_t	i_dladm_get_linkprop_db(datalink_id_t, const char *,
515d62bc4baSyz147064 			    char **, uint_t *);
516d62bc4baSyz147064 static dladm_status_t	i_dladm_set_single_prop(datalink_id_t, datalink_class_t,
517d62bc4baSyz147064 			    uint32_t, prop_desc_t *, char **, uint_t, uint_t);
518d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop(datalink_id_t, const char *,
519d62bc4baSyz147064 			    char **, uint_t, uint_t);
5204045d941Ssowmini static dladm_status_t	i_dladm_getset_defval(prop_desc_t *, datalink_id_t,
5214045d941Ssowmini 			    datalink_media_t, uint_t);
522*da14cebeSEric Cheng 
523*da14cebeSEric Cheng static dladm_status_t	link_proplist_check(dladm_arg_list_t *);
524*da14cebeSEric Cheng 
525d62bc4baSyz147064 /*
526d62bc4baSyz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
527d62bc4baSyz147064  * rates to be retrieved. However, we cannot increase it at this
528d62bc4baSyz147064  * time because it will break binary compatibility with unbundled
529d62bc4baSyz147064  * WiFi drivers and utilities. So for now we define an additional
530d62bc4baSyz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
531d62bc4baSyz147064  */
532d62bc4baSyz147064 #define	MAX_SUPPORT_RATES	64
533d62bc4baSyz147064 
534d62bc4baSyz147064 #define	AP_ANCHOR	"[anchor]"
535d62bc4baSyz147064 #define	AP_DELIMITER	'.'
536d62bc4baSyz147064 
537d62bc4baSyz147064 static dladm_status_t
538d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
539d62bc4baSyz147064     val_desc_t *vdp)
5400ba2cbe9Sxc151355 {
541d62bc4baSyz147064 	int		i, j;
5420ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
5430ba2cbe9Sxc151355 
544d62bc4baSyz147064 	for (j = 0; j < val_cnt; j++) {
545d62bc4baSyz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
546d62bc4baSyz147064 			if (strcasecmp(*prop_val,
547d62bc4baSyz147064 			    pdp->pd_optval[i].vd_name) == 0) {
5480ba2cbe9Sxc151355 				break;
5490ba2cbe9Sxc151355 			}
5500ba2cbe9Sxc151355 		}
551d62bc4baSyz147064 		if (i == pdp->pd_noptval) {
552d62bc4baSyz147064 			status = DLADM_STATUS_BADVAL;
553d62bc4baSyz147064 			goto done;
554d62bc4baSyz147064 		}
555d62bc4baSyz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
5560ba2cbe9Sxc151355 	}
5570ba2cbe9Sxc151355 
558d62bc4baSyz147064 done:
559d62bc4baSyz147064 	return (status);
5600ba2cbe9Sxc151355 }
5610ba2cbe9Sxc151355 
5620ba2cbe9Sxc151355 static dladm_status_t
563d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
564d62bc4baSyz147064     uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
565d62bc4baSyz147064     uint_t flags)
5660ba2cbe9Sxc151355 {
5670ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
568d62bc4baSyz147064 	val_desc_t	*vdp = NULL;
569d62bc4baSyz147064 	boolean_t	needfree = B_FALSE;
570d62bc4baSyz147064 	uint_t		cnt, i;
5710ba2cbe9Sxc151355 
572d62bc4baSyz147064 	if (!(pdp->pd_class & class))
573d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
5740ba2cbe9Sxc151355 
575d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
576d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
577d62bc4baSyz147064 
578d62bc4baSyz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
579d62bc4baSyz147064 		return (DLADM_STATUS_TEMPONLY);
580d62bc4baSyz147064 
581d62bc4baSyz147064 	if (!(flags & DLADM_OPT_ACTIVE))
582d62bc4baSyz147064 		return (DLADM_STATUS_OK);
583d62bc4baSyz147064 
584d62bc4baSyz147064 	if (pdp->pd_set == NULL)
585d62bc4baSyz147064 		return (DLADM_STATUS_PROPRDONLY);
586d62bc4baSyz147064 
587d62bc4baSyz147064 	if (prop_val != NULL) {
588d62bc4baSyz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
589d62bc4baSyz147064 		if (vdp == NULL)
590d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
591d62bc4baSyz147064 
592d62bc4baSyz147064 		if (pdp->pd_check != NULL) {
593*da14cebeSEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
594e7801d59Ssowmini 			status = pdp->pd_check(pdp, linkid, prop_val, val_cnt,
5956b9e797cSsowmini 			    vdp, media);
596d62bc4baSyz147064 		} else if (pdp->pd_optval != NULL) {
597d62bc4baSyz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
598d62bc4baSyz147064 		} else {
599d62bc4baSyz147064 			status = DLADM_STATUS_BADARG;
6000ba2cbe9Sxc151355 		}
6010ba2cbe9Sxc151355 
602d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
603d62bc4baSyz147064 			goto done;
604d62bc4baSyz147064 
605d62bc4baSyz147064 		cnt = val_cnt;
606d62bc4baSyz147064 	} else {
607*da14cebeSEric Cheng 		boolean_t	defval = B_FALSE;
608*da14cebeSEric Cheng 
609d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL)
610d62bc4baSyz147064 			return (DLADM_STATUS_NOTSUP);
611d62bc4baSyz147064 
6123bc21d0aSAruna Ramakrishna - Sun Microsystems 		cnt = 1;
613*da14cebeSEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
614*da14cebeSEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
615d62bc4baSyz147064 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
616d62bc4baSyz147064 				return (DLADM_STATUS_NOMEM);
6173bc21d0aSAruna Ramakrishna - Sun Microsystems 
618*da14cebeSEric Cheng 			if (defval) {
619*da14cebeSEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
620*da14cebeSEric Cheng 				    sizeof (val_desc_t));
621*da14cebeSEric Cheng 			} else if (pdp->pd_check != NULL) {
6223bc21d0aSAruna Ramakrishna - Sun Microsystems 				status = pdp->pd_check(pdp, linkid, prop_val,
6233bc21d0aSAruna Ramakrishna - Sun Microsystems 				    cnt, vdp, media);
6243bc21d0aSAruna Ramakrishna - Sun Microsystems 				if (status != DLADM_STATUS_OK)
6253bc21d0aSAruna Ramakrishna - Sun Microsystems 					goto done;
6263bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
6274045d941Ssowmini 		} else {
6284045d941Ssowmini 			status = i_dladm_getset_defval(pdp, linkid,
6294045d941Ssowmini 			    media, flags);
6304045d941Ssowmini 			return (status);
6314045d941Ssowmini 		}
632d62bc4baSyz147064 	}
6336b9e797cSsowmini 	status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media);
634d62bc4baSyz147064 	if (needfree) {
635d62bc4baSyz147064 		for (i = 0; i < cnt; i++)
636e7801d59Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
637d62bc4baSyz147064 	}
638d62bc4baSyz147064 done:
639d62bc4baSyz147064 	free(vdp);
640d62bc4baSyz147064 	return (status);
641d62bc4baSyz147064 }
642d62bc4baSyz147064 
643d62bc4baSyz147064 static dladm_status_t
644d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name,
645d62bc4baSyz147064     char **prop_val, uint_t val_cnt, uint_t flags)
646d62bc4baSyz147064 {
647d62bc4baSyz147064 	int			i;
648d62bc4baSyz147064 	boolean_t		found = B_FALSE;
649d62bc4baSyz147064 	datalink_class_t	class;
650d62bc4baSyz147064 	uint32_t		media;
651d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
652d62bc4baSyz147064 
653d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
654d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
6550ba2cbe9Sxc151355 		return (status);
6560ba2cbe9Sxc151355 
657d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
658d62bc4baSyz147064 		prop_desc_t	*pdp = &prop_table[i];
659d62bc4baSyz147064 		dladm_status_t	s;
6600ba2cbe9Sxc151355 
661d62bc4baSyz147064 		if (prop_name != NULL &&
662d62bc4baSyz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
663d62bc4baSyz147064 			continue;
664d62bc4baSyz147064 		found = B_TRUE;
665d62bc4baSyz147064 		s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val,
666d62bc4baSyz147064 		    val_cnt, flags);
667d62bc4baSyz147064 
668d62bc4baSyz147064 		if (prop_name != NULL) {
669d62bc4baSyz147064 			status = s;
670d62bc4baSyz147064 			break;
671d62bc4baSyz147064 		} else {
672d62bc4baSyz147064 			if (s != DLADM_STATUS_OK &&
673d62bc4baSyz147064 			    s != DLADM_STATUS_NOTSUP)
674d62bc4baSyz147064 				status = s;
675d62bc4baSyz147064 		}
676d62bc4baSyz147064 	}
677e7801d59Ssowmini 	if (!found) {
678e7801d59Ssowmini 		if (prop_name[0] == '_') {
679e7801d59Ssowmini 			/* other private properties */
6803bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = i_dladm_set_prop(linkid, prop_name, prop_val,
681e7801d59Ssowmini 			    val_cnt, flags);
682e7801d59Ssowmini 		} else  {
6830ba2cbe9Sxc151355 			status = DLADM_STATUS_NOTFOUND;
684e7801d59Ssowmini 		}
685e7801d59Ssowmini 	}
6860ba2cbe9Sxc151355 
6870ba2cbe9Sxc151355 	return (status);
6880ba2cbe9Sxc151355 }
6890ba2cbe9Sxc151355 
690d62bc4baSyz147064 /*
691d62bc4baSyz147064  * Set/reset link property for specific link
692d62bc4baSyz147064  */
693d62bc4baSyz147064 dladm_status_t
694d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val,
695d62bc4baSyz147064     uint_t val_cnt, uint_t flags)
6960ba2cbe9Sxc151355 {
697d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6980ba2cbe9Sxc151355 
699d62bc4baSyz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
700d62bc4baSyz147064 	    (prop_val == NULL && val_cnt > 0) ||
701d62bc4baSyz147064 	    (prop_val != NULL && val_cnt == 0) ||
702d62bc4baSyz147064 	    (prop_name == NULL && prop_val != NULL)) {
703d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
7040ba2cbe9Sxc151355 	}
7050ba2cbe9Sxc151355 
706d62bc4baSyz147064 	status = i_dladm_set_linkprop(linkid, prop_name, prop_val,
707d62bc4baSyz147064 	    val_cnt, flags);
708d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
709d62bc4baSyz147064 		return (status);
710d62bc4baSyz147064 
711d62bc4baSyz147064 	if (flags & DLADM_OPT_PERSIST) {
712d62bc4baSyz147064 		status = i_dladm_set_linkprop_db(linkid, prop_name,
713d62bc4baSyz147064 		    prop_val, val_cnt);
714d62bc4baSyz147064 	}
715d62bc4baSyz147064 	return (status);
716d62bc4baSyz147064 }
717d62bc4baSyz147064 
718d62bc4baSyz147064 /*
719d62bc4baSyz147064  * Walk link properties of the given specific link.
720d62bc4baSyz147064  */
721d62bc4baSyz147064 dladm_status_t
722d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg,
723d62bc4baSyz147064     int (*func)(datalink_id_t, const char *, void *))
7240ba2cbe9Sxc151355 {
725d62bc4baSyz147064 	dladm_status_t		status;
726d62bc4baSyz147064 	datalink_class_t	class;
727d62bc4baSyz147064 	uint_t			media;
728d62bc4baSyz147064 	int			i;
7290ba2cbe9Sxc151355 
730d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
731d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
7320ba2cbe9Sxc151355 
733d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
734d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
735d62bc4baSyz147064 		return (status);
736d62bc4baSyz147064 
737d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
738d62bc4baSyz147064 		if (!(prop_table[i].pd_class & class))
739d62bc4baSyz147064 			continue;
740d62bc4baSyz147064 
741d62bc4baSyz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
742d62bc4baSyz147064 			continue;
743d62bc4baSyz147064 
744d62bc4baSyz147064 		if (func(linkid, prop_table[i].pd_name, arg) ==
745d62bc4baSyz147064 		    DLADM_WALK_TERMINATE) {
746d62bc4baSyz147064 			break;
747d62bc4baSyz147064 		}
748d62bc4baSyz147064 	}
749d62bc4baSyz147064 
750d62bc4baSyz147064 	return (DLADM_STATUS_OK);
751d62bc4baSyz147064 }
752d62bc4baSyz147064 
753d62bc4baSyz147064 /*
754d62bc4baSyz147064  * Get linkprop of the given specific link.
755d62bc4baSyz147064  */
756d62bc4baSyz147064 dladm_status_t
757d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
758d62bc4baSyz147064     const char *prop_name, char **prop_val, uint_t *val_cntp)
759d62bc4baSyz147064 {
760d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
761d62bc4baSyz147064 	datalink_class_t	class;
762d62bc4baSyz147064 	uint_t			media;
763d62bc4baSyz147064 	prop_desc_t		*pdp;
7644045d941Ssowmini 	uint_t			cnt, dld_flags = 0;
765d62bc4baSyz147064 	int			i;
766afdda45fSVasumathi Sundaram - Sun Microsystems 	uint_t			perm_flags;
767d62bc4baSyz147064 
7684045d941Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
7693fd94f8cSam223141 		dld_flags = MAC_PROP_DEFAULT;
7704045d941Ssowmini 
771d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
772d62bc4baSyz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
773d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
774d62bc4baSyz147064 
775d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
776d62bc4baSyz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
777d62bc4baSyz147064 			break;
778d62bc4baSyz147064 
779e7801d59Ssowmini 	if (i == DLADM_MAX_PROPS) {
780e7801d59Ssowmini 		if (prop_name[0] == '_') {
781e7801d59Ssowmini 			/*
782e7801d59Ssowmini 			 * private property.
783e7801d59Ssowmini 			 */
7843bc21d0aSAruna Ramakrishna - Sun Microsystems 			return (i_dladm_get_prop(linkid, prop_name,
7854045d941Ssowmini 			    prop_val, val_cntp, type, dld_flags));
786e7801d59Ssowmini 		} else {
787d62bc4baSyz147064 			return (DLADM_STATUS_NOTFOUND);
788e7801d59Ssowmini 		}
789e7801d59Ssowmini 	}
790d62bc4baSyz147064 
791d62bc4baSyz147064 	pdp = &prop_table[i];
792d62bc4baSyz147064 
793d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
794d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
795d62bc4baSyz147064 		return (status);
796d62bc4baSyz147064 
797d62bc4baSyz147064 	if (!(pdp->pd_class & class))
798d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
799d62bc4baSyz147064 
800d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
801d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
802d62bc4baSyz147064 
803d62bc4baSyz147064 	switch (type) {
804d62bc4baSyz147064 	case DLADM_PROP_VAL_CURRENT:
8054045d941Ssowmini 		status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media,
806afdda45fSVasumathi Sundaram - Sun Microsystems 		    dld_flags, &perm_flags);
807afdda45fSVasumathi Sundaram - Sun Microsystems 		break;
808afdda45fSVasumathi Sundaram - Sun Microsystems 
809afdda45fSVasumathi Sundaram - Sun Microsystems 	case DLADM_PROP_VAL_PERM:
810afdda45fSVasumathi Sundaram - Sun Microsystems 		if (pdp->pd_set == NULL) {
811afdda45fSVasumathi Sundaram - Sun Microsystems 			perm_flags = MAC_PROP_PERM_READ;
812afdda45fSVasumathi Sundaram - Sun Microsystems 			*val_cntp = 1;
813afdda45fSVasumathi Sundaram - Sun Microsystems 		} else {
814afdda45fSVasumathi Sundaram - Sun Microsystems 			status = pdp->pd_get(pdp, linkid, prop_val, val_cntp,
815afdda45fSVasumathi Sundaram - Sun Microsystems 			    media, dld_flags, &perm_flags);
816afdda45fSVasumathi Sundaram - Sun Microsystems 		}
817afdda45fSVasumathi Sundaram - Sun Microsystems 
818afdda45fSVasumathi Sundaram - Sun Microsystems 		*prop_val[0] = '\0';
819*da14cebeSEric Cheng 		if (status == DLADM_STATUS_OK)
820*da14cebeSEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
821d62bc4baSyz147064 		break;
822d62bc4baSyz147064 
823d62bc4baSyz147064 	case DLADM_PROP_VAL_DEFAULT:
82413a55820Sar224390 		/*
82513a55820Sar224390 		 * If defaults are not defined for the property,
82613a55820Sar224390 		 * pd_defval.vd_name should be null. If the driver
82713a55820Sar224390 		 * has to be contacted for the value, vd_name should
82813a55820Sar224390 		 * be the empty string (""). Otherwise, dladm will
82913a55820Sar224390 		 * just print whatever is in the table.
83013a55820Sar224390 		 */
831d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL) {
832d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
833d62bc4baSyz147064 			break;
834d62bc4baSyz147064 		}
8354045d941Ssowmini 
8364045d941Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
8374045d941Ssowmini 			status = pdp->pd_get(pdp, linkid, prop_val, val_cntp,
838afdda45fSVasumathi Sundaram - Sun Microsystems 			    media, dld_flags, &perm_flags);
8394045d941Ssowmini 		} else {
840d62bc4baSyz147064 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
8414045d941Ssowmini 		}
842d62bc4baSyz147064 		*val_cntp = 1;
843d62bc4baSyz147064 		break;
844d62bc4baSyz147064 
845d62bc4baSyz147064 	case DLADM_PROP_VAL_MODIFIABLE:
846d62bc4baSyz147064 		if (pdp->pd_getmod != NULL) {
847e7801d59Ssowmini 			status = pdp->pd_getmod(pdp, linkid, prop_val,
848afdda45fSVasumathi Sundaram - Sun Microsystems 			    val_cntp, media, dld_flags, &perm_flags);
849d62bc4baSyz147064 			break;
850d62bc4baSyz147064 		}
851d62bc4baSyz147064 		cnt = pdp->pd_noptval;
852d62bc4baSyz147064 		if (cnt == 0) {
853d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
854d62bc4baSyz147064 		} else if (cnt > *val_cntp) {
855d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
856d62bc4baSyz147064 		} else {
857d62bc4baSyz147064 			for (i = 0; i < cnt; i++) {
858d62bc4baSyz147064 				(void) strcpy(prop_val[i],
859d62bc4baSyz147064 				    pdp->pd_optval[i].vd_name);
860d62bc4baSyz147064 			}
861d62bc4baSyz147064 			*val_cntp = cnt;
862d62bc4baSyz147064 		}
863d62bc4baSyz147064 		break;
864d62bc4baSyz147064 	case DLADM_PROP_VAL_PERSISTENT:
865d62bc4baSyz147064 		if (pdp->pd_flags & PD_TEMPONLY)
866d62bc4baSyz147064 			return (DLADM_STATUS_TEMPONLY);
867d62bc4baSyz147064 		status = i_dladm_get_linkprop_db(linkid, prop_name,
868d62bc4baSyz147064 		    prop_val, val_cntp);
869d62bc4baSyz147064 		break;
870d62bc4baSyz147064 	default:
871d62bc4baSyz147064 		status = DLADM_STATUS_BADARG;
872d62bc4baSyz147064 		break;
873d62bc4baSyz147064 	}
874d62bc4baSyz147064 
875d62bc4baSyz147064 	return (status);
876d62bc4baSyz147064 }
877d62bc4baSyz147064 
878d62bc4baSyz147064 /*ARGSUSED*/
879d62bc4baSyz147064 static int
880d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg)
881d62bc4baSyz147064 {
882d62bc4baSyz147064 	char	*buf, **propvals;
883d62bc4baSyz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
884d62bc4baSyz147064 
885d62bc4baSyz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
886d62bc4baSyz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
887d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
888d62bc4baSyz147064 	}
889d62bc4baSyz147064 
890d62bc4baSyz147064 	propvals = (char **)(void *)buf;
891d62bc4baSyz147064 	for (i = 0; i < valcnt; i++) {
892d62bc4baSyz147064 		propvals[i] = buf +
893d62bc4baSyz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
894d62bc4baSyz147064 		    i * DLADM_PROP_VAL_MAX;
895d62bc4baSyz147064 	}
896d62bc4baSyz147064 
897d62bc4baSyz147064 	if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name,
898d62bc4baSyz147064 	    propvals, &valcnt) != DLADM_STATUS_OK) {
899d62bc4baSyz147064 		goto done;
900d62bc4baSyz147064 	}
901d62bc4baSyz147064 
902d62bc4baSyz147064 	(void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt,
903d62bc4baSyz147064 	    DLADM_OPT_ACTIVE);
904d62bc4baSyz147064 
905d62bc4baSyz147064 done:
906d62bc4baSyz147064 	if (buf != NULL)
907d62bc4baSyz147064 		free(buf);
908d62bc4baSyz147064 
909d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
910d62bc4baSyz147064 }
911d62bc4baSyz147064 
912d62bc4baSyz147064 /*ARGSUSED*/
913d62bc4baSyz147064 static int
914d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg)
915d62bc4baSyz147064 {
916*da14cebeSEric Cheng 	datalink_class_t	class;
917*da14cebeSEric Cheng 	dladm_status_t		status;
918*da14cebeSEric Cheng 
919*da14cebeSEric Cheng 	status = dladm_datalink_id2info(linkid, NULL, &class, NULL, NULL, 0);
920*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
921*da14cebeSEric Cheng 		return (DLADM_WALK_TERMINATE);
922*da14cebeSEric Cheng 
923*da14cebeSEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
92430890389Sartem 		(void) dladm_init_linkprop(linkid, B_TRUE);
925*da14cebeSEric Cheng 
926d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
9270ba2cbe9Sxc151355 }
9280ba2cbe9Sxc151355 
9290ba2cbe9Sxc151355 dladm_status_t
93030890389Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media)
9310ba2cbe9Sxc151355 {
93230890389Sartem 	datalink_media_t	dmedia;
93330890389Sartem 	uint32_t		media;
93430890389Sartem 
93530890389Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
93630890389Sartem 
937d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
938d62bc4baSyz147064 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL,
93930890389Sartem 		    DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
94030890389Sartem 	} else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL,
94130890389Sartem 	    &media, NULL, 0) == DLADM_STATUS_OK) &&
94230890389Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
943d62bc4baSyz147064 		(void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop);
944d62bc4baSyz147064 	}
945d62bc4baSyz147064 	return (DLADM_STATUS_OK);
9460ba2cbe9Sxc151355 }
947f4b3ec61Sdh155122 
948e7801d59Ssowmini /* ARGSUSED */
949f4b3ec61Sdh155122 static dladm_status_t
950*da14cebeSEric Cheng do_get_zone(prop_desc_t *pdp, datalink_id_t linkid,
951*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
952*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
953f4b3ec61Sdh155122 {
954d62bc4baSyz147064 	char			zone_name[ZONENAME_MAX];
955d62bc4baSyz147064 	zoneid_t		zid;
956d62bc4baSyz147064 	dladm_status_t		status;
9573bc21d0aSAruna Ramakrishna - Sun Microsystems 	char			*cp;
9583bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
959f4b3ec61Sdh155122 
9604045d941Ssowmini 	if (flags != 0)
9614045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
9624045d941Ssowmini 
963*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
964*da14cebeSEric Cheng 	    &status, perm_flags);
965d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
966d62bc4baSyz147064 		return (status);
967d62bc4baSyz147064 
9683bc21d0aSAruna Ramakrishna - Sun Microsystems 	cp = dip->pr_val;
9693bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&zid, cp, sizeof (zid));
9703bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
9713bc21d0aSAruna Ramakrishna - Sun Microsystems 
972d62bc4baSyz147064 	*val_cnt = 1;
973d62bc4baSyz147064 	if (zid != GLOBAL_ZONEID) {
974afdda45fSVasumathi Sundaram - Sun Microsystems 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
975f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
976afdda45fSVasumathi Sundaram - Sun Microsystems 		}
977f4b3ec61Sdh155122 
978d62bc4baSyz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
97947a01978Sbw 	} else {
980d62bc4baSyz147064 		*prop_val[0] = '\0';
98147a01978Sbw 	}
982f4b3ec61Sdh155122 
983f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
984f4b3ec61Sdh155122 }
985f4b3ec61Sdh155122 
986f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
987f4b3ec61Sdh155122 
988f4b3ec61Sdh155122 static int
989f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
990f4b3ec61Sdh155122 {
991f4b3ec61Sdh155122 	char			root[MAXPATHLEN];
992f4b3ec61Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
993f4b3ec61Sdh155122 	void			*dlhandle;
994f4b3ec61Sdh155122 	void			*sym;
995f4b3ec61Sdh155122 	int			ret;
996f4b3ec61Sdh155122 
997f4b3ec61Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
998f4b3ec61Sdh155122 		return (-1);
999f4b3ec61Sdh155122 
1000f4b3ec61Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
1001f4b3ec61Sdh155122 		(void) dlclose(dlhandle);
1002f4b3ec61Sdh155122 		return (-1);
1003f4b3ec61Sdh155122 	}
1004f4b3ec61Sdh155122 
1005f4b3ec61Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
1006f4b3ec61Sdh155122 
1007f4b3ec61Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
1008f4b3ec61Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
1009f4b3ec61Sdh155122 	(void) dlclose(dlhandle);
1010f4b3ec61Sdh155122 	return (ret);
1011f4b3ec61Sdh155122 }
1012f4b3ec61Sdh155122 
1013f4b3ec61Sdh155122 static dladm_status_t
1014d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add)
1015f4b3ec61Sdh155122 {
1016f4b3ec61Sdh155122 	char		path[MAXPATHLEN];
1017d62bc4baSyz147064 	char		name[MAXLINKNAMELEN];
1018f4b3ec61Sdh155122 	di_prof_t	prof = NULL;
1019f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
1020f4b3ec61Sdh155122 	dladm_status_t	status;
1021d62bc4baSyz147064 	int		ret;
1022f4b3ec61Sdh155122 
1023f4b3ec61Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
1024f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
1025f4b3ec61Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
1026f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
1027f4b3ec61Sdh155122 	if (di_prof_init(path, &prof) != 0)
1028f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
1029f4b3ec61Sdh155122 
1030d62bc4baSyz147064 	status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN);
1031f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
1032d62bc4baSyz147064 		goto cleanup;
1033f4b3ec61Sdh155122 
1034d62bc4baSyz147064 	if (add)
1035d62bc4baSyz147064 		ret = di_prof_add_dev(prof, name);
1036d62bc4baSyz147064 	else
1037d62bc4baSyz147064 		ret = di_prof_add_exclude(prof, name);
1038f4b3ec61Sdh155122 
1039d62bc4baSyz147064 	if (ret != 0) {
1040d62bc4baSyz147064 		status = dladm_errno2status(errno);
1041d62bc4baSyz147064 		goto cleanup;
1042f4b3ec61Sdh155122 	}
1043f4b3ec61Sdh155122 
1044d62bc4baSyz147064 	if (di_prof_commit(prof) != 0)
1045d62bc4baSyz147064 		status = dladm_errno2status(errno);
1046d62bc4baSyz147064 cleanup:
1047d62bc4baSyz147064 	if (prof)
1048d62bc4baSyz147064 		di_prof_fini(prof);
1049d62bc4baSyz147064 
1050d62bc4baSyz147064 	return (status);
1051f4b3ec61Sdh155122 }
1052f4b3ec61Sdh155122 
1053e7801d59Ssowmini /* ARGSUSED */
1054f4b3ec61Sdh155122 static dladm_status_t
1055*da14cebeSEric Cheng do_set_zone(prop_desc_t *pdp, datalink_id_t linkid, val_desc_t *vdp,
10566b9e797cSsowmini     uint_t val_cnt, uint_t flags, datalink_media_t media)
1057f4b3ec61Sdh155122 {
10583bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t		status = DLADM_STATUS_OK;
1059f4b3ec61Sdh155122 	zoneid_t		zid_old, zid_new;
1060d62bc4baSyz147064 	char			link[MAXLINKNAMELEN];
10613bc21d0aSAruna Ramakrishna - Sun Microsystems 	char			*cp;
10623bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
10633bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t		*dzp;
1064f4b3ec61Sdh155122 
1065f4b3ec61Sdh155122 	if (val_cnt != 1)
1066f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
1067f4b3ec61Sdh155122 
10683bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
10693bc21d0aSAruna Ramakrishna - Sun Microsystems 
1070*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
1071*da14cebeSEric Cheng 	    &status, NULL);
1072f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
1073f4b3ec61Sdh155122 		return (status);
1074f4b3ec61Sdh155122 
10753bc21d0aSAruna Ramakrishna - Sun Microsystems 	cp = dip->pr_val;
10763bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
10773bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
1078f4b3ec61Sdh155122 
10793bc21d0aSAruna Ramakrishna - Sun Microsystems 	zid_new = dzp->diz_zid;
10803bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
10813bc21d0aSAruna Ramakrishna - Sun Microsystems 
10823bc21d0aSAruna Ramakrishna - Sun Microsystems 	/* Do nothing if setting to current value */
10833bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new == zid_old)
10843bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (status);
10853bc21d0aSAruna Ramakrishna - Sun Microsystems 
1086d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
1087d62bc4baSyz147064 		/*
1088d62bc4baSyz147064 		 * If the new zoneid is the global zone, we could destroy
1089d62bc4baSyz147064 		 * the link (in the case of an implicitly-created VLAN) as a
10903bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * result of setting the zoneid. In that case, we defer the
10913bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * operation to the end of this function to avoid recreating
10923bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * the VLAN and getting a different linkid during the rollback
10933bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * if other operation fails.
1094d62bc4baSyz147064 		 *
10953bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * Otherwise, this operation will hold a reference to the
1096d62bc4baSyz147064 		 * link and prevent a link renaming, so we need to do it
1097d62bc4baSyz147064 		 * before other operations.
1098d62bc4baSyz147064 		 */
1099*da14cebeSEric Cheng 		status = i_dladm_set_public_prop(pdp, linkid, vdp, val_cnt,
11003bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1101d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
1102d62bc4baSyz147064 			return (status);
1103d62bc4baSyz147064 	}
1104d62bc4baSyz147064 
1105d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID) {
1106d62bc4baSyz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
1107f4b3ec61Sdh155122 		    errno != ENXIO) {
1108f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
1109f4b3ec61Sdh155122 			goto rollback1;
1110f4b3ec61Sdh155122 		}
1111f4b3ec61Sdh155122 
1112d62bc4baSyz147064 		/*
1113d62bc4baSyz147064 		 * It is okay to fail to update the /dev entry (some
1114d62bc4baSyz147064 		 * vanity-named links do not have a /dev entry).
1115d62bc4baSyz147064 		 */
1116d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_FALSE);
1117d62bc4baSyz147064 	}
1118d62bc4baSyz147064 
1119d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
1120d62bc4baSyz147064 		if (zone_add_datalink(zid_new, link) != 0) {
1121d62bc4baSyz147064 			status = dladm_errno2status(errno);
1122d62bc4baSyz147064 			goto rollback2;
1123d62bc4baSyz147064 		}
1124d62bc4baSyz147064 
1125d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_new, linkid, B_TRUE);
1126d62bc4baSyz147064 	} else {
1127*da14cebeSEric Cheng 		status = i_dladm_set_public_prop(pdp, linkid, vdp, val_cnt,
11283bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1129f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
1130f4b3ec61Sdh155122 			goto rollback2;
1131f4b3ec61Sdh155122 	}
1132f4b3ec61Sdh155122 
1133f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1134f4b3ec61Sdh155122 
1135f4b3ec61Sdh155122 rollback2:
1136f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID)
1137d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_TRUE);
1138d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID)
1139d62bc4baSyz147064 		(void) zone_add_datalink(zid_old, link);
1140f4b3ec61Sdh155122 rollback1:
11413bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new != GLOBAL_ZONEID) {
11423bc21d0aSAruna Ramakrishna - Sun Microsystems 		dzp->diz_zid = zid_old;
1143*da14cebeSEric Cheng 		(void) i_dladm_set_public_prop(pdp, linkid, vdp, val_cnt,
11443bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
11453bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11463bc21d0aSAruna Ramakrishna - Sun Microsystems 
1147f4b3ec61Sdh155122 	return (status);
1148f4b3ec61Sdh155122 }
1149f4b3ec61Sdh155122 
1150f4b3ec61Sdh155122 /* ARGSUSED */
1151f4b3ec61Sdh155122 static dladm_status_t
1152*da14cebeSEric Cheng do_check_zone(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
11536b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1154f4b3ec61Sdh155122 {
11553bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*zone_name;
11563bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		linkname[MAXLINKNAMELEN];
11573bc21d0aSAruna Ramakrishna - Sun Microsystems 	zoneid_t	zoneid;
11583bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status = DLADM_STATUS_OK;
11593bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t	*dzp;
1160f4b3ec61Sdh155122 
1161f4b3ec61Sdh155122 	if (val_cnt != 1)
1162f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
1163f4b3ec61Sdh155122 
11643bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = malloc(sizeof (dld_ioc_zid_t));
11653bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dzp == NULL)
11663bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (DLADM_STATUS_NOMEM);
1167f4b3ec61Sdh155122 
11683bc21d0aSAruna Ramakrishna - Sun Microsystems 	if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL,
11693bc21d0aSAruna Ramakrishna - Sun Microsystems 	    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
11703bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
11713bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11723bc21d0aSAruna Ramakrishna - Sun Microsystems 
1173*da14cebeSEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
11743bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (strlen(linkname) > MAXLINKNAMELEN) {
11753bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
11763bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
11773bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11783bc21d0aSAruna Ramakrishna - Sun Microsystems 
11793bc21d0aSAruna Ramakrishna - Sun Microsystems 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
11803bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
11813bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
11823bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11833bc21d0aSAruna Ramakrishna - Sun Microsystems 
11843bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zoneid != GLOBAL_ZONEID) {
1185f4b3ec61Sdh155122 		ushort_t	flags;
1186f4b3ec61Sdh155122 
11873bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
1188f4b3ec61Sdh155122 		    sizeof (flags)) < 0) {
11893bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = dladm_errno2status(errno);
11903bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1191f4b3ec61Sdh155122 		}
1192f4b3ec61Sdh155122 
1193f4b3ec61Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
11943bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = DLADM_STATUS_BADVAL;
11953bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1196f4b3ec61Sdh155122 		}
1197f4b3ec61Sdh155122 	}
1198f4b3ec61Sdh155122 
11993bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
12003bc21d0aSAruna Ramakrishna - Sun Microsystems 
12013bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp->diz_zid = zoneid;
12023bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
12033bc21d0aSAruna Ramakrishna - Sun Microsystems 
12043bc21d0aSAruna Ramakrishna - Sun Microsystems 	vdp->vd_val = (uintptr_t)dzp;
1205f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
12063bc21d0aSAruna Ramakrishna - Sun Microsystems done:
12073bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dzp);
12083bc21d0aSAruna Ramakrishna - Sun Microsystems 	return (status);
1209f4b3ec61Sdh155122 }
1210f4b3ec61Sdh155122 
1211e7801d59Ssowmini /* ARGSUSED */
1212f4b3ec61Sdh155122 static dladm_status_t
1213*da14cebeSEric Cheng dld_maxbw_get(prop_desc_t *pdp, datalink_id_t linkid,
1214*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1215*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1216*da14cebeSEric Cheng {
1217*da14cebeSEric Cheng 	dld_ioc_macprop_t	*dip;
1218*da14cebeSEric Cheng 	mac_resource_props_t	mrp;
1219*da14cebeSEric Cheng 	dladm_status_t		status;
1220*da14cebeSEric Cheng 
1221*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
1222*da14cebeSEric Cheng 	    &status, perm_flags);
1223*da14cebeSEric Cheng 	if (dip == NULL)
1224*da14cebeSEric Cheng 		return (status);
1225*da14cebeSEric Cheng 
1226*da14cebeSEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
1227*da14cebeSEric Cheng 	free(dip);
1228*da14cebeSEric Cheng 
1229*da14cebeSEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
1230*da14cebeSEric Cheng 		(*prop_val)[0] = '\0';
1231*da14cebeSEric Cheng 	} else {
1232*da14cebeSEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
1233*da14cebeSEric Cheng 	}
1234*da14cebeSEric Cheng 	*val_cnt = 1;
1235*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1236*da14cebeSEric Cheng }
1237*da14cebeSEric Cheng 
1238*da14cebeSEric Cheng /* ARGSUSED */
1239*da14cebeSEric Cheng static dladm_status_t
1240*da14cebeSEric Cheng do_check_maxbw(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
1241*da14cebeSEric Cheng     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1242*da14cebeSEric Cheng {
1243*da14cebeSEric Cheng 	uint64_t	*maxbw;
1244*da14cebeSEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
1245*da14cebeSEric Cheng 
1246*da14cebeSEric Cheng 	if (val_cnt != 1)
1247*da14cebeSEric Cheng 		return (DLADM_STATUS_BADVALCNT);
1248*da14cebeSEric Cheng 
1249*da14cebeSEric Cheng 	maxbw = malloc(sizeof (uint64_t));
1250*da14cebeSEric Cheng 	if (maxbw == NULL)
1251*da14cebeSEric Cheng 		return (DLADM_STATUS_NOMEM);
1252*da14cebeSEric Cheng 
1253*da14cebeSEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
1254*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK) {
1255*da14cebeSEric Cheng 		free(maxbw);
1256*da14cebeSEric Cheng 		return (status);
1257*da14cebeSEric Cheng 	}
1258*da14cebeSEric Cheng 
1259*da14cebeSEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
1260*da14cebeSEric Cheng 		free(maxbw);
1261*da14cebeSEric Cheng 		return (DLADM_STATUS_MINMAXBW);
1262*da14cebeSEric Cheng 	}
1263*da14cebeSEric Cheng 
1264*da14cebeSEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
1265*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1266*da14cebeSEric Cheng }
1267*da14cebeSEric Cheng 
1268*da14cebeSEric Cheng /* ARGSUSED */
1269*da14cebeSEric Cheng dladm_status_t
1270*da14cebeSEric Cheng do_extract_maxbw(val_desc_t *vdp, void *arg, uint_t cnt)
1271*da14cebeSEric Cheng {
1272*da14cebeSEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
1273*da14cebeSEric Cheng 
1274*da14cebeSEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
1275*da14cebeSEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
1276*da14cebeSEric Cheng 
1277*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1278*da14cebeSEric Cheng }
1279*da14cebeSEric Cheng 
1280*da14cebeSEric Cheng /* ARGSUSED */
1281*da14cebeSEric Cheng static dladm_status_t
1282*da14cebeSEric Cheng dld_cpus_get(prop_desc_t *pdp, datalink_id_t linkid,
1283*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1284*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1285*da14cebeSEric Cheng {
1286*da14cebeSEric Cheng 	dld_ioc_macprop_t	*dip;
1287*da14cebeSEric Cheng 	mac_resource_props_t	mrp;
1288*da14cebeSEric Cheng 	int			i;
1289*da14cebeSEric Cheng 	uint32_t		ncpus;
1290*da14cebeSEric Cheng 	uchar_t			*cp;
1291*da14cebeSEric Cheng 	dladm_status_t		status;
1292*da14cebeSEric Cheng 
1293*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
1294*da14cebeSEric Cheng 	    &status, perm_flags);
1295*da14cebeSEric Cheng 	if (dip == NULL)
1296*da14cebeSEric Cheng 		return (status);
1297*da14cebeSEric Cheng 
1298*da14cebeSEric Cheng 	cp = (uchar_t *)dip->pr_val;
1299*da14cebeSEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
1300*da14cebeSEric Cheng 	free(dip);
1301*da14cebeSEric Cheng 
1302*da14cebeSEric Cheng 	ncpus = mrp.mrp_ncpus;
1303*da14cebeSEric Cheng 
1304*da14cebeSEric Cheng 	if (ncpus > *val_cnt)
1305*da14cebeSEric Cheng 		return (DLADM_STATUS_TOOSMALL);
1306*da14cebeSEric Cheng 
1307*da14cebeSEric Cheng 	if (ncpus == 0) {
1308*da14cebeSEric Cheng 		(*prop_val)[0] = '\0';
1309*da14cebeSEric Cheng 		*val_cnt = 1;
1310*da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
1311*da14cebeSEric Cheng 	}
1312*da14cebeSEric Cheng 
1313*da14cebeSEric Cheng 	*val_cnt = ncpus;
1314*da14cebeSEric Cheng 	for (i = 0; i < ncpus; i++) {
1315*da14cebeSEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
1316*da14cebeSEric Cheng 		    "%u", mrp.mrp_cpu[i]);
1317*da14cebeSEric Cheng 	}
1318*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1319*da14cebeSEric Cheng }
1320*da14cebeSEric Cheng 
1321*da14cebeSEric Cheng /* ARGSUSED */
1322*da14cebeSEric Cheng static dladm_status_t
1323*da14cebeSEric Cheng do_set_res(prop_desc_t *pdp, datalink_id_t linkid, val_desc_t *vdp,
1324*da14cebeSEric Cheng     uint_t val_cnt, uint_t flags, datalink_media_t media)
1325*da14cebeSEric Cheng {
1326*da14cebeSEric Cheng 	mac_resource_props_t	mrp;
1327*da14cebeSEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
1328*da14cebeSEric Cheng 	dld_ioc_macprop_t	*dip;
1329*da14cebeSEric Cheng 
1330*da14cebeSEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
1331*da14cebeSEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
1332*da14cebeSEric Cheng 	    flags, &status);
1333*da14cebeSEric Cheng 
1334*da14cebeSEric Cheng 	if (dip == NULL)
1335*da14cebeSEric Cheng 		return (status);
1336*da14cebeSEric Cheng 
1337*da14cebeSEric Cheng 	if (vdp->vd_val == RESET_VAL) {
1338*da14cebeSEric Cheng 		switch (dip->pr_num) {
1339*da14cebeSEric Cheng 		case MAC_PROP_MAXBW:
1340*da14cebeSEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
1341*da14cebeSEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
1342*da14cebeSEric Cheng 			break;
1343*da14cebeSEric Cheng 		case MAC_PROP_PRIO:
1344*da14cebeSEric Cheng 			mrp.mrp_priority = MPL_RESET;
1345*da14cebeSEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
1346*da14cebeSEric Cheng 			break;
1347*da14cebeSEric Cheng 		default:
1348*da14cebeSEric Cheng 			free(dip);
1349*da14cebeSEric Cheng 			return (DLADM_STATUS_BADARG);
1350*da14cebeSEric Cheng 		}
1351*da14cebeSEric Cheng 	} else {
1352*da14cebeSEric Cheng 		switch (dip->pr_num) {
1353*da14cebeSEric Cheng 		case MAC_PROP_MAXBW:
1354*da14cebeSEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
1355*da14cebeSEric Cheng 			    sizeof (uint64_t));
1356*da14cebeSEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
1357*da14cebeSEric Cheng 			break;
1358*da14cebeSEric Cheng 		case MAC_PROP_PRIO:
1359*da14cebeSEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
1360*da14cebeSEric Cheng 			    sizeof (mac_priority_level_t));
1361*da14cebeSEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
1362*da14cebeSEric Cheng 			break;
1363*da14cebeSEric Cheng 		default:
1364*da14cebeSEric Cheng 			free(dip);
1365*da14cebeSEric Cheng 			return (DLADM_STATUS_BADARG);
1366*da14cebeSEric Cheng 		}
1367*da14cebeSEric Cheng 	}
1368*da14cebeSEric Cheng 
1369*da14cebeSEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
1370*da14cebeSEric Cheng 	status = i_dladm_macprop(dip, B_TRUE);
1371*da14cebeSEric Cheng 	free(dip);
1372*da14cebeSEric Cheng 	return (status);
1373*da14cebeSEric Cheng }
1374*da14cebeSEric Cheng 
1375*da14cebeSEric Cheng /* ARGSUSED */
1376*da14cebeSEric Cheng static dladm_status_t
1377*da14cebeSEric Cheng do_set_cpus(prop_desc_t *pdp, datalink_id_t linkid, val_desc_t *vdp,
1378*da14cebeSEric Cheng     uint_t val_cnt, uint_t flags, datalink_media_t media)
1379*da14cebeSEric Cheng {
1380*da14cebeSEric Cheng 	mac_resource_props_t	mrp;
1381*da14cebeSEric Cheng 	dladm_status_t		status;
1382*da14cebeSEric Cheng 	dld_ioc_macprop_t	*dip;
1383*da14cebeSEric Cheng 	datalink_class_t	class;
1384*da14cebeSEric Cheng 
1385*da14cebeSEric Cheng 	/*
1386*da14cebeSEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
1387*da14cebeSEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
1388*da14cebeSEric Cheng 	 * the phys_info test only on physical links.
1389*da14cebeSEric Cheng 	 */
1390*da14cebeSEric Cheng 	if ((status = dladm_datalink_id2info(linkid, NULL, &class,
1391*da14cebeSEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
1392*da14cebeSEric Cheng 		return (status);
1393*da14cebeSEric Cheng 	}
1394*da14cebeSEric Cheng 
1395*da14cebeSEric Cheng 	/*
1396*da14cebeSEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
1397*da14cebeSEric Cheng 	 * if possible when the setup is complete in MAC.
1398*da14cebeSEric Cheng 	 */
1399*da14cebeSEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
1400*da14cebeSEric Cheng 	mrp.mrp_mask = MRP_CPUS;
1401*da14cebeSEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
1402*da14cebeSEric Cheng 		mac_resource_props_t	*vmrp;
1403*da14cebeSEric Cheng 
1404*da14cebeSEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
1405*da14cebeSEric Cheng 		if (vmrp->mrp_ncpus > 0) {
1406*da14cebeSEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
1407*da14cebeSEric Cheng 			mrp.mrp_mask = MRP_CPUS;
1408*da14cebeSEric Cheng 		}
1409*da14cebeSEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
1410*da14cebeSEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
1411*da14cebeSEric Cheng 		mrp.mrp_intr_cpu = -1;
1412*da14cebeSEric Cheng 	}
1413*da14cebeSEric Cheng 
1414*da14cebeSEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
1415*da14cebeSEric Cheng 	    flags, &status);
1416*da14cebeSEric Cheng 	if (dip == NULL)
1417*da14cebeSEric Cheng 		return (status);
1418*da14cebeSEric Cheng 
1419*da14cebeSEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
1420*da14cebeSEric Cheng 	status = i_dladm_macprop(dip, B_TRUE);
1421*da14cebeSEric Cheng 	free(dip);
1422*da14cebeSEric Cheng 	return (status);
1423*da14cebeSEric Cheng }
1424*da14cebeSEric Cheng 
1425*da14cebeSEric Cheng /* ARGSUSED */
1426*da14cebeSEric Cheng static dladm_status_t
1427*da14cebeSEric Cheng do_check_cpus(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
1428*da14cebeSEric Cheng     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1429*da14cebeSEric Cheng {
1430*da14cebeSEric Cheng 	uint32_t		cpuid;
1431*da14cebeSEric Cheng 	int			i, j, rc;
1432*da14cebeSEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
1433*da14cebeSEric Cheng 	mac_resource_props_t	*mrp;
1434*da14cebeSEric Cheng 
1435*da14cebeSEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
1436*da14cebeSEric Cheng 	if (mrp == NULL)
1437*da14cebeSEric Cheng 		return (DLADM_STATUS_NOMEM);
1438*da14cebeSEric Cheng 
1439*da14cebeSEric Cheng 	for (i = 0; i < val_cnt; i++) {
1440*da14cebeSEric Cheng 		errno = 0;
1441*da14cebeSEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
1442*da14cebeSEric Cheng 		if (errno != 0 || cpuid >= nproc) {
1443*da14cebeSEric Cheng 			free(mrp);
1444*da14cebeSEric Cheng 			return (DLADM_STATUS_CPUMAX);
1445*da14cebeSEric Cheng 		}
1446*da14cebeSEric Cheng 		rc = p_online(cpuid, P_STATUS);
1447*da14cebeSEric Cheng 		if (rc < 1) {
1448*da14cebeSEric Cheng 			free(mrp);
1449*da14cebeSEric Cheng 			return (DLADM_STATUS_CPUERR);
1450*da14cebeSEric Cheng 		}
1451*da14cebeSEric Cheng 		if (rc != P_ONLINE) {
1452*da14cebeSEric Cheng 			free(mrp);
1453*da14cebeSEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
1454*da14cebeSEric Cheng 		}
1455*da14cebeSEric Cheng 		mrp->mrp_cpu[i] = cpuid;
1456*da14cebeSEric Cheng 	}
1457*da14cebeSEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
1458*da14cebeSEric Cheng 
1459*da14cebeSEric Cheng 	/* Check for duplicates */
1460*da14cebeSEric Cheng 	for (i = 0; i < val_cnt; i++) {
1461*da14cebeSEric Cheng 		for (j = 0; j < val_cnt; j++) {
1462*da14cebeSEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
1463*da14cebeSEric Cheng 				free(mrp);
1464*da14cebeSEric Cheng 				return (DLADM_STATUS_BADARG);
1465*da14cebeSEric Cheng 			}
1466*da14cebeSEric Cheng 		}
1467*da14cebeSEric Cheng 	}
1468*da14cebeSEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
1469*da14cebeSEric Cheng 
1470*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1471*da14cebeSEric Cheng }
1472*da14cebeSEric Cheng 
1473*da14cebeSEric Cheng /* ARGSUSED */
1474*da14cebeSEric Cheng dladm_status_t
1475*da14cebeSEric Cheng do_extract_cpus(val_desc_t *vdp, void *arg, uint_t cnt)
1476*da14cebeSEric Cheng {
1477*da14cebeSEric Cheng 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
1478*da14cebeSEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
1479*da14cebeSEric Cheng 	int			i;
1480*da14cebeSEric Cheng 
1481*da14cebeSEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
1482*da14cebeSEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
1483*da14cebeSEric Cheng 	}
1484*da14cebeSEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
1485*da14cebeSEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
1486*da14cebeSEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
1487*da14cebeSEric Cheng 
1488*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1489*da14cebeSEric Cheng }
1490*da14cebeSEric Cheng 
1491*da14cebeSEric Cheng /* ARGSUSED */
1492*da14cebeSEric Cheng static dladm_status_t
1493*da14cebeSEric Cheng dld_priority_get(prop_desc_t *pdp, datalink_id_t linkid,
1494*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1495*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1496*da14cebeSEric Cheng {
1497*da14cebeSEric Cheng 	dld_ioc_macprop_t	*dip;
1498*da14cebeSEric Cheng 	mac_resource_props_t	mrp;
1499*da14cebeSEric Cheng 	mac_priority_level_t	pri;
1500*da14cebeSEric Cheng 	dladm_status_t		status;
1501*da14cebeSEric Cheng 
1502*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
1503*da14cebeSEric Cheng 	    &status, perm_flags);
1504*da14cebeSEric Cheng 	if (dip == NULL)
1505*da14cebeSEric Cheng 		return (status);
1506*da14cebeSEric Cheng 
1507*da14cebeSEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
1508*da14cebeSEric Cheng 	free(dip);
1509*da14cebeSEric Cheng 
1510*da14cebeSEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
1511*da14cebeSEric Cheng 	    mrp.mrp_priority;
1512*da14cebeSEric Cheng 
1513*da14cebeSEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
1514*da14cebeSEric Cheng 	*val_cnt = 1;
1515*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1516*da14cebeSEric Cheng }
1517*da14cebeSEric Cheng 
1518*da14cebeSEric Cheng /* ARGSUSED */
1519*da14cebeSEric Cheng static dladm_status_t
1520*da14cebeSEric Cheng do_check_priority(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
1521*da14cebeSEric Cheng     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1522*da14cebeSEric Cheng {
1523*da14cebeSEric Cheng 	mac_priority_level_t	*pri;
1524*da14cebeSEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
1525*da14cebeSEric Cheng 
1526*da14cebeSEric Cheng 	if (val_cnt != 1)
1527*da14cebeSEric Cheng 		return (DLADM_STATUS_BADVALCNT);
1528*da14cebeSEric Cheng 
1529*da14cebeSEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
1530*da14cebeSEric Cheng 	if (pri == NULL)
1531*da14cebeSEric Cheng 		return (DLADM_STATUS_NOMEM);
1532*da14cebeSEric Cheng 
1533*da14cebeSEric Cheng 	status = dladm_str2pri(*prop_val, pri);
1534*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK) {
1535*da14cebeSEric Cheng 		free(pri);
1536*da14cebeSEric Cheng 		return (status);
1537*da14cebeSEric Cheng 	}
1538*da14cebeSEric Cheng 
1539*da14cebeSEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
1540*da14cebeSEric Cheng 		free(pri);
1541*da14cebeSEric Cheng 		return (DLADM_STATUS_BADVAL);
1542*da14cebeSEric Cheng 	}
1543*da14cebeSEric Cheng 
1544*da14cebeSEric Cheng 	vdp->vd_val = (uintptr_t)pri;
1545*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1546*da14cebeSEric Cheng }
1547*da14cebeSEric Cheng 
1548*da14cebeSEric Cheng /* ARGSUSED */
1549*da14cebeSEric Cheng dladm_status_t
1550*da14cebeSEric Cheng do_extract_priority(val_desc_t *vdp, void *arg, uint_t cnt)
1551*da14cebeSEric Cheng {
1552*da14cebeSEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
1553*da14cebeSEric Cheng 
1554*da14cebeSEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
1555*da14cebeSEric Cheng 	    sizeof (mac_priority_level_t));
1556*da14cebeSEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
1557*da14cebeSEric Cheng 
1558*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
1559*da14cebeSEric Cheng }
1560*da14cebeSEric Cheng 
1561*da14cebeSEric Cheng /* ARGSUSED */
1562*da14cebeSEric Cheng static dladm_status_t
1563*da14cebeSEric Cheng do_get_autopush(prop_desc_t *pdp, datalink_id_t linkid,
1564*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1565*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1566d62bc4baSyz147064 {
15673bc21d0aSAruna Ramakrishna - Sun Microsystems 	struct		dlautopush dlap;
15683bc21d0aSAruna Ramakrishna - Sun Microsystems 	int		i, len;
15693bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status;
15703bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
1571d62bc4baSyz147064 
15723fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
1573149b7eb2SSowmini Varadhan 		return (DLADM_STATUS_NOTDEFINED);
15744045d941Ssowmini 
1575d62bc4baSyz147064 	*val_cnt = 1;
1576*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
1577*da14cebeSEric Cheng 	    &status, perm_flags);
15783bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dip == NULL) {
1579d62bc4baSyz147064 		(*prop_val)[0] = '\0';
1580*da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
1581d62bc4baSyz147064 	}
15823bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
1583d62bc4baSyz147064 
15843bc21d0aSAruna Ramakrishna - Sun Microsystems 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
1585d62bc4baSyz147064 		if (i != 0) {
1586d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1587d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
1588d62bc4baSyz147064 			len += 1;
1589d62bc4baSyz147064 		}
1590d62bc4baSyz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
15913bc21d0aSAruna Ramakrishna - Sun Microsystems 		    "%s", dlap.dap_aplist[i]);
15923bc21d0aSAruna Ramakrishna - Sun Microsystems 		len += strlen(dlap.dap_aplist[i]);
15933bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (dlap.dap_anchor - 1 == i) {
1594d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1595d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
1596d62bc4baSyz147064 			    AP_ANCHOR);
1597d62bc4baSyz147064 			len += (strlen(AP_ANCHOR) + 1);
1598d62bc4baSyz147064 		}
1599d62bc4baSyz147064 	}
16003bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
1601d62bc4baSyz147064 done:
1602d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1603d62bc4baSyz147064 }
1604d62bc4baSyz147064 
1605d62bc4baSyz147064 /*
1606d62bc4baSyz147064  * Add the specified module to the dlautopush structure; returns a
1607d62bc4baSyz147064  * DLADM_STATUS_* code.
1608d62bc4baSyz147064  */
1609d62bc4baSyz147064 dladm_status_t
1610d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
1611d62bc4baSyz147064 {
1612d62bc4baSyz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
1613d62bc4baSyz147064 		return (DLADM_STATUS_BADVAL);
1614d62bc4baSyz147064 
1615d62bc4baSyz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
1616d62bc4baSyz147064 		/*
1617d62bc4baSyz147064 		 * We don't allow multiple anchors, and the anchor must
1618d62bc4baSyz147064 		 * be after at least one module.
1619d62bc4baSyz147064 		 */
1620d62bc4baSyz147064 		if (dlap->dap_anchor != 0)
1621d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1622d62bc4baSyz147064 		if (dlap->dap_npush == 0)
1623d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1624d62bc4baSyz147064 
1625d62bc4baSyz147064 		dlap->dap_anchor = dlap->dap_npush;
1626d62bc4baSyz147064 		return (DLADM_STATUS_OK);
1627d62bc4baSyz147064 	}
1628d62bc4baSyz147064 	if (dlap->dap_npush > MAXAPUSH)
1629d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1630d62bc4baSyz147064 
1631d62bc4baSyz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
1632d62bc4baSyz147064 	    FMNAMESZ + 1);
1633d62bc4baSyz147064 
1634d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1635d62bc4baSyz147064 }
1636d62bc4baSyz147064 
1637d62bc4baSyz147064 /*
1638d62bc4baSyz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
1639d62bc4baSyz147064  * autopush modules. The former is used in dladm set-linkprop, and the
1640d62bc4baSyz147064  * latter is used in the autopush(1M) file.
1641d62bc4baSyz147064  */
1642d62bc4baSyz147064 /* ARGSUSED */
1643d62bc4baSyz147064 static dladm_status_t
1644*da14cebeSEric Cheng do_check_autopush(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
16456b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1646d62bc4baSyz147064 {
1647d62bc4baSyz147064 	char			*module;
1648d62bc4baSyz147064 	struct dlautopush	*dlap;
1649d62bc4baSyz147064 	dladm_status_t		status;
1650d62bc4baSyz147064 	char			val[DLADM_PROP_VAL_MAX];
1651d62bc4baSyz147064 	char			delimiters[4];
1652d62bc4baSyz147064 
1653d62bc4baSyz147064 	if (val_cnt != 1)
1654d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1655d62bc4baSyz147064 
16563bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (prop_val != NULL) {
1657d62bc4baSyz147064 		dlap = malloc(sizeof (struct dlautopush));
1658d62bc4baSyz147064 		if (dlap == NULL)
1659d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
1660d62bc4baSyz147064 
1661d62bc4baSyz147064 		(void) memset(dlap, 0, sizeof (struct dlautopush));
1662d62bc4baSyz147064 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
1663d62bc4baSyz147064 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
1664d62bc4baSyz147064 		module = strtok(val, delimiters);
1665d62bc4baSyz147064 		while (module != NULL) {
1666d62bc4baSyz147064 			status = i_dladm_add_ap_module(module, dlap);
1667d62bc4baSyz147064 			if (status != DLADM_STATUS_OK)
1668d62bc4baSyz147064 				return (status);
1669d62bc4baSyz147064 			module = strtok(NULL, delimiters);
1670d62bc4baSyz147064 		}
1671d62bc4baSyz147064 
1672d62bc4baSyz147064 		vdp->vd_val = (uintptr_t)dlap;
16733bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
16743bc21d0aSAruna Ramakrishna - Sun Microsystems 		vdp->vd_val = 0;
16753bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1676d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1677d62bc4baSyz147064 }
1678d62bc4baSyz147064 
1679bcb5c89dSSowmini Varadhan #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
1680bcb5c89dSSowmini Varadhan 
1681e7801d59Ssowmini /* ARGSUSED */
1682d62bc4baSyz147064 static dladm_status_t
1683*da14cebeSEric Cheng do_get_rate_common(prop_desc_t *pdp, datalink_id_t linkid,
1684*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, uint_t id, uint_t *perm_flags)
1685d62bc4baSyz147064 {
1686d62bc4baSyz147064 	wl_rates_t	*wrp;
1687d62bc4baSyz147064 	uint_t		i;
1688d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1689d62bc4baSyz147064 
1690bcb5c89dSSowmini Varadhan 	wrp = malloc(WLDP_BUFSIZE);
1691bcb5c89dSSowmini Varadhan 	if (wrp == NULL)
1692bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
1693d62bc4baSyz147064 
1694bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_param(linkid, wrp, id, WLDP_BUFSIZE, B_FALSE);
1695d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1696d62bc4baSyz147064 		goto done;
1697d62bc4baSyz147064 
1698d62bc4baSyz147064 	if (wrp->wl_rates_num > *val_cnt) {
1699d62bc4baSyz147064 		status = DLADM_STATUS_TOOSMALL;
1700d62bc4baSyz147064 		goto done;
1701d62bc4baSyz147064 	}
1702d62bc4baSyz147064 
1703d62bc4baSyz147064 	if (wrp->wl_rates_rates[0] == 0) {
1704d62bc4baSyz147064 		prop_val[0][0] = '\0';
1705d62bc4baSyz147064 		*val_cnt = 1;
1706d62bc4baSyz147064 		goto done;
1707d62bc4baSyz147064 	}
1708d62bc4baSyz147064 
1709d62bc4baSyz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
1710d62bc4baSyz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
1711d62bc4baSyz147064 		    wrp->wl_rates_rates[i] % 2,
1712d62bc4baSyz147064 		    (float)wrp->wl_rates_rates[i] / 2);
1713d62bc4baSyz147064 	}
1714d62bc4baSyz147064 	*val_cnt = wrp->wl_rates_num;
1715*da14cebeSEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
1716d62bc4baSyz147064 
1717d62bc4baSyz147064 done:
1718bcb5c89dSSowmini Varadhan 	free(wrp);
1719d62bc4baSyz147064 	return (status);
1720d62bc4baSyz147064 }
1721d62bc4baSyz147064 
1722d62bc4baSyz147064 static dladm_status_t
1723*da14cebeSEric Cheng do_get_rate_prop(prop_desc_t *pdp, datalink_id_t linkid,
1724*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1725*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1726d62bc4baSyz147064 {
1727afdda45fSVasumathi Sundaram - Sun Microsystems 	if (media != DL_WIFI) {
1728*da14cebeSEric Cheng 		return (i_dladm_speed_get(pdp, linkid, prop_val,
1729*da14cebeSEric Cheng 		    val_cnt, flags, perm_flags));
1730afdda45fSVasumathi Sundaram - Sun Microsystems 	}
17316b9e797cSsowmini 
1732*da14cebeSEric Cheng 	return (do_get_rate_common(pdp, linkid, prop_val, val_cnt,
1733*da14cebeSEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
1734d62bc4baSyz147064 }
1735d62bc4baSyz147064 
17364045d941Ssowmini /* ARGSUSED */
1737d62bc4baSyz147064 static dladm_status_t
1738*da14cebeSEric Cheng do_get_rate_mod(prop_desc_t *pdp, datalink_id_t linkid,
1739*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1740*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1741d62bc4baSyz147064 {
17426b9e797cSsowmini 	switch (media) {
17436b9e797cSsowmini 	case DL_ETHER:
17444045d941Ssowmini 		/*
17454045d941Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
17464045d941Ssowmini 		 * links can have a speed of 5.5 Gbps.
17474045d941Ssowmini 		 */
17484045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
17496b9e797cSsowmini 
17506b9e797cSsowmini 	case DL_WIFI:
1751*da14cebeSEric Cheng 		return (do_get_rate_common(pdp, linkid, prop_val, val_cnt,
1752*da14cebeSEric Cheng 		    MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
17536b9e797cSsowmini 	default:
17546b9e797cSsowmini 		return (DLADM_STATUS_BADARG);
17556b9e797cSsowmini 	}
1756d62bc4baSyz147064 }
1757d62bc4baSyz147064 
1758d62bc4baSyz147064 static dladm_status_t
1759d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates)
1760f4b3ec61Sdh155122 {
1761f4b3ec61Sdh155122 	int		i;
1762d62bc4baSyz147064 	uint_t		len;
1763d62bc4baSyz147064 	wl_rates_t	*wrp;
1764d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1765d62bc4baSyz147064 
1766bcb5c89dSSowmini Varadhan 	wrp = malloc(WLDP_BUFSIZE);
1767bcb5c89dSSowmini Varadhan 	if (wrp == NULL)
1768d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1769d62bc4baSyz147064 
1770bcb5c89dSSowmini Varadhan 	bzero(wrp, WLDP_BUFSIZE);
1771d62bc4baSyz147064 	for (i = 0; i < rates->wr_cnt; i++)
1772d62bc4baSyz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
1773d62bc4baSyz147064 	wrp->wl_rates_num = rates->wr_cnt;
1774d62bc4baSyz147064 
1775d62bc4baSyz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
1776d62bc4baSyz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
1777bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_param(linkid, wrp, MAC_PROP_WL_DESIRED_RATES,
1778bcb5c89dSSowmini Varadhan 	    len, B_TRUE);
1779d62bc4baSyz147064 
1780bcb5c89dSSowmini Varadhan 	free(wrp);
1781d62bc4baSyz147064 	return (status);
1782d62bc4baSyz147064 }
1783d62bc4baSyz147064 
1784e7801d59Ssowmini /* ARGSUSED */
1785d62bc4baSyz147064 static dladm_status_t
1786*da14cebeSEric Cheng do_set_rate_prop(prop_desc_t *pdp, datalink_id_t linkid,
17876b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1788d62bc4baSyz147064 {
1789d62bc4baSyz147064 	dladm_wlan_rates_t	rates;
1790f4b3ec61Sdh155122 	dladm_status_t		status;
1791f4b3ec61Sdh155122 
17926b9e797cSsowmini 	/*
17936b9e797cSsowmini 	 * can currently set rate on WIFI links only.
17946b9e797cSsowmini 	 */
17956b9e797cSsowmini 	if (media != DL_WIFI)
17966b9e797cSsowmini 		return (DLADM_STATUS_PROPRDONLY);
17976b9e797cSsowmini 
1798d62bc4baSyz147064 	if (val_cnt != 1)
1799d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1800f4b3ec61Sdh155122 
1801d62bc4baSyz147064 	rates.wr_cnt = 1;
1802d62bc4baSyz147064 	rates.wr_rates[0] = vdp[0].vd_val;
1803f4b3ec61Sdh155122 
1804d62bc4baSyz147064 	status = do_set_rate(linkid, &rates);
1805f4b3ec61Sdh155122 
1806d62bc4baSyz147064 done:
1807d62bc4baSyz147064 	return (status);
1808d62bc4baSyz147064 }
1809d62bc4baSyz147064 
1810d62bc4baSyz147064 /* ARGSUSED */
1811d62bc4baSyz147064 static dladm_status_t
1812*da14cebeSEric Cheng do_check_rate(prop_desc_t *pdp, datalink_id_t linkid, char **prop_val,
18136b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1814d62bc4baSyz147064 {
1815d62bc4baSyz147064 	int		i;
1816d62bc4baSyz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
1817d62bc4baSyz147064 	char		*buf, **modval;
1818d62bc4baSyz147064 	dladm_status_t	status;
1819afdda45fSVasumathi Sundaram - Sun Microsystems 	uint_t 		perm_flags;
1820d62bc4baSyz147064 
1821d62bc4baSyz147064 	if (val_cnt != 1)
1822d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1823d62bc4baSyz147064 
1824d62bc4baSyz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
1825d62bc4baSyz147064 	    MAX_SUPPORT_RATES);
1826d62bc4baSyz147064 	if (buf == NULL) {
1827d62bc4baSyz147064 		status = DLADM_STATUS_NOMEM;
1828d62bc4baSyz147064 		goto done;
1829d62bc4baSyz147064 	}
1830d62bc4baSyz147064 
1831d62bc4baSyz147064 	modval = (char **)(void *)buf;
1832d62bc4baSyz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
1833d62bc4baSyz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
1834d62bc4baSyz147064 		    i * DLADM_STRSIZE;
1835d62bc4baSyz147064 	}
1836d62bc4baSyz147064 
1837afdda45fSVasumathi Sundaram - Sun Microsystems 	status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media,
1838afdda45fSVasumathi Sundaram - Sun Microsystems 	    0, &perm_flags);
1839d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1840d62bc4baSyz147064 		goto done;
1841d62bc4baSyz147064 
1842d62bc4baSyz147064 	for (i = 0; i < modval_cnt; i++) {
1843d62bc4baSyz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
1844e7801d59Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
1845e7801d59Ssowmini 			    (atof(*prop_val) * 2);
1846f4b3ec61Sdh155122 			status = DLADM_STATUS_OK;
1847f4b3ec61Sdh155122 			break;
1848f4b3ec61Sdh155122 		}
1849d62bc4baSyz147064 	}
1850d62bc4baSyz147064 	if (i == modval_cnt)
1851d62bc4baSyz147064 		status = DLADM_STATUS_BADVAL;
1852d62bc4baSyz147064 done:
1853d62bc4baSyz147064 	free(buf);
1854d62bc4baSyz147064 	return (status);
1855d62bc4baSyz147064 }
1856f4b3ec61Sdh155122 
1857d62bc4baSyz147064 static dladm_status_t
1858bcb5c89dSSowmini Varadhan do_get_phyconf(datalink_id_t linkid, void *buf, int buflen)
1859d62bc4baSyz147064 {
1860bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_PHY_CONFIG,
1861bcb5c89dSSowmini Varadhan 	    buflen, B_FALSE));
1862d62bc4baSyz147064 }
1863d62bc4baSyz147064 
1864e7801d59Ssowmini /* ARGSUSED */
1865d62bc4baSyz147064 static dladm_status_t
1866*da14cebeSEric Cheng do_get_channel_prop(prop_desc_t *pdp, datalink_id_t linkid,
1867*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1868*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1869d62bc4baSyz147064 {
1870d62bc4baSyz147064 	uint32_t	channel;
1871bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1872d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1873bcb5c89dSSowmini Varadhan 	wl_phy_conf_t	wl_phy_conf;
1874d62bc4baSyz147064 
1875bcb5c89dSSowmini Varadhan 	if ((status = do_get_phyconf(linkid, buf, sizeof (buf)))
1876bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1877d62bc4baSyz147064 		goto done;
1878d62bc4baSyz147064 
1879bcb5c89dSSowmini Varadhan 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
1880bcb5c89dSSowmini Varadhan 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
1881d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1882d62bc4baSyz147064 		goto done;
1883d62bc4baSyz147064 	}
1884d62bc4baSyz147064 
1885d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
1886d62bc4baSyz147064 	*val_cnt = 1;
1887*da14cebeSEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
1888d62bc4baSyz147064 done:
1889d62bc4baSyz147064 	return (status);
1890d62bc4baSyz147064 }
1891d62bc4baSyz147064 
1892d62bc4baSyz147064 static dladm_status_t
1893bcb5c89dSSowmini Varadhan do_get_powermode(datalink_id_t linkid, void *buf, int buflen)
1894d62bc4baSyz147064 {
1895bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_POWER_MODE,
1896bcb5c89dSSowmini Varadhan 	    buflen, B_FALSE));
1897d62bc4baSyz147064 }
1898d62bc4baSyz147064 
1899e7801d59Ssowmini /* ARGSUSED */
1900d62bc4baSyz147064 static dladm_status_t
1901*da14cebeSEric Cheng do_get_powermode_prop(prop_desc_t *pdp, datalink_id_t linkid,
1902*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1903*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1904d62bc4baSyz147064 {
1905bcb5c89dSSowmini Varadhan 	wl_ps_mode_t	mode;
1906d62bc4baSyz147064 	const char	*s;
1907bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1908d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1909d62bc4baSyz147064 
1910bcb5c89dSSowmini Varadhan 	if ((status = do_get_powermode(linkid, buf, sizeof (buf)))
1911bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1912d62bc4baSyz147064 		goto done;
1913d62bc4baSyz147064 
1914bcb5c89dSSowmini Varadhan 	(void) memcpy(&mode, buf, sizeof (mode));
1915bcb5c89dSSowmini Varadhan 	switch (mode.wl_ps_mode) {
1916d62bc4baSyz147064 	case WL_PM_AM:
1917d62bc4baSyz147064 		s = "off";
1918f4b3ec61Sdh155122 		break;
1919d62bc4baSyz147064 	case WL_PM_MPS:
1920d62bc4baSyz147064 		s = "max";
1921d62bc4baSyz147064 		break;
1922d62bc4baSyz147064 	case WL_PM_FAST:
1923d62bc4baSyz147064 		s = "fast";
1924f4b3ec61Sdh155122 		break;
1925f4b3ec61Sdh155122 	default:
1926d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1927d62bc4baSyz147064 		goto done;
1928f4b3ec61Sdh155122 	}
1929d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
1930d62bc4baSyz147064 	*val_cnt = 1;
1931afdda45fSVasumathi Sundaram - Sun Microsystems 	*perm_flags = MAC_PROP_PERM_RW;
1932*da14cebeSEric Cheng done:
1933d62bc4baSyz147064 	return (status);
1934d62bc4baSyz147064 }
1935d62bc4baSyz147064 
1936d62bc4baSyz147064 static dladm_status_t
1937d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm)
1938d62bc4baSyz147064 {
1939d62bc4baSyz147064 	wl_ps_mode_t    ps_mode;
1940d62bc4baSyz147064 
1941d62bc4baSyz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
1942d62bc4baSyz147064 
1943d62bc4baSyz147064 	switch (*pm) {
1944d62bc4baSyz147064 	case DLADM_WLAN_PM_OFF:
1945d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
1946d62bc4baSyz147064 		break;
1947d62bc4baSyz147064 	case DLADM_WLAN_PM_MAX:
1948d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
1949d62bc4baSyz147064 		break;
1950d62bc4baSyz147064 	case DLADM_WLAN_PM_FAST:
1951d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
1952d62bc4baSyz147064 		break;
1953d62bc4baSyz147064 	default:
1954d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
1955d62bc4baSyz147064 	}
1956bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, &ps_mode, MAC_PROP_WL_POWER_MODE,
1957bcb5c89dSSowmini Varadhan 	    sizeof (ps_mode), B_TRUE));
1958d62bc4baSyz147064 }
1959d62bc4baSyz147064 
1960d62bc4baSyz147064 /* ARGSUSED */
1961d62bc4baSyz147064 static dladm_status_t
1962*da14cebeSEric Cheng do_set_powermode_prop(prop_desc_t *pdp, datalink_id_t linkid,
19636b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1964d62bc4baSyz147064 {
1965d62bc4baSyz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
1966d62bc4baSyz147064 	dladm_status_t status;
1967d62bc4baSyz147064 
1968d62bc4baSyz147064 	if (val_cnt != 1)
1969d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1970d62bc4baSyz147064 
1971d62bc4baSyz147064 	status = do_set_powermode(linkid, &powermode);
1972f4b3ec61Sdh155122 
1973f4b3ec61Sdh155122 	return (status);
1974f4b3ec61Sdh155122 }
1975f4b3ec61Sdh155122 
1976f4b3ec61Sdh155122 static dladm_status_t
1977bcb5c89dSSowmini Varadhan do_get_radio(datalink_id_t linkid, void *buf, int buflen)
1978f4b3ec61Sdh155122 {
1979bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_RADIO, buflen,
1980bcb5c89dSSowmini Varadhan 	    B_FALSE));
1981d62bc4baSyz147064 }
1982d62bc4baSyz147064 
1983e7801d59Ssowmini /* ARGSUSED */
1984d62bc4baSyz147064 static dladm_status_t
1985*da14cebeSEric Cheng do_get_radio_prop(prop_desc_t *pdp, datalink_id_t linkid,
1986*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1987*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
1988d62bc4baSyz147064 {
1989d62bc4baSyz147064 	wl_radio_t	radio;
1990d62bc4baSyz147064 	const char	*s;
1991bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1992d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1993d62bc4baSyz147064 
1994bcb5c89dSSowmini Varadhan 	if ((status = do_get_radio(linkid, buf, sizeof (buf)))
1995bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1996d62bc4baSyz147064 		goto done;
1997d62bc4baSyz147064 
1998bcb5c89dSSowmini Varadhan 	(void) memcpy(&radio, buf, sizeof (radio));
1999d62bc4baSyz147064 	switch (radio) {
2000d62bc4baSyz147064 	case B_TRUE:
2001d62bc4baSyz147064 		s = "on";
2002d62bc4baSyz147064 		break;
2003d62bc4baSyz147064 	case B_FALSE:
2004d62bc4baSyz147064 		s = "off";
2005d62bc4baSyz147064 		break;
2006d62bc4baSyz147064 	default:
2007d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
2008d62bc4baSyz147064 		goto done;
2009d62bc4baSyz147064 	}
2010d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
2011d62bc4baSyz147064 	*val_cnt = 1;
2012afdda45fSVasumathi Sundaram - Sun Microsystems 	*perm_flags = MAC_PROP_PERM_RW;
2013*da14cebeSEric Cheng done:
2014d62bc4baSyz147064 	return (status);
2015d62bc4baSyz147064 }
2016d62bc4baSyz147064 
2017d62bc4baSyz147064 static dladm_status_t
2018d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio)
2019d62bc4baSyz147064 {
2020d62bc4baSyz147064 	wl_radio_t r;
2021d62bc4baSyz147064 
2022d62bc4baSyz147064 	switch (*radio) {
2023d62bc4baSyz147064 	case DLADM_WLAN_RADIO_ON:
2024d62bc4baSyz147064 		r = B_TRUE;
2025d62bc4baSyz147064 		break;
2026d62bc4baSyz147064 	case DLADM_WLAN_RADIO_OFF:
2027d62bc4baSyz147064 		r = B_FALSE;
2028d62bc4baSyz147064 		break;
2029d62bc4baSyz147064 	default:
2030d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
2031d62bc4baSyz147064 	}
2032bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, &r, MAC_PROP_WL_RADIO,
2033bcb5c89dSSowmini Varadhan 	    sizeof (r), B_TRUE));
2034d62bc4baSyz147064 }
2035d62bc4baSyz147064 
2036d62bc4baSyz147064 /* ARGSUSED */
2037d62bc4baSyz147064 static dladm_status_t
2038*da14cebeSEric Cheng do_set_radio_prop(prop_desc_t *pdp, datalink_id_t linkid,
20396b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
2040d62bc4baSyz147064 {
2041d62bc4baSyz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
2042f4b3ec61Sdh155122 	dladm_status_t status;
2043f4b3ec61Sdh155122 
2044d62bc4baSyz147064 	if (val_cnt != 1)
2045d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
2046f4b3ec61Sdh155122 
2047d62bc4baSyz147064 	status = do_set_radio(linkid, &radio);
2048f4b3ec61Sdh155122 
2049d62bc4baSyz147064 	return (status);
2050d62bc4baSyz147064 }
2051f4b3ec61Sdh155122 
2052d62bc4baSyz147064 static dladm_status_t
2053d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name,
2054d62bc4baSyz147064     char **prop_val, uint_t val_cnt)
2055d62bc4baSyz147064 {
2056d62bc4baSyz147064 	char		buf[MAXLINELEN];
2057d62bc4baSyz147064 	int		i;
2058d62bc4baSyz147064 	dladm_conf_t	conf;
2059d62bc4baSyz147064 	dladm_status_t	status;
2060d62bc4baSyz147064 
2061d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
2062f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
2063f4b3ec61Sdh155122 		return (status);
2064f4b3ec61Sdh155122 
2065d62bc4baSyz147064 	/*
2066d62bc4baSyz147064 	 * reset case.
2067d62bc4baSyz147064 	 */
2068d62bc4baSyz147064 	if (val_cnt == 0) {
2069d62bc4baSyz147064 		status = dladm_unset_conf_field(conf, prop_name);
2070d62bc4baSyz147064 		if (status == DLADM_STATUS_OK)
2071d62bc4baSyz147064 			status = dladm_write_conf(conf);
2072d62bc4baSyz147064 		goto done;
2073f4b3ec61Sdh155122 	}
2074f4b3ec61Sdh155122 
2075d62bc4baSyz147064 	buf[0] = '\0';
2076d62bc4baSyz147064 	for (i = 0; i < val_cnt; i++) {
2077d62bc4baSyz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
2078d62bc4baSyz147064 		if (i != val_cnt - 1)
2079d62bc4baSyz147064 			(void) strlcat(buf, ",", MAXLINELEN);
2080d62bc4baSyz147064 	}
2081f4b3ec61Sdh155122 
2082d62bc4baSyz147064 	status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf);
2083d62bc4baSyz147064 	if (status == DLADM_STATUS_OK)
2084d62bc4baSyz147064 		status = dladm_write_conf(conf);
2085d62bc4baSyz147064 
2086d62bc4baSyz147064 done:
2087d62bc4baSyz147064 	dladm_destroy_conf(conf);
2088f4b3ec61Sdh155122 	return (status);
2089f4b3ec61Sdh155122 }
2090f4b3ec61Sdh155122 
2091f4b3ec61Sdh155122 static dladm_status_t
2092d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name,
2093d62bc4baSyz147064     char **prop_val, uint_t *val_cntp)
2094f4b3ec61Sdh155122 {
2095d62bc4baSyz147064 	char		buf[MAXLINELEN], *str;
2096d62bc4baSyz147064 	uint_t		cnt = 0;
2097d62bc4baSyz147064 	dladm_conf_t	conf;
2098d62bc4baSyz147064 	dladm_status_t	status;
2099f4b3ec61Sdh155122 
2100d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
2101d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
2102f4b3ec61Sdh155122 		return (status);
2103d62bc4baSyz147064 
2104d62bc4baSyz147064 	status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN);
2105d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
2106d62bc4baSyz147064 		goto done;
2107d62bc4baSyz147064 
2108d62bc4baSyz147064 	str = strtok(buf, ",");
2109d62bc4baSyz147064 	while (str != NULL) {
2110d62bc4baSyz147064 		if (cnt == *val_cntp) {
2111d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
2112d62bc4baSyz147064 			goto done;
2113d62bc4baSyz147064 		}
2114d62bc4baSyz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
2115d62bc4baSyz147064 		str = strtok(NULL, ",");
2116f4b3ec61Sdh155122 	}
2117f4b3ec61Sdh155122 
2118d62bc4baSyz147064 	*val_cntp = cnt;
2119f4b3ec61Sdh155122 
2120d62bc4baSyz147064 done:
2121d62bc4baSyz147064 	dladm_destroy_conf(conf);
2122d62bc4baSyz147064 	return (status);
2123f4b3ec61Sdh155122 }
2124e7801d59Ssowmini 
2125bcb5c89dSSowmini Varadhan static link_attr_t *
2126e7801d59Ssowmini dladm_name2prop(const char *prop_name)
2127e7801d59Ssowmini {
2128bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2129e7801d59Ssowmini 
2130bcb5c89dSSowmini Varadhan 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
2131e7801d59Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
2132e7801d59Ssowmini 			break;
2133e7801d59Ssowmini 	}
2134e7801d59Ssowmini 	return (p);
2135e7801d59Ssowmini }
2136e7801d59Ssowmini 
2137bcb5c89dSSowmini Varadhan static link_attr_t *
2138bcb5c89dSSowmini Varadhan dladm_id2prop(mac_prop_id_t propid)
2139bcb5c89dSSowmini Varadhan {
2140bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2141bcb5c89dSSowmini Varadhan 
2142bcb5c89dSSowmini Varadhan 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
2143bcb5c89dSSowmini Varadhan 		if (p->pp_id == propid)
2144bcb5c89dSSowmini Varadhan 			break;
2145bcb5c89dSSowmini Varadhan 	}
2146bcb5c89dSSowmini Varadhan 	return (p);
2147bcb5c89dSSowmini Varadhan }
2148e7801d59Ssowmini 
21493fd94f8cSam223141 static dld_ioc_macprop_t *
2150bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
2151bcb5c89dSSowmini Varadhan     const char *prop_name, mac_prop_id_t propid, uint_t flags,
2152bcb5c89dSSowmini Varadhan     dladm_status_t *status)
2153e7801d59Ssowmini {
2154e7801d59Ssowmini 	int dsize;
21553fd94f8cSam223141 	dld_ioc_macprop_t *dip;
2156e7801d59Ssowmini 
2157e7801d59Ssowmini 	*status = DLADM_STATUS_OK;
21583fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
2159e7801d59Ssowmini 	dip = malloc(dsize);
2160e7801d59Ssowmini 	if (dip == NULL) {
2161e7801d59Ssowmini 		*status = DLADM_STATUS_NOMEM;
2162e7801d59Ssowmini 		return (NULL);
2163e7801d59Ssowmini 	}
2164e7801d59Ssowmini 	bzero(dip, dsize);
2165e7801d59Ssowmini 	dip->pr_valsize = valsize;
21664045d941Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
21673fd94f8cSam223141 	dip->pr_version = MAC_PROP_VERSION;
21686b9e797cSsowmini 	dip->pr_linkid = linkid;
2169bcb5c89dSSowmini Varadhan 	dip->pr_num = propid;
21704045d941Ssowmini 	dip->pr_flags = flags;
2171e7801d59Ssowmini 	return (dip);
2172e7801d59Ssowmini }
2173e7801d59Ssowmini 
2174bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *
2175bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
2176bcb5c89dSSowmini Varadhan     const char *prop_name, uint_t flags, dladm_status_t *status)
2177bcb5c89dSSowmini Varadhan {
2178bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2179bcb5c89dSSowmini Varadhan 
2180bcb5c89dSSowmini Varadhan 	p = dladm_name2prop(prop_name);
2181bcb5c89dSSowmini Varadhan 	valsize = MAX(p->pp_valsize, valsize);
2182bcb5c89dSSowmini Varadhan 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
2183bcb5c89dSSowmini Varadhan 	    flags, status));
2184bcb5c89dSSowmini Varadhan }
2185bcb5c89dSSowmini Varadhan 
2186bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *
2187bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
2188bcb5c89dSSowmini Varadhan     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
2189bcb5c89dSSowmini Varadhan {
2190bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2191bcb5c89dSSowmini Varadhan 
2192bcb5c89dSSowmini Varadhan 	p = dladm_id2prop(propid);
2193bcb5c89dSSowmini Varadhan 	valsize = MAX(p->pp_valsize, valsize);
2194bcb5c89dSSowmini Varadhan 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
2195bcb5c89dSSowmini Varadhan 	    flags, status));
2196bcb5c89dSSowmini Varadhan }
2197bcb5c89dSSowmini Varadhan 
2198e7801d59Ssowmini /* ARGSUSED */
2199e7801d59Ssowmini static dladm_status_t
2200*da14cebeSEric Cheng i_dladm_set_public_prop(prop_desc_t *pdp, datalink_id_t linkid,
22016b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
2202e7801d59Ssowmini {
22033fd94f8cSam223141 	dld_ioc_macprop_t	*dip;
2204e7801d59Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
2205e7801d59Ssowmini 	uint8_t		u8;
2206e7801d59Ssowmini 	uint16_t	u16;
2207e7801d59Ssowmini 	uint32_t	u32;
2208e7801d59Ssowmini 	void		*val;
2209e7801d59Ssowmini 
2210*da14cebeSEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
2211e7801d59Ssowmini 	if (dip == NULL)
2212e7801d59Ssowmini 		return (status);
2213e7801d59Ssowmini 
2214*da14cebeSEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
2215e7801d59Ssowmini 		val = (void *)vdp->vd_val;
2216e7801d59Ssowmini 	else {
2217e7801d59Ssowmini 		/*
2218e7801d59Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
2219e7801d59Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
2220e7801d59Ssowmini 		 */
2221e7801d59Ssowmini 		switch (dip->pr_valsize) {
2222e7801d59Ssowmini 		case 1:
2223e7801d59Ssowmini 			u8 = vdp->vd_val;
2224e7801d59Ssowmini 			val = &u8;
2225e7801d59Ssowmini 			break;
2226e7801d59Ssowmini 		case 2:
2227e7801d59Ssowmini 			u16 = vdp->vd_val;
2228e7801d59Ssowmini 			val = &u16;
2229e7801d59Ssowmini 			break;
2230e7801d59Ssowmini 		case 4:
2231e7801d59Ssowmini 			u32 = vdp->vd_val;
2232e7801d59Ssowmini 			val = &u32;
2233e7801d59Ssowmini 			break;
2234e7801d59Ssowmini 		default:
2235e7801d59Ssowmini 			val = &vdp->vd_val;
2236e7801d59Ssowmini 			break;
2237e7801d59Ssowmini 		}
2238e7801d59Ssowmini 	}
2239e7801d59Ssowmini 
22403bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (val != NULL)
2241e7801d59Ssowmini 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
22423bc21d0aSAruna Ramakrishna - Sun Microsystems 	else
22433bc21d0aSAruna Ramakrishna - Sun Microsystems 		dip->pr_valsize = 0;
22443bc21d0aSAruna Ramakrishna - Sun Microsystems 
2245bcb5c89dSSowmini Varadhan 	status = i_dladm_macprop(dip, B_TRUE);
2246bcb5c89dSSowmini Varadhan 
2247bcb5c89dSSowmini Varadhan done:
2248bcb5c89dSSowmini Varadhan 	free(dip);
2249bcb5c89dSSowmini Varadhan 	return (status);
2250bcb5c89dSSowmini Varadhan }
2251bcb5c89dSSowmini Varadhan 
2252bcb5c89dSSowmini Varadhan dladm_status_t
2253bcb5c89dSSowmini Varadhan i_dladm_macprop(void *dip, boolean_t set)
2254bcb5c89dSSowmini Varadhan {
2255bcb5c89dSSowmini Varadhan 	int fd;
2256bcb5c89dSSowmini Varadhan 	dladm_status_t status = DLADM_STATUS_OK;
2257bcb5c89dSSowmini Varadhan 
2258e7801d59Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
2259e7801d59Ssowmini 		status = dladm_errno2status(errno);
2260bcb5c89dSSowmini Varadhan 		return (status);
2261e7801d59Ssowmini 	}
2262bcb5c89dSSowmini Varadhan 	if (ioctl(fd, (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
2263e7801d59Ssowmini 		status = dladm_errno2status(errno);
2264e7801d59Ssowmini 
2265e7801d59Ssowmini 	(void) close(fd);
2266e7801d59Ssowmini 	return (status);
2267e7801d59Ssowmini }
2268e7801d59Ssowmini 
22693fd94f8cSam223141 static dld_ioc_macprop_t *
22703bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags,
2271*da14cebeSEric Cheng     dladm_status_t *status, uint_t *perm_flags)
2272e7801d59Ssowmini {
22733fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
22744045d941Ssowmini 
2275bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
22764045d941Ssowmini 	if (dip == NULL)
22774045d941Ssowmini 		return (NULL);
2278e7801d59Ssowmini 
2279bcb5c89dSSowmini Varadhan 	*status = i_dladm_macprop(dip, B_FALSE);
22804045d941Ssowmini 	if (*status != DLADM_STATUS_OK) {
22814045d941Ssowmini 		free(dip);
22824045d941Ssowmini 		return (NULL);
22834045d941Ssowmini 	}
2284*da14cebeSEric Cheng 	if (perm_flags != NULL)
2285*da14cebeSEric Cheng 		*perm_flags = dip->pr_perm_flags;
2286*da14cebeSEric Cheng 
22874045d941Ssowmini 	return (dip);
2288e7801d59Ssowmini }
2289e7801d59Ssowmini 
2290e7801d59Ssowmini /* ARGSUSED */
2291e7801d59Ssowmini static dladm_status_t
2292*da14cebeSEric Cheng i_dladm_defmtu_check(prop_desc_t *pdp, datalink_id_t linkid,
22933bc21d0aSAruna Ramakrishna - Sun Microsystems     char **prop_val, uint_t val_cnt, val_desc_t *v, datalink_media_t media)
2294e7801d59Ssowmini {
2295e7801d59Ssowmini 	if (val_cnt != 1)
2296e7801d59Ssowmini 		return (DLADM_STATUS_BADVAL);
22974045d941Ssowmini 	v->vd_val = atoi(prop_val[0]);
2298e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2299e7801d59Ssowmini }
2300e7801d59Ssowmini 
2301e7801d59Ssowmini /* ARGSUSED */
2302e7801d59Ssowmini static dladm_status_t
2303*da14cebeSEric Cheng i_dladm_duplex_get(prop_desc_t *pdp, datalink_id_t linkid,
2304*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2305*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
2306e7801d59Ssowmini {
2307e7801d59Ssowmini 	link_duplex_t   link_duplex;
2308e7801d59Ssowmini 	dladm_status_t  status;
2309e7801d59Ssowmini 
2310e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "link_duplex",
2311e7801d59Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
2312e7801d59Ssowmini 		return (status);
2313e7801d59Ssowmini 
2314e7801d59Ssowmini 	switch (link_duplex) {
2315e7801d59Ssowmini 	case LINK_DUPLEX_FULL:
2316e7801d59Ssowmini 		(void) strcpy(*prop_val, "full");
2317e7801d59Ssowmini 		break;
2318e7801d59Ssowmini 	case LINK_DUPLEX_HALF:
2319e7801d59Ssowmini 		(void) strcpy(*prop_val, "half");
2320e7801d59Ssowmini 		break;
2321e7801d59Ssowmini 	default:
2322e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
2323e7801d59Ssowmini 		break;
2324e7801d59Ssowmini 	}
2325e7801d59Ssowmini 	*val_cnt = 1;
2326e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2327e7801d59Ssowmini }
2328e7801d59Ssowmini 
2329e7801d59Ssowmini /* ARGSUSED */
2330e7801d59Ssowmini static dladm_status_t
2331*da14cebeSEric Cheng i_dladm_speed_get(prop_desc_t *pdp, datalink_id_t linkid,
2332*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
2333e7801d59Ssowmini {
2334e7801d59Ssowmini 	uint64_t	ifspeed = 0;
2335e7801d59Ssowmini 	dladm_status_t status;
2336e7801d59Ssowmini 
2337e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "ifspeed",
2338e7801d59Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
2339e7801d59Ssowmini 		return (status);
23404045d941Ssowmini 
23416b9e797cSsowmini 	if ((ifspeed % 1000000) != 0) {
23426b9e797cSsowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
23436b9e797cSsowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
23446b9e797cSsowmini 	} else {
2345e7801d59Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
2346e7801d59Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
23476b9e797cSsowmini 	}
2348e7801d59Ssowmini 	*val_cnt = 1;
2349*da14cebeSEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
2350e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2351e7801d59Ssowmini }
2352e7801d59Ssowmini 
2353e7801d59Ssowmini /* ARGSUSED */
2354e7801d59Ssowmini static dladm_status_t
2355*da14cebeSEric Cheng i_dladm_status_get(prop_desc_t *pdp, datalink_id_t linkid,
2356*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2357*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
2358e7801d59Ssowmini {
2359e7801d59Ssowmini 	link_state_t		link_state;
2360e7801d59Ssowmini 	dladm_status_t		status;
23614045d941Ssowmini 	uchar_t 		*cp;
23623fd94f8cSam223141 	dld_ioc_macprop_t	*dip;
2363e7801d59Ssowmini 
2364*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
2365*da14cebeSEric Cheng 	    &status, perm_flags);
23664045d941Ssowmini 	if (status != DLADM_STATUS_OK)
2367e7801d59Ssowmini 		return (status);
2368*da14cebeSEric Cheng 
23694045d941Ssowmini 	cp = (uchar_t *)dip->pr_val;
23704045d941Ssowmini 	(void) memcpy(&link_state, cp, sizeof (link_state));
2371e7801d59Ssowmini 
2372e7801d59Ssowmini 	switch (link_state) {
2373e7801d59Ssowmini 	case LINK_STATE_UP:
2374e7801d59Ssowmini 		(void) strcpy(*prop_val, "up");
2375e7801d59Ssowmini 		break;
2376e7801d59Ssowmini 	case LINK_STATE_DOWN:
2377e7801d59Ssowmini 		(void) strcpy(*prop_val, "down");
2378e7801d59Ssowmini 		break;
2379e7801d59Ssowmini 	default:
2380e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
2381e7801d59Ssowmini 		break;
2382e7801d59Ssowmini 	}
2383e7801d59Ssowmini 	*val_cnt = 1;
23844045d941Ssowmini 	free(dip);
2385e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2386e7801d59Ssowmini }
2387e7801d59Ssowmini 
2388e7801d59Ssowmini /* ARGSUSED */
2389e7801d59Ssowmini static dladm_status_t
2390*da14cebeSEric Cheng i_dladm_binary_get(prop_desc_t *pdp, datalink_id_t linkid,
2391*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2392*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
2393e7801d59Ssowmini {
23943fd94f8cSam223141 	dld_ioc_macprop_t *dip;
2395e7801d59Ssowmini 	dladm_status_t status;
2396e7801d59Ssowmini 
2397*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
2398*da14cebeSEric Cheng 	    &status, perm_flags);
23994045d941Ssowmini 	if (dip == NULL)
2400e7801d59Ssowmini 		return (status);
2401*da14cebeSEric Cheng 
2402e7801d59Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
2403e7801d59Ssowmini 	free(dip);
2404e7801d59Ssowmini 	*val_cnt = 1;
2405e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2406e7801d59Ssowmini }
2407e7801d59Ssowmini 
24086b9e797cSsowmini /* ARGSUSED */
2409e7801d59Ssowmini static dladm_status_t
2410*da14cebeSEric Cheng i_dladm_uint32_get(prop_desc_t *pdp, datalink_id_t linkid,
2411*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2412*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
2413e7801d59Ssowmini {
24143fd94f8cSam223141 	dld_ioc_macprop_t *dip;
24154045d941Ssowmini 	uint32_t v = 0;
2416e7801d59Ssowmini 	uchar_t *cp;
2417e7801d59Ssowmini 	dladm_status_t status;
2418e7801d59Ssowmini 
2419*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
2420*da14cebeSEric Cheng 	    &status, perm_flags);
24214045d941Ssowmini 	if (dip == NULL)
2422e7801d59Ssowmini 		return (status);
2423*da14cebeSEric Cheng 
2424e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
2425e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
24264045d941Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
2427e7801d59Ssowmini 	free(dip);
2428e7801d59Ssowmini 	*val_cnt = 1;
2429e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2430e7801d59Ssowmini }
2431e7801d59Ssowmini 
24326b9e797cSsowmini /* ARGSUSED */
2433e7801d59Ssowmini static dladm_status_t
2434*da14cebeSEric Cheng i_dladm_flowctl_get(prop_desc_t *pdp, datalink_id_t linkid,
2435*da14cebeSEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2436*da14cebeSEric Cheng     uint_t flags, uint_t *perm_flags)
2437e7801d59Ssowmini {
24383fd94f8cSam223141 	dld_ioc_macprop_t *dip;
2439e7801d59Ssowmini 	link_flowctrl_t v;
2440e7801d59Ssowmini 	dladm_status_t status;
2441e7801d59Ssowmini 	uchar_t *cp;
2442e7801d59Ssowmini 
2443*da14cebeSEric Cheng 	dip = i_dladm_get_public_prop(linkid, pdp->pd_name, flags,
2444*da14cebeSEric Cheng 	    &status, perm_flags);
24454045d941Ssowmini 	if (dip == NULL)
2446e7801d59Ssowmini 		return (status);
2447*da14cebeSEric Cheng 
2448e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
2449e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
2450e7801d59Ssowmini 	switch (v) {
2451e7801d59Ssowmini 	case LINK_FLOWCTRL_NONE:
2452e7801d59Ssowmini 		(void) sprintf(*prop_val, "no");
2453e7801d59Ssowmini 		break;
2454e7801d59Ssowmini 	case LINK_FLOWCTRL_RX:
2455e7801d59Ssowmini 		(void) sprintf(*prop_val, "rx");
2456e7801d59Ssowmini 		break;
2457e7801d59Ssowmini 	case LINK_FLOWCTRL_TX:
2458e7801d59Ssowmini 		(void) sprintf(*prop_val, "tx");
2459e7801d59Ssowmini 		break;
2460e7801d59Ssowmini 	case LINK_FLOWCTRL_BI:
2461e7801d59Ssowmini 		(void) sprintf(*prop_val, "bi");
2462e7801d59Ssowmini 		break;
2463e7801d59Ssowmini 	}
2464e7801d59Ssowmini 	free(dip);
2465e7801d59Ssowmini 	*val_cnt = 1;
2466e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2467e7801d59Ssowmini }
2468e7801d59Ssowmini 
2469e7801d59Ssowmini 
2470e7801d59Ssowmini /* ARGSUSED */
2471e7801d59Ssowmini static dladm_status_t
24723bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_set_prop(datalink_id_t linkid, const char *prop_name,
2473e7801d59Ssowmini     char **prop_val, uint_t val_cnt, uint_t flags)
2474e7801d59Ssowmini {
2475bcb5c89dSSowmini Varadhan 	int		i, slen;
2476eae72b5bSSebastien Roy 	int 		bufsize = 0;
24773fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2478e7801d59Ssowmini 	uchar_t 	*dp;
2479bcb5c89dSSowmini Varadhan 	link_attr_t *p;
24804045d941Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
2481e7801d59Ssowmini 
2482e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2483e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2484e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2485e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
24863fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2487e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2488e7801d59Ssowmini 
2489e7801d59Ssowmini 	/*
2490e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2491e7801d59Ssowmini 	 * allocate a enough space for each property + its separator (',').
2492e7801d59Ssowmini 	 */
2493e7801d59Ssowmini 	for (i = 0; i < val_cnt; i++) {
2494e7801d59Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
2495e7801d59Ssowmini 	}
24964045d941Ssowmini 
24974045d941Ssowmini 	if (prop_val == NULL) {
24984045d941Ssowmini 		/*
24994045d941Ssowmini 		 * getting default value. so use more buffer space.
25004045d941Ssowmini 		 */
2501bcb5c89dSSowmini Varadhan 		bufsize += DLADM_PROP_BUF_CHUNK;
25024045d941Ssowmini 	}
25034045d941Ssowmini 
2504bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
25053fd94f8cSam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
2506e7801d59Ssowmini 	if (dip == NULL)
2507e7801d59Ssowmini 		return (status);
2508e7801d59Ssowmini 
2509e7801d59Ssowmini 	dp = (uchar_t *)dip->pr_val;
2510e7801d59Ssowmini 	slen = 0;
2511bcb5c89dSSowmini Varadhan 
25124045d941Ssowmini 	if (prop_val == NULL) {
2513bcb5c89dSSowmini Varadhan 		status = i_dladm_macprop(dip, B_FALSE);
25144045d941Ssowmini 	} else {
2515e7801d59Ssowmini 		for (i = 0; i < val_cnt; i++) {
2516e7801d59Ssowmini 			int plen = 0;
2517e7801d59Ssowmini 
2518e7801d59Ssowmini 			plen = strlen(prop_val[i]);
2519e7801d59Ssowmini 			bcopy(prop_val[i], dp, plen);
2520e7801d59Ssowmini 			slen += plen;
2521e7801d59Ssowmini 			/*
2522e7801d59Ssowmini 			 * add a "," separator and update dp.
2523e7801d59Ssowmini 			 */
2524e7801d59Ssowmini 			if (i != (val_cnt -1))
2525e7801d59Ssowmini 				dp[slen++] = ',';
2526e7801d59Ssowmini 			dp += (plen + 1);
2527e7801d59Ssowmini 		}
2528bcb5c89dSSowmini Varadhan 		status = i_dladm_macprop(dip, B_TRUE);
2529e7801d59Ssowmini 	}
25304045d941Ssowmini 
2531e7801d59Ssowmini 	free(dip);
2532e7801d59Ssowmini 	return (status);
2533e7801d59Ssowmini }
2534e7801d59Ssowmini 
2535e7801d59Ssowmini static dladm_status_t
25363bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_prop(datalink_id_t linkid, const char *prop_name,
25374045d941Ssowmini     char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags)
2538e7801d59Ssowmini {
2539e7801d59Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
25403fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2541bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2542e7801d59Ssowmini 	char tmp = '\0';
2543e7801d59Ssowmini 
2544e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2545e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2546e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2547e7801d59Ssowmini 
2548e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
25493fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2550e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2551e7801d59Ssowmini 
25524045d941Ssowmini 	if (type == DLADM_PROP_VAL_MODIFIABLE) {
2553e7801d59Ssowmini 		*prop_val = &tmp;
2554e7801d59Ssowmini 		*val_cnt = 1;
2555e7801d59Ssowmini 		return (DLADM_STATUS_OK);
2556e7801d59Ssowmini 	}
2557e7801d59Ssowmini 
2558e7801d59Ssowmini 	/*
2559e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2560e7801d59Ssowmini 	 */
2561bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
2562bcb5c89dSSowmini Varadhan 	    dld_flags, &status);
2563e7801d59Ssowmini 	if (dip == NULL)
2564e7801d59Ssowmini 		return (status);
2565e7801d59Ssowmini 
2566bcb5c89dSSowmini Varadhan 	if ((status = i_dladm_macprop(dip, B_FALSE)) == DLADM_STATUS_OK) {
2567afdda45fSVasumathi Sundaram - Sun Microsystems 		if (type == DLADM_PROP_VAL_PERM) {
2568*da14cebeSEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
2569afdda45fSVasumathi Sundaram - Sun Microsystems 		} else {
2570afdda45fSVasumathi Sundaram - Sun Microsystems 			(void) strncpy(*prop_val, dip->pr_val,
2571afdda45fSVasumathi Sundaram - Sun Microsystems 			    DLADM_PROP_VAL_MAX);
2572afdda45fSVasumathi Sundaram - Sun Microsystems 		}
2573e7801d59Ssowmini 		*val_cnt = 1;
2574e7801d59Ssowmini 	}
25754045d941Ssowmini 	free(dip);
25764045d941Ssowmini 	return (status);
25774045d941Ssowmini }
25784045d941Ssowmini 
25794045d941Ssowmini 
25804045d941Ssowmini static dladm_status_t
25814045d941Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid,
25824045d941Ssowmini     datalink_media_t media, uint_t flags)
25834045d941Ssowmini {
25844045d941Ssowmini 	dladm_status_t status;
25854045d941Ssowmini 	char **prop_vals = NULL, *buf;
25864045d941Ssowmini 	size_t bufsize;
25874045d941Ssowmini 	uint_t cnt;
25884045d941Ssowmini 	int i;
2589afdda45fSVasumathi Sundaram - Sun Microsystems 	uint_t perm_flags;
25904045d941Ssowmini 
25914045d941Ssowmini 	/*
25924045d941Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
25934045d941Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
25944045d941Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
25954045d941Ssowmini 	 */
25964045d941Ssowmini 	bufsize =
25974045d941Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
25984045d941Ssowmini 	buf = malloc(bufsize);
25994045d941Ssowmini 	prop_vals = (char **)(void *)buf;
26004045d941Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
26014045d941Ssowmini 		prop_vals[i] = buf +
26024045d941Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
26034045d941Ssowmini 		    i * DLADM_PROP_VAL_MAX;
26044045d941Ssowmini 	}
260513a55820Sar224390 
260613a55820Sar224390 	/*
26073bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
26083bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * string, the "" itself is used to reset the property (exceptions
26093bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * are zone and autopush, which populate vdp->vd_val). So
26103bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
26113bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * down on the setprop using the global values in the table. For
26123bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * other cases (vd_name is ""), doing reset-linkprop will cause
26133bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm to do a getprop to find the default value and then do
26143bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * a setprop to reset the value to default.
261513a55820Sar224390 	 */
26163fd94f8cSam223141 	status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media,
2617afdda45fSVasumathi Sundaram - Sun Microsystems 	    MAC_PROP_DEFAULT, &perm_flags);
26184045d941Ssowmini 	if (status == DLADM_STATUS_OK) {
2619afdda45fSVasumathi Sundaram - Sun Microsystems 		if (perm_flags == MAC_PROP_PERM_RW) {
26204045d941Ssowmini 			status = i_dladm_set_single_prop(linkid, pdp->pd_class,
26214045d941Ssowmini 			    media, pdp, prop_vals, cnt, flags);
26224045d941Ssowmini 		}
2623afdda45fSVasumathi Sundaram - Sun Microsystems 		else
2624afdda45fSVasumathi Sundaram - Sun Microsystems 			status = DLADM_STATUS_NOTSUP;
2625afdda45fSVasumathi Sundaram - Sun Microsystems 	}
26264045d941Ssowmini 	free(buf);
2627e7801d59Ssowmini 	return (status);
2628e7801d59Ssowmini }
2629bcb5c89dSSowmini Varadhan 
2630bcb5c89dSSowmini Varadhan int
2631bcb5c89dSSowmini Varadhan macprop_to_wifi(mac_prop_id_t wl_prop)
2632bcb5c89dSSowmini Varadhan {
2633bcb5c89dSSowmini Varadhan 	switch (wl_prop) {
2634bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ESSID:
2635bcb5c89dSSowmini Varadhan 		return (WL_ESSID);
2636bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_BSSID:
2637bcb5c89dSSowmini Varadhan 		return (WL_BSSID);
2638bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_BSSTYPE:
2639bcb5c89dSSowmini Varadhan 		return (WL_BSS_TYPE);
2640bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_LINKSTATUS:
2641bcb5c89dSSowmini Varadhan 		return (WL_LINKSTATUS);
2642bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_DESIRED_RATES:
2643bcb5c89dSSowmini Varadhan 		return (WL_DESIRED_RATES);
2644bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SUPPORTED_RATES:
2645bcb5c89dSSowmini Varadhan 		return (WL_SUPPORTED_RATES);
2646bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_AUTH_MODE:
2647bcb5c89dSSowmini Varadhan 		return (WL_AUTH_MODE);
2648bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ENCRYPTION:
2649bcb5c89dSSowmini Varadhan 		return (WL_ENCRYPTION);
2650bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_RSSI:
2651bcb5c89dSSowmini Varadhan 		return (WL_RSSI);
2652bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_PHY_CONFIG:
2653bcb5c89dSSowmini Varadhan 		return (WL_PHY_CONFIG);
2654bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_CAPABILITY:
2655bcb5c89dSSowmini Varadhan 		return (WL_CAPABILITY);
2656bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_WPA:
2657bcb5c89dSSowmini Varadhan 		return (WL_WPA);
2658bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SCANRESULTS:
2659bcb5c89dSSowmini Varadhan 		return (WL_SCANRESULTS);
2660bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_POWER_MODE:
2661bcb5c89dSSowmini Varadhan 		return (WL_POWER_MODE);
2662bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_RADIO:
2663bcb5c89dSSowmini Varadhan 		return (WL_RADIO);
2664bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ESS_LIST:
2665bcb5c89dSSowmini Varadhan 		return (WL_ESS_LIST);
2666bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_KEY_TAB:
2667bcb5c89dSSowmini Varadhan 		return (WL_WEP_KEY_TAB);
2668bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_CREATE_IBSS:
2669bcb5c89dSSowmini Varadhan 		return (WL_CREATE_IBSS);
2670bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SETOPTIE:
2671bcb5c89dSSowmini Varadhan 		return (WL_SETOPTIE);
2672bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_DELKEY:
2673bcb5c89dSSowmini Varadhan 		return (WL_DELKEY);
2674bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_KEY:
2675bcb5c89dSSowmini Varadhan 		return (WL_KEY);
2676bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_MLME:
2677bcb5c89dSSowmini Varadhan 		return (WL_MLME);
2678bcb5c89dSSowmini Varadhan 	default:
2679bcb5c89dSSowmini Varadhan 		return (-1);
2680bcb5c89dSSowmini Varadhan 	}
2681bcb5c89dSSowmini Varadhan }
2682bcb5c89dSSowmini Varadhan 
2683bcb5c89dSSowmini Varadhan dladm_status_t
2684bcb5c89dSSowmini Varadhan i_dladm_wlan_param(datalink_id_t linkid, void *buf, mac_prop_id_t cmd,
2685bcb5c89dSSowmini Varadhan     size_t len, boolean_t set)
2686bcb5c89dSSowmini Varadhan {
2687bcb5c89dSSowmini Varadhan 	uint32_t		flags;
2688bcb5c89dSSowmini Varadhan 	dladm_status_t		status;
2689bcb5c89dSSowmini Varadhan 	uint32_t		media;
2690bcb5c89dSSowmini Varadhan 	dld_ioc_macprop_t	*dip;
2691bcb5c89dSSowmini Varadhan 	void			*dp;
2692bcb5c89dSSowmini Varadhan 
2693bcb5c89dSSowmini Varadhan 	if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media,
2694bcb5c89dSSowmini Varadhan 	    NULL, 0)) != DLADM_STATUS_OK) {
2695bcb5c89dSSowmini Varadhan 		return (status);
2696bcb5c89dSSowmini Varadhan 	}
2697bcb5c89dSSowmini Varadhan 
2698bcb5c89dSSowmini Varadhan 	if (media != DL_WIFI)
2699bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_BADARG);
2700bcb5c89dSSowmini Varadhan 
2701bcb5c89dSSowmini Varadhan 	if (!(flags & DLADM_OPT_ACTIVE))
2702bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_TEMPONLY);
2703bcb5c89dSSowmini Varadhan 
2704bcb5c89dSSowmini Varadhan 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
2705bcb5c89dSSowmini Varadhan 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
2706bcb5c89dSSowmini Varadhan 
2707bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
2708bcb5c89dSSowmini Varadhan 	if (dip == NULL)
2709bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2710bcb5c89dSSowmini Varadhan 
2711bcb5c89dSSowmini Varadhan 	dp = (uchar_t *)dip->pr_val;
2712bcb5c89dSSowmini Varadhan 	if (set)
2713bcb5c89dSSowmini Varadhan 		(void) memcpy(dp, buf, len);
2714bcb5c89dSSowmini Varadhan 
2715bcb5c89dSSowmini Varadhan 	status = i_dladm_macprop(dip, set);
2716bcb5c89dSSowmini Varadhan 	if (status == DLADM_STATUS_NOTSUP) {
2717bcb5c89dSSowmini Varadhan 		if (set) {
2718bcb5c89dSSowmini Varadhan 			status = i_dladm_wlan_set_legacy_ioctl(linkid,
2719bcb5c89dSSowmini Varadhan 			    buf, len, macprop_to_wifi(cmd));
2720bcb5c89dSSowmini Varadhan 		} else {
2721bcb5c89dSSowmini Varadhan 			status = i_dladm_wlan_get_legacy_ioctl(linkid,
2722bcb5c89dSSowmini Varadhan 			    buf, len, macprop_to_wifi(cmd));
2723bcb5c89dSSowmini Varadhan 		}
2724bcb5c89dSSowmini Varadhan 	} else if (status == DLADM_STATUS_OK) {
2725bcb5c89dSSowmini Varadhan 		if (!set)
2726bcb5c89dSSowmini Varadhan 			(void) memcpy(buf, dp, len);
2727bcb5c89dSSowmini Varadhan 	}
2728bcb5c89dSSowmini Varadhan 
2729bcb5c89dSSowmini Varadhan 	free(dip);
2730bcb5c89dSSowmini Varadhan 	return (status);
2731bcb5c89dSSowmini Varadhan }
2732bcb5c89dSSowmini Varadhan 
2733bcb5c89dSSowmini Varadhan static dladm_status_t
2734bcb5c89dSSowmini Varadhan i_dladm_wlan_get_legacy_ioctl(datalink_id_t linkid, void *buf, uint_t buflen,
2735bcb5c89dSSowmini Varadhan     uint_t id)
2736bcb5c89dSSowmini Varadhan {
2737bcb5c89dSSowmini Varadhan 	wldp_t *gbuf;
2738bcb5c89dSSowmini Varadhan 	dladm_status_t status;
2739bcb5c89dSSowmini Varadhan 
2740bcb5c89dSSowmini Varadhan 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
2741bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2742bcb5c89dSSowmini Varadhan 
2743bcb5c89dSSowmini Varadhan 	(void) memset(gbuf, 0, MAX_BUF_LEN);
2744bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, MAX_BUF_LEN,
2745bcb5c89dSSowmini Varadhan 	    WLAN_GET_PARAM, sizeof (wldp_t));
2746bcb5c89dSSowmini Varadhan 	if (status == DLADM_STATUS_OK)
2747bcb5c89dSSowmini Varadhan 		(void) memcpy(buf, gbuf->wldp_buf, buflen);
2748bcb5c89dSSowmini Varadhan 
2749bcb5c89dSSowmini Varadhan 	free(gbuf);
2750bcb5c89dSSowmini Varadhan 	return (status);
2751bcb5c89dSSowmini Varadhan }
2752bcb5c89dSSowmini Varadhan 
2753bcb5c89dSSowmini Varadhan static dladm_status_t
2754bcb5c89dSSowmini Varadhan i_dladm_wlan_set_legacy_ioctl(datalink_id_t linkid,  void *buf, uint_t buflen,
2755bcb5c89dSSowmini Varadhan     uint_t id)
2756bcb5c89dSSowmini Varadhan {
2757bcb5c89dSSowmini Varadhan 	wldp_t *gbuf;
2758bcb5c89dSSowmini Varadhan 	dladm_status_t status = DLADM_STATUS_OK;
2759bcb5c89dSSowmini Varadhan 
2760bcb5c89dSSowmini Varadhan 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
2761bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2762bcb5c89dSSowmini Varadhan 
2763bcb5c89dSSowmini Varadhan 	(void) memset(gbuf, 0, MAX_BUF_LEN);
2764bcb5c89dSSowmini Varadhan 	(void) memcpy(gbuf->wldp_buf, buf, buflen);
2765bcb5c89dSSowmini Varadhan 	buflen += WIFI_BUF_OFFSET;
2766bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, buflen,
2767bcb5c89dSSowmini Varadhan 	    WLAN_SET_PARAM, buflen);
2768bcb5c89dSSowmini Varadhan 
2769bcb5c89dSSowmini Varadhan 	free(gbuf);
2770bcb5c89dSSowmini Varadhan 	return (status);
2771bcb5c89dSSowmini Varadhan }
2772*da14cebeSEric Cheng 
2773*da14cebeSEric Cheng static dladm_status_t
2774*da14cebeSEric Cheng link_proplist_check(dladm_arg_list_t *proplist)
2775*da14cebeSEric Cheng {
2776*da14cebeSEric Cheng 	int		i, j;
2777*da14cebeSEric Cheng 	boolean_t	matched;
2778*da14cebeSEric Cheng 
2779*da14cebeSEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
2780*da14cebeSEric Cheng 		matched = B_FALSE;
2781*da14cebeSEric Cheng 		for (j = 0; j < DLADM_MAX_PROPS; j++) {
2782*da14cebeSEric Cheng 			if (strcmp(proplist->al_info[i].ai_name,
2783*da14cebeSEric Cheng 			    prop_table[j].pd_name) == 0)
2784*da14cebeSEric Cheng 				matched = B_TRUE;
2785*da14cebeSEric Cheng 		}
2786*da14cebeSEric Cheng 		if (!matched)
2787*da14cebeSEric Cheng 			return (DLADM_STATUS_BADPROP);
2788*da14cebeSEric Cheng 	}
2789*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
2790*da14cebeSEric Cheng }
2791*da14cebeSEric Cheng 
2792*da14cebeSEric Cheng dladm_status_t
2793*da14cebeSEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
2794*da14cebeSEric Cheng {
2795*da14cebeSEric Cheng 	dladm_status_t	status;
2796*da14cebeSEric Cheng 
2797*da14cebeSEric Cheng 	status = dladm_parse_args(str, listp, novalues);
2798*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
2799*da14cebeSEric Cheng 		return (status);
2800*da14cebeSEric Cheng 
2801*da14cebeSEric Cheng 	status = link_proplist_check(*listp);
2802*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK) {
2803*da14cebeSEric Cheng 		dladm_free_props(*listp);
2804*da14cebeSEric Cheng 		return (status);
2805*da14cebeSEric Cheng 	}
2806*da14cebeSEric Cheng 
2807*da14cebeSEric Cheng 	return (DLADM_STATUS_OK);
2808*da14cebeSEric Cheng }
2809*da14cebeSEric Cheng 
2810*da14cebeSEric Cheng /*
2811*da14cebeSEric Cheng  * Retrieve the one link property from the database
2812*da14cebeSEric Cheng  */
2813*da14cebeSEric Cheng /*ARGSUSED*/
2814*da14cebeSEric Cheng static int
2815*da14cebeSEric Cheng i_dladm_get_one_prop(datalink_id_t linkid, const char *prop_name, void *arg)
2816*da14cebeSEric Cheng {
2817*da14cebeSEric Cheng 	dladm_arg_list_t	*proplist = arg;
2818*da14cebeSEric Cheng 	dladm_arg_info_t	*aip = NULL;
2819*da14cebeSEric Cheng 
2820*da14cebeSEric Cheng 	aip = &proplist->al_info[proplist->al_count];
2821*da14cebeSEric Cheng 	/*
2822*da14cebeSEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
2823*da14cebeSEric Cheng 	 * prop_table[n].pd_name.
2824*da14cebeSEric Cheng 	 */
2825*da14cebeSEric Cheng 	aip->ai_name = prop_name;
2826*da14cebeSEric Cheng 
2827*da14cebeSEric Cheng 	(void) dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name,
2828*da14cebeSEric Cheng 	    aip->ai_val, &aip->ai_count);
2829*da14cebeSEric Cheng 
2830*da14cebeSEric Cheng 	if (aip->ai_count != 0)
2831*da14cebeSEric Cheng 		proplist->al_count++;
2832*da14cebeSEric Cheng 
2833*da14cebeSEric Cheng 	return (DLADM_WALK_CONTINUE);
2834*da14cebeSEric Cheng }
2835*da14cebeSEric Cheng 
2836*da14cebeSEric Cheng 
2837*da14cebeSEric Cheng /*
2838*da14cebeSEric Cheng  * Retrieve all link properties for a link from the database and
2839*da14cebeSEric Cheng  * return a property list.
2840*da14cebeSEric Cheng  */
2841*da14cebeSEric Cheng dladm_status_t
2842*da14cebeSEric Cheng dladm_link_get_proplist(datalink_id_t linkid, dladm_arg_list_t **listp)
2843*da14cebeSEric Cheng {
2844*da14cebeSEric Cheng 	dladm_arg_list_t	*list;
2845*da14cebeSEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
2846*da14cebeSEric Cheng 
2847*da14cebeSEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
2848*da14cebeSEric Cheng 	if (list == NULL)
2849*da14cebeSEric Cheng 		return (dladm_errno2status(errno));
2850*da14cebeSEric Cheng 
2851*da14cebeSEric Cheng 	status = dladm_walk_linkprop(linkid, list, i_dladm_get_one_prop);
2852*da14cebeSEric Cheng 
2853*da14cebeSEric Cheng 	*listp = list;
2854*da14cebeSEric Cheng 	return (status);
2855*da14cebeSEric Cheng }
2856*da14cebeSEric Cheng 
2857*da14cebeSEric Cheng /*
2858*da14cebeSEric Cheng  * Retrieve the named property from a proplist, check the value and
2859*da14cebeSEric Cheng  * convert to a kernel structure.
2860*da14cebeSEric Cheng  */
2861*da14cebeSEric Cheng static dladm_status_t
2862*da14cebeSEric Cheng i_dladm_link_proplist_extract_one(dladm_arg_list_t *proplist,
2863*da14cebeSEric Cheng     const char *name, void *val)
2864*da14cebeSEric Cheng {
2865*da14cebeSEric Cheng 	dladm_status_t		status;
2866*da14cebeSEric Cheng 	dladm_arg_info_t	*aip = NULL;
2867*da14cebeSEric Cheng 	int			i, j;
2868*da14cebeSEric Cheng 
2869*da14cebeSEric Cheng 	/* Find named property in proplist */
2870*da14cebeSEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
2871*da14cebeSEric Cheng 		aip = &proplist->al_info[i];
2872*da14cebeSEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
2873*da14cebeSEric Cheng 			break;
2874*da14cebeSEric Cheng 	}
2875*da14cebeSEric Cheng 
2876*da14cebeSEric Cheng 	/* Property not in list */
2877*da14cebeSEric Cheng 	if (i == proplist->al_count)
2878*da14cebeSEric Cheng 		return (DLADM_STATUS_OK);
2879*da14cebeSEric Cheng 
2880*da14cebeSEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
2881*da14cebeSEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
2882*da14cebeSEric Cheng 		val_desc_t	*vdp;
2883*da14cebeSEric Cheng 
2884*da14cebeSEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
2885*da14cebeSEric Cheng 		if (vdp == NULL)
2886*da14cebeSEric Cheng 			return (DLADM_STATUS_NOMEM);
2887*da14cebeSEric Cheng 
2888*da14cebeSEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
2889*da14cebeSEric Cheng 			continue;
2890*da14cebeSEric Cheng 
2891*da14cebeSEric Cheng 		if (aip->ai_val == NULL)
2892*da14cebeSEric Cheng 			return (DLADM_STATUS_BADARG);
2893*da14cebeSEric Cheng 
2894*da14cebeSEric Cheng 		/* Check property value */
2895*da14cebeSEric Cheng 		if (pdp->pd_check != NULL) {
2896*da14cebeSEric Cheng 			status = pdp->pd_check(pdp, 0, aip->ai_val,
2897*da14cebeSEric Cheng 			    aip->ai_count, vdp, 0);
2898*da14cebeSEric Cheng 		} else {
2899*da14cebeSEric Cheng 			status = DLADM_STATUS_BADARG;
2900*da14cebeSEric Cheng 		}
2901*da14cebeSEric Cheng 
2902*da14cebeSEric Cheng 		if (status != DLADM_STATUS_OK)
2903*da14cebeSEric Cheng 			return (status);
2904*da14cebeSEric Cheng 
2905*da14cebeSEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
2906*da14cebeSEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
2907*da14cebeSEric Cheng 
2908*da14cebeSEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
2909*da14cebeSEric Cheng 				continue;
2910*da14cebeSEric Cheng 
2911*da14cebeSEric Cheng 			/* Extract kernel structure */
2912*da14cebeSEric Cheng 			if (rpp->rp_extract != NULL) {
2913*da14cebeSEric Cheng 				status = rpp->rp_extract(vdp, val,
2914*da14cebeSEric Cheng 				    aip->ai_count);
2915*da14cebeSEric Cheng 			} else {
2916*da14cebeSEric Cheng 				status = DLADM_STATUS_BADARG;
2917*da14cebeSEric Cheng 			}
2918*da14cebeSEric Cheng 			break;
2919*da14cebeSEric Cheng 		}
2920*da14cebeSEric Cheng 
2921*da14cebeSEric Cheng 		if (status != DLADM_STATUS_OK)
2922*da14cebeSEric Cheng 			return (status);
2923*da14cebeSEric Cheng 
2924*da14cebeSEric Cheng 		break;
2925*da14cebeSEric Cheng 	}
2926*da14cebeSEric Cheng 	return (status);
2927*da14cebeSEric Cheng }
2928*da14cebeSEric Cheng 
2929*da14cebeSEric Cheng /*
2930*da14cebeSEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
2931*da14cebeSEric Cheng  */
2932*da14cebeSEric Cheng dladm_status_t
2933*da14cebeSEric Cheng dladm_link_proplist_extract(dladm_arg_list_t *proplist,
2934*da14cebeSEric Cheng     mac_resource_props_t *mrp)
2935*da14cebeSEric Cheng {
2936*da14cebeSEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
2937*da14cebeSEric Cheng 
2938*da14cebeSEric Cheng 	status = i_dladm_link_proplist_extract_one(proplist, "maxbw", mrp);
2939*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
2940*da14cebeSEric Cheng 		return (status);
2941*da14cebeSEric Cheng 	status = i_dladm_link_proplist_extract_one(proplist, "priority", mrp);
2942*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
2943*da14cebeSEric Cheng 		return (status);
2944*da14cebeSEric Cheng 	status = i_dladm_link_proplist_extract_one(proplist, "cpus", mrp);
2945*da14cebeSEric Cheng 	if (status != DLADM_STATUS_OK)
2946*da14cebeSEric Cheng 		return (status);
2947*da14cebeSEric Cheng 	return (status);
2948*da14cebeSEric Cheng }
2949*da14cebeSEric Cheng 
2950*da14cebeSEric Cheng static const char *
2951*da14cebeSEric Cheng dladm_perm2str(uint_t perm, char *buf)
2952*da14cebeSEric Cheng {
2953*da14cebeSEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
2954*da14cebeSEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
2955*da14cebeSEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
2956*da14cebeSEric Cheng 	return (buf);
2957*da14cebeSEric Cheng }
2958