xref: /titanic_44/usr/src/lib/libdladm/common/linkprop.c (revision 149b7eb2919570a01d698963b7ab14d45b4edda8)
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>
44f4b3ec61Sdh155122 #include <dlfcn.h>
45f4b3ec61Sdh155122 #include <link.h>
46d62bc4baSyz147064 #include <inet/wifi_ioctl.h>
47e7801d59Ssowmini #include <libdladm.h>
48e7801d59Ssowmini #include <sys/param.h>
49e7801d59Ssowmini #include <inttypes.h>
50e7801d59Ssowmini #include <sys/ethernet.h>
51bcb5c89dSSowmini Varadhan #include <net/wpa.h>
52bcb5c89dSSowmini Varadhan #include <sys/sysmacros.h>
53f4b3ec61Sdh155122 
54d62bc4baSyz147064 /*
55d62bc4baSyz147064  * The linkprop get() callback.
56e7801d59Ssowmini  * - pd: 	pointer to the struct prop_desc
57d62bc4baSyz147064  * - propstrp:	a property string array to keep the returned property.
58d62bc4baSyz147064  *		Caller allocated.
59d62bc4baSyz147064  * - cntp:	number of returned properties.
60d62bc4baSyz147064  *		Caller also uses it to indicate how many it expects.
61d62bc4baSyz147064  */
62e7801d59Ssowmini struct prop_desc;
63e7801d59Ssowmini 
64e7801d59Ssowmini typedef dladm_status_t	pd_getf_t(struct prop_desc *pd,
656b9e797cSsowmini 			datalink_id_t, char **propstp, uint_t *cntp,
664045d941Ssowmini 			datalink_media_t, uint_t);
67f4b3ec61Sdh155122 
68d62bc4baSyz147064 /*
69d62bc4baSyz147064  * The linkprop set() callback.
70d62bc4baSyz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
71d62bc4baSyz147064  * - cnt:	number of properties to be set.
72e7801d59Ssowmini  * - flags: 	additional flags passed down the system call.
73e7801d59Ssowmini  *
74e7801d59Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
75e7801d59Ssowmini  * a format suitable for kernel consumption. This may require allocation
76e7801d59Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
77e7801d59Ssowmini  * by all other pd_sets) which invokes the ioctl.
78d62bc4baSyz147064  */
79e7801d59Ssowmini typedef dladm_status_t	pd_setf_t(struct prop_desc *, datalink_id_t,
806b9e797cSsowmini 			val_desc_t *propval, uint_t cnt, uint_t flags,
816b9e797cSsowmini 			datalink_media_t);
82f4b3ec61Sdh155122 
83f4b3ec61Sdh155122 
84d62bc4baSyz147064 /*
85d62bc4baSyz147064  * The linkprop check() callback.
86d62bc4baSyz147064  * - propstrp:	property string array which keeps the property to be checked.
87d62bc4baSyz147064  * - cnt:	number of properties.
88d62bc4baSyz147064  * - propval:	return value; the property values of the given property strings.
89e7801d59Ssowmini  *
90e7801d59Ssowmini  * pd_check checks that the input values are valid. It does so by
91e7801d59Ssowmini  * iteraring through the pd_modval list for the property. If
92e7801d59Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
93e7801d59Ssowmini  * specific to this property can be used. If the input values are
94e7801d59Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
95e7801d59Ssowmini  * with either a val_desc_t found on the pd_modval list or something
96e7801d59Ssowmini  * generated on the fly.
97d62bc4baSyz147064  */
98e7801d59Ssowmini typedef dladm_status_t	pd_checkf_t(struct prop_desc *pd,
99e7801d59Ssowmini 			    datalink_id_t, char **propstrp,
1006b9e797cSsowmini 			    uint_t cnt, val_desc_t *propval,
1016b9e797cSsowmini 			    datalink_media_t);
102f4b3ec61Sdh155122 
103bcb5c89dSSowmini Varadhan typedef struct link_attr_s {
1043fd94f8cSam223141 	mac_prop_id_t	pp_id;
105e7801d59Ssowmini 	size_t		pp_valsize;
106e7801d59Ssowmini 	char		*pp_name;
107bcb5c89dSSowmini Varadhan } link_attr_t;
108e7801d59Ssowmini 
109bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
110bcb5c89dSSowmini Varadhan 					const char *, uint_t, dladm_status_t *);
111bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
112bcb5c89dSSowmini Varadhan 					mac_prop_id_t, uint_t,
113bcb5c89dSSowmini Varadhan 					dladm_status_t *);
1143bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_set_prop(datalink_id_t, const char *, char **,
115e7801d59Ssowmini 					uint_t, uint_t);
1163bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_get_prop(datalink_id_t, const char *, char **,
1174045d941Ssowmini 					uint_t *, dladm_prop_type_t, uint_t);
118bcb5c89dSSowmini Varadhan static link_attr_t *dladm_name2prop(const char *);
119bcb5c89dSSowmini Varadhan static link_attr_t *dladm_id2prop(mac_prop_id_t);
1203bc21d0aSAruna Ramakrishna - Sun Microsystems static dld_ioc_macprop_t *i_dladm_get_public_prop(datalink_id_t, char *, uint_t,
1213bc21d0aSAruna Ramakrishna - Sun Microsystems 					dladm_status_t *);
122d62bc4baSyz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
123d62bc4baSyz147064 			do_get_rate_prop, do_get_channel_prop,
124e7801d59Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
1253bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_duplex_get, i_dladm_status_get,
1263bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_binary_get, i_dladm_uint32_get,
1273bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_flowctl_get;
1283bc21d0aSAruna Ramakrishna - Sun Microsystems static pd_setf_t	do_set_zone, do_set_rate_prop,
129e7801d59Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
1303bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_set_public_prop;
131e7801d59Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
1323bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_defmtu_check;
133f4b3ec61Sdh155122 
1343bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t	i_dladm_speed_get(struct prop_desc *, datalink_id_t,
1354045d941Ssowmini 			char **, uint_t *, uint_t);
136bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_wlan_get_legacy_ioctl(datalink_id_t, void *,
137bcb5c89dSSowmini Varadhan 			    uint_t, uint_t);
138bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_wlan_set_legacy_ioctl(datalink_id_t, void *,
139bcb5c89dSSowmini Varadhan 			    uint_t, uint_t);
140bcb5c89dSSowmini Varadhan static dladm_status_t	i_dladm_macprop(void *, boolean_t);
1416b9e797cSsowmini 
142f4b3ec61Sdh155122 typedef struct prop_desc {
143d62bc4baSyz147064 	/*
144d62bc4baSyz147064 	 * link property name
145d62bc4baSyz147064 	 */
146f4b3ec61Sdh155122 	char			*pd_name;
147d62bc4baSyz147064 
148d62bc4baSyz147064 	/*
149d62bc4baSyz147064 	 * default property value, can be set to { "", NULL }
150d62bc4baSyz147064 	 */
151f4b3ec61Sdh155122 	val_desc_t		pd_defval;
152d62bc4baSyz147064 
153d62bc4baSyz147064 	/*
154d62bc4baSyz147064 	 * list of optional property values, can be NULL.
155d62bc4baSyz147064 	 *
156d62bc4baSyz147064 	 * This is set to non-NULL if there is a list of possible property
157d62bc4baSyz147064 	 * values.  pd_optval would point to the array of possible values.
158d62bc4baSyz147064 	 */
159d62bc4baSyz147064 	val_desc_t		*pd_optval;
160d62bc4baSyz147064 
161d62bc4baSyz147064 	/*
162d62bc4baSyz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
163d62bc4baSyz147064 	 */
164d62bc4baSyz147064 	uint_t			pd_noptval;
165d62bc4baSyz147064 
166d62bc4baSyz147064 	/*
167d62bc4baSyz147064 	 * callback to set link property;
168d62bc4baSyz147064 	 * set to NULL if this property is read-only
169d62bc4baSyz147064 	 */
170f4b3ec61Sdh155122 	pd_setf_t		*pd_set;
171d62bc4baSyz147064 
172d62bc4baSyz147064 	/*
173d62bc4baSyz147064 	 * callback to get modifiable link property
174d62bc4baSyz147064 	 */
175f4b3ec61Sdh155122 	pd_getf_t		*pd_getmod;
176d62bc4baSyz147064 
177d62bc4baSyz147064 	/*
178d62bc4baSyz147064 	 * callback to get current link property
179d62bc4baSyz147064 	 */
180f4b3ec61Sdh155122 	pd_getf_t		*pd_get;
181d62bc4baSyz147064 
182d62bc4baSyz147064 	/*
183d62bc4baSyz147064 	 * callback to validate link property value, set to NULL if pd_optval
184d62bc4baSyz147064 	 * is not NULL. In that case, validate the value by comparing it with
185d62bc4baSyz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
186d62bc4baSyz147064 	 * valid.
187d62bc4baSyz147064 	 */
188f4b3ec61Sdh155122 	pd_checkf_t		*pd_check;
189d62bc4baSyz147064 
190d62bc4baSyz147064 	uint_t			pd_flags;
191e7801d59Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
192e7801d59Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
193d62bc4baSyz147064 	/*
194d62bc4baSyz147064 	 * indicate link classes this property applies to.
195d62bc4baSyz147064 	 */
196d62bc4baSyz147064 	datalink_class_t	pd_class;
197d62bc4baSyz147064 
198d62bc4baSyz147064 	/*
199d62bc4baSyz147064 	 * indicate link media type this property applies to.
200d62bc4baSyz147064 	 */
201d62bc4baSyz147064 	datalink_media_t	pd_dmedia;
202f4b3ec61Sdh155122 } prop_desc_t;
203f4b3ec61Sdh155122 
2043fd94f8cSam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
205e7801d59Ssowmini 
206bcb5c89dSSowmini Varadhan /*
207bcb5c89dSSowmini Varadhan  * Supported link properties enumerated in the prop_table[] array are
208bcb5c89dSSowmini Varadhan  * computed using the callback functions in that array. To compute the
209bcb5c89dSSowmini Varadhan  * property value, multiple distinct system calls may be needed (e.g.,
210bcb5c89dSSowmini Varadhan  * for wifi speed, we need to issue system calls to get desired/supported
211bcb5c89dSSowmini Varadhan  * rates). The link_attr[] table enumerates the interfaces to the kernel,
212bcb5c89dSSowmini Varadhan  * and the type/size of the data passed in the user-kernel interface.
213bcb5c89dSSowmini Varadhan  */
214bcb5c89dSSowmini Varadhan static link_attr_t link_attr[] = {
215bcb5c89dSSowmini Varadhan 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
216e7801d59Ssowmini 
217bcb5c89dSSowmini Varadhan 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
218e7801d59Ssowmini 
219bcb5c89dSSowmini Varadhan 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
220e7801d59Ssowmini 
221bcb5c89dSSowmini Varadhan 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
222e7801d59Ssowmini 
223bcb5c89dSSowmini Varadhan 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
224e7801d59Ssowmini 
225bcb5c89dSSowmini Varadhan 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
226e7801d59Ssowmini 
227bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
228e7801d59Ssowmini 
229bcb5c89dSSowmini Varadhan 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2303bc21d0aSAruna Ramakrishna - Sun Microsystems 
231bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2323bc21d0aSAruna Ramakrishna - Sun Microsystems 
233bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
234e7801d59Ssowmini 
235bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
236e7801d59Ssowmini 
237bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
238e7801d59Ssowmini 
239bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
240e7801d59Ssowmini 
241bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
242e7801d59Ssowmini 
243bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
244e7801d59Ssowmini 
245bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
246e7801d59Ssowmini 
247bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
248e7801d59Ssowmini 
249bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
250e7801d59Ssowmini 
251bcb5c89dSSowmini Varadhan 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
252e7801d59Ssowmini 
253bcb5c89dSSowmini Varadhan 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
254e7801d59Ssowmini 
255bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
256e7801d59Ssowmini 
257bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
258bcb5c89dSSowmini Varadhan 
259bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
260bcb5c89dSSowmini Varadhan 
261bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
262bcb5c89dSSowmini Varadhan 
263bcb5c89dSSowmini Varadhan 	/* wl_rates_t has variable length */
264bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
265bcb5c89dSSowmini Varadhan 
266bcb5c89dSSowmini Varadhan 	/* wl_rates_t has variable length */
267bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
268bcb5c89dSSowmini Varadhan 
269bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
270bcb5c89dSSowmini Varadhan 
271bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
272bcb5c89dSSowmini Varadhan 
273bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
274bcb5c89dSSowmini Varadhan 
275bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
276bcb5c89dSSowmini Varadhan 
277bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
278bcb5c89dSSowmini Varadhan 
279bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
280bcb5c89dSSowmini Varadhan 
281bcb5c89dSSowmini Varadhan 	/*  wl_wpa_ess_t has variable length */
282bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
283bcb5c89dSSowmini Varadhan 
284bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
285bcb5c89dSSowmini Varadhan 
286bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
287bcb5c89dSSowmini Varadhan 
288bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
289bcb5c89dSSowmini Varadhan 
290bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
291bcb5c89dSSowmini Varadhan 
292bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
293bcb5c89dSSowmini Varadhan 
294bcb5c89dSSowmini Varadhan 	/* wl_wpa_ie_t has variable length */
295bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
296bcb5c89dSSowmini Varadhan 
297bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
298bcb5c89dSSowmini Varadhan 
299bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
300bcb5c89dSSowmini Varadhan 
301bcb5c89dSSowmini Varadhan 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
302bcb5c89dSSowmini Varadhan 
303bcb5c89dSSowmini Varadhan 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
304e7801d59Ssowmini };
305e7801d59Ssowmini 
306e7801d59Ssowmini static  val_desc_t	link_duplex_vals[] = {
307e7801d59Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
308e7801d59Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
309e7801d59Ssowmini };
310e7801d59Ssowmini static  val_desc_t	link_status_vals[] = {
311e7801d59Ssowmini 	{ "up",		LINK_STATE_UP		},
312e7801d59Ssowmini 	{ "down",	LINK_STATE_DOWN		}
313e7801d59Ssowmini };
314e7801d59Ssowmini static  val_desc_t	link_01_vals[] = {
315e7801d59Ssowmini 	{ "1",		1			},
316e7801d59Ssowmini 	{ "0",		0			}
317e7801d59Ssowmini };
318e7801d59Ssowmini static  val_desc_t	link_flow_vals[] = {
319e7801d59Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
320e7801d59Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
321e7801d59Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
322e7801d59Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
323e7801d59Ssowmini };
324e7801d59Ssowmini 
325e7801d59Ssowmini #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
326e7801d59Ssowmini 
327d62bc4baSyz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
328d62bc4baSyz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
329d62bc4baSyz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
330d62bc4baSyz147064 };
331d62bc4baSyz147064 
332d62bc4baSyz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
333d62bc4baSyz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
334d62bc4baSyz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
335d62bc4baSyz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
336d62bc4baSyz147064 };
337d62bc4baSyz147064 
338f4b3ec61Sdh155122 static prop_desc_t	prop_table[] = {
339d62bc4baSyz147064 
340e7801d59Ssowmini 	{ "channel",	{ NULL, 0 },
341e7801d59Ssowmini 	    NULL, 0, NULL, NULL,
342d62bc4baSyz147064 	    do_get_channel_prop, NULL, 0,
343d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
344d62bc4baSyz147064 
345d62bc4baSyz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
346d62bc4baSyz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
347d62bc4baSyz147064 	    do_set_powermode_prop, NULL,
348d62bc4baSyz147064 	    do_get_powermode_prop, NULL, 0,
349d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
350d62bc4baSyz147064 
351d62bc4baSyz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
352d62bc4baSyz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
353d62bc4baSyz147064 	    do_set_radio_prop, NULL,
354d62bc4baSyz147064 	    do_get_radio_prop, NULL, 0,
355d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
356d62bc4baSyz147064 
357d62bc4baSyz147064 	{ "speed",	{ "", 0 }, NULL, 0,
358d62bc4baSyz147064 	    do_set_rate_prop, do_get_rate_mod,
359d62bc4baSyz147064 	    do_get_rate_prop, do_check_rate, 0,
3606b9e797cSsowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
361d62bc4baSyz147064 
3624045d941Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
3633bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL,
3643bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
365d62bc4baSyz147064 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
366d62bc4baSyz147064 
3674045d941Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
368f4b3ec61Sdh155122 	    do_set_zone, NULL,
3693bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
370e7801d59Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
371e7801d59Ssowmini 
3724045d941Ssowmini 	{ "duplex", { "", 0 },
373e7801d59Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
3743bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_duplex_get, NULL,
375e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
376e7801d59Ssowmini 
3776b9e797cSsowmini 	{ "state", { "up", LINK_STATE_UP },
378e7801d59Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
3793bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_status_get, NULL,
3804045d941Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
381e7801d59Ssowmini 
382e7801d59Ssowmini 	{ "adv_autoneg_cap", { "1", 1 },
383e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
3843bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
385e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
386e7801d59Ssowmini 
3874045d941Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
3883bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
3893bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL,
3903bc21d0aSAruna Ramakrishna - Sun Microsystems 	    DATALINK_ANY_MEDIATYPE },
391e7801d59Ssowmini 
3924045d941Ssowmini 	{ "flowctrl", { "", 0 },
393e7801d59Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
3943bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
395e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
396e7801d59Ssowmini 
3974045d941Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
3984045d941Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
3993bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
400e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
401e7801d59Ssowmini 
4024045d941Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
403e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4043bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
405e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
406e7801d59Ssowmini 
4074045d941Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
408e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4093bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
410e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
411e7801d59Ssowmini 
4124045d941Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
413e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4143bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
415e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
416e7801d59Ssowmini 
4174045d941Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
418e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4193bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
420e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
421e7801d59Ssowmini 
4224045d941Ssowmini 	{ "en_100fdx_cap", { "", 0 },
423e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4243bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
425e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
426e7801d59Ssowmini 
4274045d941Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
428e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4293bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
430e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
431e7801d59Ssowmini 
4324045d941Ssowmini 	{ "en_100hdx_cap", { "", 0 },
433e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4343bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
435e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
436e7801d59Ssowmini 
4374045d941Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
438e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4393bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
440e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
441e7801d59Ssowmini 
4424045d941Ssowmini 	{ "en_10fdx_cap", { "", 0 },
443e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4443bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
445e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
446e7801d59Ssowmini 
4474045d941Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
448e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4493bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
450e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
451e7801d59Ssowmini 
4524045d941Ssowmini 	{ "en_10hdx_cap", { "", 0 },
453e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4543bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
455e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER }
456e7801d59Ssowmini 
457f4b3ec61Sdh155122 };
458f4b3ec61Sdh155122 
459d62bc4baSyz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
4600ba2cbe9Sxc151355 
461bcb5c89dSSowmini Varadhan /*
462bcb5c89dSSowmini Varadhan  * when retrieving  private properties, we pass down a buffer with
463bcb5c89dSSowmini Varadhan  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
464bcb5c89dSSowmini Varadhan  */
465bcb5c89dSSowmini Varadhan #define	DLADM_PROP_BUF_CHUNK	1024
466bcb5c89dSSowmini Varadhan 
467d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop_db(datalink_id_t, const char *,
468d62bc4baSyz147064 			    char **, uint_t);
469d62bc4baSyz147064 static dladm_status_t	i_dladm_get_linkprop_db(datalink_id_t, const char *,
470d62bc4baSyz147064 			    char **, uint_t *);
471d62bc4baSyz147064 static dladm_status_t	i_dladm_set_single_prop(datalink_id_t, datalink_class_t,
472d62bc4baSyz147064 			    uint32_t, prop_desc_t *, char **, uint_t, uint_t);
473d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop(datalink_id_t, const char *,
474d62bc4baSyz147064 			    char **, uint_t, uint_t);
4754045d941Ssowmini static dladm_status_t	i_dladm_getset_defval(prop_desc_t *, datalink_id_t,
4764045d941Ssowmini 			    datalink_media_t, uint_t);
477d62bc4baSyz147064 /*
478d62bc4baSyz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
479d62bc4baSyz147064  * rates to be retrieved. However, we cannot increase it at this
480d62bc4baSyz147064  * time because it will break binary compatibility with unbundled
481d62bc4baSyz147064  * WiFi drivers and utilities. So for now we define an additional
482d62bc4baSyz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
483d62bc4baSyz147064  */
484d62bc4baSyz147064 #define	MAX_SUPPORT_RATES	64
485d62bc4baSyz147064 
486d62bc4baSyz147064 #define	AP_ANCHOR	"[anchor]"
487d62bc4baSyz147064 #define	AP_DELIMITER	'.'
488d62bc4baSyz147064 
489d62bc4baSyz147064 static dladm_status_t
490d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
491d62bc4baSyz147064     val_desc_t *vdp)
4920ba2cbe9Sxc151355 {
493d62bc4baSyz147064 	int		i, j;
4940ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
4950ba2cbe9Sxc151355 
496d62bc4baSyz147064 	for (j = 0; j < val_cnt; j++) {
497d62bc4baSyz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
498d62bc4baSyz147064 			if (strcasecmp(*prop_val,
499d62bc4baSyz147064 			    pdp->pd_optval[i].vd_name) == 0) {
5000ba2cbe9Sxc151355 				break;
5010ba2cbe9Sxc151355 			}
5020ba2cbe9Sxc151355 		}
503d62bc4baSyz147064 		if (i == pdp->pd_noptval) {
504d62bc4baSyz147064 			status = DLADM_STATUS_BADVAL;
505d62bc4baSyz147064 			goto done;
506d62bc4baSyz147064 		}
507d62bc4baSyz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
5080ba2cbe9Sxc151355 	}
5090ba2cbe9Sxc151355 
510d62bc4baSyz147064 done:
511d62bc4baSyz147064 	return (status);
5120ba2cbe9Sxc151355 }
5130ba2cbe9Sxc151355 
5140ba2cbe9Sxc151355 static dladm_status_t
515d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
516d62bc4baSyz147064     uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
517d62bc4baSyz147064     uint_t flags)
5180ba2cbe9Sxc151355 {
5190ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
520d62bc4baSyz147064 	val_desc_t	*vdp = NULL;
521d62bc4baSyz147064 	boolean_t	needfree = B_FALSE;
522d62bc4baSyz147064 	uint_t		cnt, i;
5230ba2cbe9Sxc151355 
524d62bc4baSyz147064 	if (!(pdp->pd_class & class))
525d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
5260ba2cbe9Sxc151355 
527d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
528d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
529d62bc4baSyz147064 
530d62bc4baSyz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
531d62bc4baSyz147064 		return (DLADM_STATUS_TEMPONLY);
532d62bc4baSyz147064 
533d62bc4baSyz147064 	if (!(flags & DLADM_OPT_ACTIVE))
534d62bc4baSyz147064 		return (DLADM_STATUS_OK);
535d62bc4baSyz147064 
536d62bc4baSyz147064 	if (pdp->pd_set == NULL)
537d62bc4baSyz147064 		return (DLADM_STATUS_PROPRDONLY);
538d62bc4baSyz147064 
539e7801d59Ssowmini 	if (pdp->pd_flags & PD_CHECK_ALLOC)
540e7801d59Ssowmini 		needfree = B_TRUE;
541e7801d59Ssowmini 	else
542e7801d59Ssowmini 		needfree = B_FALSE;
543d62bc4baSyz147064 	if (prop_val != NULL) {
544d62bc4baSyz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
545d62bc4baSyz147064 		if (vdp == NULL)
546d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
547d62bc4baSyz147064 
548e7801d59Ssowmini 
549d62bc4baSyz147064 		if (pdp->pd_check != NULL) {
550e7801d59Ssowmini 			status = pdp->pd_check(pdp, linkid, prop_val, val_cnt,
5516b9e797cSsowmini 			    vdp, media);
552d62bc4baSyz147064 		} else if (pdp->pd_optval != NULL) {
553d62bc4baSyz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
554d62bc4baSyz147064 		} else {
555d62bc4baSyz147064 			status = DLADM_STATUS_BADARG;
5560ba2cbe9Sxc151355 		}
5570ba2cbe9Sxc151355 
558d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
559d62bc4baSyz147064 			goto done;
560d62bc4baSyz147064 
561d62bc4baSyz147064 		cnt = val_cnt;
562d62bc4baSyz147064 	} else {
563d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL)
564d62bc4baSyz147064 			return (DLADM_STATUS_NOTSUP);
565d62bc4baSyz147064 
5663bc21d0aSAruna Ramakrishna - Sun Microsystems 		cnt = 1;
5673bc21d0aSAruna Ramakrishna - Sun Microsystems 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 ||
5684045d941Ssowmini 		    strlen(pdp->pd_defval.vd_name) > 0) {
569d62bc4baSyz147064 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
570d62bc4baSyz147064 				return (DLADM_STATUS_NOMEM);
5713bc21d0aSAruna Ramakrishna - Sun Microsystems 
5723bc21d0aSAruna Ramakrishna - Sun Microsystems 			if (pdp->pd_check != NULL) {
5733bc21d0aSAruna Ramakrishna - Sun Microsystems 				status = pdp->pd_check(pdp, linkid, prop_val,
5743bc21d0aSAruna Ramakrishna - Sun Microsystems 				    cnt, vdp, media);
5753bc21d0aSAruna Ramakrishna - Sun Microsystems 				if (status != DLADM_STATUS_OK)
5763bc21d0aSAruna Ramakrishna - Sun Microsystems 					goto done;
5773bc21d0aSAruna Ramakrishna - Sun Microsystems 			} else {
5784045d941Ssowmini 				(void) memcpy(vdp, &pdp->pd_defval,
5794045d941Ssowmini 				    sizeof (val_desc_t));
5803bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
5814045d941Ssowmini 		} else {
5824045d941Ssowmini 			status = i_dladm_getset_defval(pdp, linkid,
5834045d941Ssowmini 			    media, flags);
5844045d941Ssowmini 			return (status);
5854045d941Ssowmini 		}
586d62bc4baSyz147064 	}
5876b9e797cSsowmini 	status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media);
588d62bc4baSyz147064 	if (needfree) {
589d62bc4baSyz147064 		for (i = 0; i < cnt; i++)
590e7801d59Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
591d62bc4baSyz147064 	}
592d62bc4baSyz147064 done:
593d62bc4baSyz147064 	free(vdp);
594d62bc4baSyz147064 	return (status);
595d62bc4baSyz147064 }
596d62bc4baSyz147064 
597d62bc4baSyz147064 static dladm_status_t
598d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name,
599d62bc4baSyz147064     char **prop_val, uint_t val_cnt, uint_t flags)
600d62bc4baSyz147064 {
601d62bc4baSyz147064 	int			i;
602d62bc4baSyz147064 	boolean_t		found = B_FALSE;
603d62bc4baSyz147064 	datalink_class_t	class;
604d62bc4baSyz147064 	uint32_t		media;
605d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
606d62bc4baSyz147064 
607d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
608d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
6090ba2cbe9Sxc151355 		return (status);
6100ba2cbe9Sxc151355 
611d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
612d62bc4baSyz147064 		prop_desc_t	*pdp = &prop_table[i];
613d62bc4baSyz147064 		dladm_status_t	s;
6140ba2cbe9Sxc151355 
615d62bc4baSyz147064 		if (prop_name != NULL &&
616d62bc4baSyz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
617d62bc4baSyz147064 			continue;
618d62bc4baSyz147064 
619d62bc4baSyz147064 		found = B_TRUE;
620d62bc4baSyz147064 		s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val,
621d62bc4baSyz147064 		    val_cnt, flags);
622d62bc4baSyz147064 
623d62bc4baSyz147064 		if (prop_name != NULL) {
624d62bc4baSyz147064 			status = s;
625d62bc4baSyz147064 			break;
626d62bc4baSyz147064 		} else {
627d62bc4baSyz147064 			if (s != DLADM_STATUS_OK &&
628d62bc4baSyz147064 			    s != DLADM_STATUS_NOTSUP)
629d62bc4baSyz147064 				status = s;
630d62bc4baSyz147064 		}
631d62bc4baSyz147064 	}
632e7801d59Ssowmini 	if (!found) {
633e7801d59Ssowmini 		if (prop_name[0] == '_') {
634e7801d59Ssowmini 			/* other private properties */
6353bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = i_dladm_set_prop(linkid, prop_name, prop_val,
636e7801d59Ssowmini 			    val_cnt, flags);
637e7801d59Ssowmini 		} else  {
6380ba2cbe9Sxc151355 			status = DLADM_STATUS_NOTFOUND;
639e7801d59Ssowmini 		}
640e7801d59Ssowmini 	}
6410ba2cbe9Sxc151355 
6420ba2cbe9Sxc151355 	return (status);
6430ba2cbe9Sxc151355 }
6440ba2cbe9Sxc151355 
645d62bc4baSyz147064 /*
646d62bc4baSyz147064  * Set/reset link property for specific link
647d62bc4baSyz147064  */
648d62bc4baSyz147064 dladm_status_t
649d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val,
650d62bc4baSyz147064     uint_t val_cnt, uint_t flags)
6510ba2cbe9Sxc151355 {
652d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6530ba2cbe9Sxc151355 
654d62bc4baSyz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
655d62bc4baSyz147064 	    (prop_val == NULL && val_cnt > 0) ||
656d62bc4baSyz147064 	    (prop_val != NULL && val_cnt == 0) ||
657d62bc4baSyz147064 	    (prop_name == NULL && prop_val != NULL)) {
658d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
6590ba2cbe9Sxc151355 	}
6600ba2cbe9Sxc151355 
661d62bc4baSyz147064 	status = i_dladm_set_linkprop(linkid, prop_name, prop_val,
662d62bc4baSyz147064 	    val_cnt, flags);
663d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
664d62bc4baSyz147064 		return (status);
665d62bc4baSyz147064 
666d62bc4baSyz147064 	if (flags & DLADM_OPT_PERSIST) {
667d62bc4baSyz147064 		status = i_dladm_set_linkprop_db(linkid, prop_name,
668d62bc4baSyz147064 		    prop_val, val_cnt);
669d62bc4baSyz147064 	}
670d62bc4baSyz147064 	return (status);
671d62bc4baSyz147064 }
672d62bc4baSyz147064 
673d62bc4baSyz147064 /*
674d62bc4baSyz147064  * Walk link properties of the given specific link.
675d62bc4baSyz147064  */
676d62bc4baSyz147064 dladm_status_t
677d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg,
678d62bc4baSyz147064     int (*func)(datalink_id_t, const char *, void *))
6790ba2cbe9Sxc151355 {
680d62bc4baSyz147064 	dladm_status_t		status;
681d62bc4baSyz147064 	datalink_class_t	class;
682d62bc4baSyz147064 	uint_t			media;
683d62bc4baSyz147064 	int			i;
6840ba2cbe9Sxc151355 
685d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
686d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
6870ba2cbe9Sxc151355 
688d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
689d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
690d62bc4baSyz147064 		return (status);
691d62bc4baSyz147064 
692d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
693d62bc4baSyz147064 		if (!(prop_table[i].pd_class & class))
694d62bc4baSyz147064 			continue;
695d62bc4baSyz147064 
696d62bc4baSyz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
697d62bc4baSyz147064 			continue;
698d62bc4baSyz147064 
699d62bc4baSyz147064 		if (func(linkid, prop_table[i].pd_name, arg) ==
700d62bc4baSyz147064 		    DLADM_WALK_TERMINATE) {
701d62bc4baSyz147064 			break;
702d62bc4baSyz147064 		}
703d62bc4baSyz147064 	}
704d62bc4baSyz147064 
705d62bc4baSyz147064 	return (DLADM_STATUS_OK);
706d62bc4baSyz147064 }
707d62bc4baSyz147064 
708d62bc4baSyz147064 /*
709d62bc4baSyz147064  * Get linkprop of the given specific link.
710d62bc4baSyz147064  */
711d62bc4baSyz147064 dladm_status_t
712d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
713d62bc4baSyz147064     const char *prop_name, char **prop_val, uint_t *val_cntp)
714d62bc4baSyz147064 {
715d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
716d62bc4baSyz147064 	datalink_class_t	class;
717d62bc4baSyz147064 	uint_t			media;
718d62bc4baSyz147064 	prop_desc_t		*pdp;
7194045d941Ssowmini 	uint_t			cnt, dld_flags = 0;
720d62bc4baSyz147064 	int			i;
721d62bc4baSyz147064 
7224045d941Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
7233fd94f8cSam223141 		dld_flags = MAC_PROP_DEFAULT;
7244045d941Ssowmini 
725d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
726d62bc4baSyz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
727d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
728d62bc4baSyz147064 
729d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
730d62bc4baSyz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
731d62bc4baSyz147064 			break;
732d62bc4baSyz147064 
733e7801d59Ssowmini 	if (i == DLADM_MAX_PROPS) {
734e7801d59Ssowmini 		if (prop_name[0] == '_') {
735e7801d59Ssowmini 			/*
736e7801d59Ssowmini 			 * private property.
737e7801d59Ssowmini 			 */
7383bc21d0aSAruna Ramakrishna - Sun Microsystems 			return (i_dladm_get_prop(linkid, prop_name,
7394045d941Ssowmini 			    prop_val, val_cntp, type, dld_flags));
740e7801d59Ssowmini 		} else {
741d62bc4baSyz147064 			return (DLADM_STATUS_NOTFOUND);
742e7801d59Ssowmini 		}
743e7801d59Ssowmini 	}
744d62bc4baSyz147064 
745d62bc4baSyz147064 	pdp = &prop_table[i];
746d62bc4baSyz147064 
747d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
748d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
749d62bc4baSyz147064 		return (status);
750d62bc4baSyz147064 
751d62bc4baSyz147064 	if (!(pdp->pd_class & class))
752d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
753d62bc4baSyz147064 
754d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
755d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
756d62bc4baSyz147064 
757d62bc4baSyz147064 	switch (type) {
758d62bc4baSyz147064 	case DLADM_PROP_VAL_CURRENT:
7594045d941Ssowmini 		status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media,
7604045d941Ssowmini 		    dld_flags);
761d62bc4baSyz147064 		break;
762d62bc4baSyz147064 
763d62bc4baSyz147064 	case DLADM_PROP_VAL_DEFAULT:
76413a55820Sar224390 		/*
76513a55820Sar224390 		 * If defaults are not defined for the property,
76613a55820Sar224390 		 * pd_defval.vd_name should be null. If the driver
76713a55820Sar224390 		 * has to be contacted for the value, vd_name should
76813a55820Sar224390 		 * be the empty string (""). Otherwise, dladm will
76913a55820Sar224390 		 * just print whatever is in the table.
77013a55820Sar224390 		 */
771d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL) {
772d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
773d62bc4baSyz147064 			break;
774d62bc4baSyz147064 		}
7754045d941Ssowmini 
7764045d941Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
7774045d941Ssowmini 			status = pdp->pd_get(pdp, linkid, prop_val, val_cntp,
7784045d941Ssowmini 			    media, dld_flags);
7794045d941Ssowmini 		} else {
780d62bc4baSyz147064 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
7814045d941Ssowmini 		}
782d62bc4baSyz147064 		*val_cntp = 1;
783d62bc4baSyz147064 		break;
784d62bc4baSyz147064 
785d62bc4baSyz147064 	case DLADM_PROP_VAL_MODIFIABLE:
786d62bc4baSyz147064 		if (pdp->pd_getmod != NULL) {
787e7801d59Ssowmini 			status = pdp->pd_getmod(pdp, linkid, prop_val,
7884045d941Ssowmini 			    val_cntp, media, dld_flags);
789d62bc4baSyz147064 			break;
790d62bc4baSyz147064 		}
791d62bc4baSyz147064 		cnt = pdp->pd_noptval;
792d62bc4baSyz147064 		if (cnt == 0) {
793d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
794d62bc4baSyz147064 		} else if (cnt > *val_cntp) {
795d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
796d62bc4baSyz147064 		} else {
797d62bc4baSyz147064 			for (i = 0; i < cnt; i++) {
798d62bc4baSyz147064 				(void) strcpy(prop_val[i],
799d62bc4baSyz147064 				    pdp->pd_optval[i].vd_name);
800d62bc4baSyz147064 			}
801d62bc4baSyz147064 			*val_cntp = cnt;
802d62bc4baSyz147064 		}
803d62bc4baSyz147064 		break;
804d62bc4baSyz147064 	case DLADM_PROP_VAL_PERSISTENT:
805d62bc4baSyz147064 		if (pdp->pd_flags & PD_TEMPONLY)
806d62bc4baSyz147064 			return (DLADM_STATUS_TEMPONLY);
807d62bc4baSyz147064 		status = i_dladm_get_linkprop_db(linkid, prop_name,
808d62bc4baSyz147064 		    prop_val, val_cntp);
809d62bc4baSyz147064 		break;
810d62bc4baSyz147064 	default:
811d62bc4baSyz147064 		status = DLADM_STATUS_BADARG;
812d62bc4baSyz147064 		break;
813d62bc4baSyz147064 	}
814d62bc4baSyz147064 
815d62bc4baSyz147064 	return (status);
816d62bc4baSyz147064 }
817d62bc4baSyz147064 
818d62bc4baSyz147064 /*ARGSUSED*/
819d62bc4baSyz147064 static int
820d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg)
821d62bc4baSyz147064 {
822d62bc4baSyz147064 	char	*buf, **propvals;
823d62bc4baSyz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
824d62bc4baSyz147064 
825d62bc4baSyz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
826d62bc4baSyz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
827d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
828d62bc4baSyz147064 	}
829d62bc4baSyz147064 
830d62bc4baSyz147064 	propvals = (char **)(void *)buf;
831d62bc4baSyz147064 	for (i = 0; i < valcnt; i++) {
832d62bc4baSyz147064 		propvals[i] = buf +
833d62bc4baSyz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
834d62bc4baSyz147064 		    i * DLADM_PROP_VAL_MAX;
835d62bc4baSyz147064 	}
836d62bc4baSyz147064 
837d62bc4baSyz147064 	if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name,
838d62bc4baSyz147064 	    propvals, &valcnt) != DLADM_STATUS_OK) {
839d62bc4baSyz147064 		goto done;
840d62bc4baSyz147064 	}
841d62bc4baSyz147064 
842d62bc4baSyz147064 	(void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt,
843d62bc4baSyz147064 	    DLADM_OPT_ACTIVE);
844d62bc4baSyz147064 
845d62bc4baSyz147064 done:
846d62bc4baSyz147064 	if (buf != NULL)
847d62bc4baSyz147064 		free(buf);
848d62bc4baSyz147064 
849d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
850d62bc4baSyz147064 }
851d62bc4baSyz147064 
852d62bc4baSyz147064 /*ARGSUSED*/
853d62bc4baSyz147064 static int
854d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg)
855d62bc4baSyz147064 {
85630890389Sartem 	(void) dladm_init_linkprop(linkid, B_TRUE);
857d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
8580ba2cbe9Sxc151355 }
8590ba2cbe9Sxc151355 
8600ba2cbe9Sxc151355 dladm_status_t
86130890389Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media)
8620ba2cbe9Sxc151355 {
86330890389Sartem 	datalink_media_t	dmedia;
86430890389Sartem 	uint32_t		media;
86530890389Sartem 
86630890389Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
86730890389Sartem 
868d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
869d62bc4baSyz147064 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL,
87030890389Sartem 		    DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
87130890389Sartem 	} else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL,
87230890389Sartem 	    &media, NULL, 0) == DLADM_STATUS_OK) &&
87330890389Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
874d62bc4baSyz147064 		(void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop);
875d62bc4baSyz147064 	}
876d62bc4baSyz147064 	return (DLADM_STATUS_OK);
8770ba2cbe9Sxc151355 }
878f4b3ec61Sdh155122 
879e7801d59Ssowmini /* ARGSUSED */
880f4b3ec61Sdh155122 static dladm_status_t
881e7801d59Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid,
8824045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
883f4b3ec61Sdh155122 {
884d62bc4baSyz147064 	char		zone_name[ZONENAME_MAX];
885d62bc4baSyz147064 	zoneid_t	zid;
886d62bc4baSyz147064 	dladm_status_t	status;
8873bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
8883bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
889f4b3ec61Sdh155122 
8904045d941Ssowmini 	if (flags != 0)
8914045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
8924045d941Ssowmini 
8933bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
894d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
895d62bc4baSyz147064 		return (status);
896d62bc4baSyz147064 
8973bc21d0aSAruna Ramakrishna - Sun Microsystems 	cp = dip->pr_val;
8983bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&zid, cp, sizeof (zid));
8993bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
9003bc21d0aSAruna Ramakrishna - Sun Microsystems 
901d62bc4baSyz147064 	*val_cnt = 1;
902d62bc4baSyz147064 	if (zid != GLOBAL_ZONEID) {
903d62bc4baSyz147064 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
904f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
905f4b3ec61Sdh155122 
906d62bc4baSyz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
90747a01978Sbw 	} else {
908d62bc4baSyz147064 		*prop_val[0] = '\0';
90947a01978Sbw 	}
910f4b3ec61Sdh155122 
911f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
912f4b3ec61Sdh155122 }
913f4b3ec61Sdh155122 
914f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
915f4b3ec61Sdh155122 
916f4b3ec61Sdh155122 static int
917f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
918f4b3ec61Sdh155122 {
919f4b3ec61Sdh155122 	char			root[MAXPATHLEN];
920f4b3ec61Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
921f4b3ec61Sdh155122 	void			*dlhandle;
922f4b3ec61Sdh155122 	void			*sym;
923f4b3ec61Sdh155122 	int			ret;
924f4b3ec61Sdh155122 
925f4b3ec61Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
926f4b3ec61Sdh155122 		return (-1);
927f4b3ec61Sdh155122 
928f4b3ec61Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
929f4b3ec61Sdh155122 		(void) dlclose(dlhandle);
930f4b3ec61Sdh155122 		return (-1);
931f4b3ec61Sdh155122 	}
932f4b3ec61Sdh155122 
933f4b3ec61Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
934f4b3ec61Sdh155122 
935f4b3ec61Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
936f4b3ec61Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
937f4b3ec61Sdh155122 	(void) dlclose(dlhandle);
938f4b3ec61Sdh155122 	return (ret);
939f4b3ec61Sdh155122 }
940f4b3ec61Sdh155122 
941f4b3ec61Sdh155122 static dladm_status_t
942d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add)
943f4b3ec61Sdh155122 {
944f4b3ec61Sdh155122 	char		path[MAXPATHLEN];
945d62bc4baSyz147064 	char		name[MAXLINKNAMELEN];
946f4b3ec61Sdh155122 	di_prof_t	prof = NULL;
947f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
948f4b3ec61Sdh155122 	dladm_status_t	status;
949d62bc4baSyz147064 	int		ret;
950f4b3ec61Sdh155122 
951f4b3ec61Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
952f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
953f4b3ec61Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
954f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
955f4b3ec61Sdh155122 	if (di_prof_init(path, &prof) != 0)
956f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
957f4b3ec61Sdh155122 
958d62bc4baSyz147064 	status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN);
959f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
960d62bc4baSyz147064 		goto cleanup;
961f4b3ec61Sdh155122 
962d62bc4baSyz147064 	if (add)
963d62bc4baSyz147064 		ret = di_prof_add_dev(prof, name);
964d62bc4baSyz147064 	else
965d62bc4baSyz147064 		ret = di_prof_add_exclude(prof, name);
966f4b3ec61Sdh155122 
967d62bc4baSyz147064 	if (ret != 0) {
968d62bc4baSyz147064 		status = dladm_errno2status(errno);
969d62bc4baSyz147064 		goto cleanup;
970f4b3ec61Sdh155122 	}
971f4b3ec61Sdh155122 
972d62bc4baSyz147064 	if (di_prof_commit(prof) != 0)
973d62bc4baSyz147064 		status = dladm_errno2status(errno);
974d62bc4baSyz147064 cleanup:
975d62bc4baSyz147064 	if (prof)
976d62bc4baSyz147064 		di_prof_fini(prof);
977d62bc4baSyz147064 
978d62bc4baSyz147064 	return (status);
979f4b3ec61Sdh155122 }
980f4b3ec61Sdh155122 
981e7801d59Ssowmini /* ARGSUSED */
982f4b3ec61Sdh155122 static dladm_status_t
9836b9e797cSsowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp,
9846b9e797cSsowmini     uint_t val_cnt, uint_t flags, datalink_media_t media)
985f4b3ec61Sdh155122 {
9863bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status = DLADM_STATUS_OK;
987f4b3ec61Sdh155122 	zoneid_t	zid_old, zid_new;
988d62bc4baSyz147064 	char		link[MAXLINKNAMELEN];
9893bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
9903bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
9913bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t		*dzp;
992f4b3ec61Sdh155122 
993f4b3ec61Sdh155122 	if (val_cnt != 1)
994f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
995f4b3ec61Sdh155122 
9963bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
9973bc21d0aSAruna Ramakrishna - Sun Microsystems 
9983bc21d0aSAruna Ramakrishna - Sun Microsystems 	/*
9993bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * If diz_is_ppa_hack is set, then an implicit vlan must be created.
10003bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * There is no old value to compare against, and vdp->vd_val is
10013bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * already populated with the zoneid and linkname in the function
10023bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * do_check_zone().
10033bc21d0aSAruna Ramakrishna - Sun Microsystems 	 */
10043bc21d0aSAruna Ramakrishna - Sun Microsystems 
10053bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dzp->diz_is_ppa_hack) {
10063bc21d0aSAruna Ramakrishna - Sun Microsystems 		zid_old = GLOBAL_ZONEID;
10073bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
10083bc21d0aSAruna Ramakrishna - Sun Microsystems 		dip = i_dladm_get_public_prop(linkid, pd->pd_name,
10093bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, &status);
1010f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
1011f4b3ec61Sdh155122 			return (status);
1012f4b3ec61Sdh155122 
10133bc21d0aSAruna Ramakrishna - Sun Microsystems 		cp = dip->pr_val;
10143bc21d0aSAruna Ramakrishna - Sun Microsystems 		(void) memcpy(&zid_old, cp, sizeof (zid_old));
10153bc21d0aSAruna Ramakrishna - Sun Microsystems 		free(dip);
1016d62bc4baSyz147064 	}
1017f4b3ec61Sdh155122 
10183bc21d0aSAruna Ramakrishna - Sun Microsystems 	zid_new = dzp->diz_zid;
10193bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
10203bc21d0aSAruna Ramakrishna - Sun Microsystems 
10213bc21d0aSAruna Ramakrishna - Sun Microsystems 	/* Do nothing if setting to current value */
10223bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new == zid_old)
10233bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (status);
10243bc21d0aSAruna Ramakrishna - Sun Microsystems 
1025d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
1026d62bc4baSyz147064 		/*
1027d62bc4baSyz147064 		 * If the new zoneid is the global zone, we could destroy
1028d62bc4baSyz147064 		 * the link (in the case of an implicitly-created VLAN) as a
10293bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * result of setting the zoneid. In that case, we defer the
10303bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * operation to the end of this function to avoid recreating
10313bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * the VLAN and getting a different linkid during the rollback
10323bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * if other operation fails.
1033d62bc4baSyz147064 		 *
10343bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * Otherwise, this operation will hold a reference to the
1035d62bc4baSyz147064 		 * link and prevent a link renaming, so we need to do it
1036d62bc4baSyz147064 		 * before other operations.
1037d62bc4baSyz147064 		 */
10383bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
10393bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1040d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
1041d62bc4baSyz147064 			return (status);
1042d62bc4baSyz147064 	}
1043d62bc4baSyz147064 
1044d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID) {
1045d62bc4baSyz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
1046f4b3ec61Sdh155122 		    errno != ENXIO) {
1047f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
1048f4b3ec61Sdh155122 			goto rollback1;
1049f4b3ec61Sdh155122 		}
1050f4b3ec61Sdh155122 
1051d62bc4baSyz147064 		/*
1052d62bc4baSyz147064 		 * It is okay to fail to update the /dev entry (some
1053d62bc4baSyz147064 		 * vanity-named links do not have a /dev entry).
1054d62bc4baSyz147064 		 */
1055d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_FALSE);
1056d62bc4baSyz147064 	}
1057d62bc4baSyz147064 
1058d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
1059d62bc4baSyz147064 		if (zone_add_datalink(zid_new, link) != 0) {
1060d62bc4baSyz147064 			status = dladm_errno2status(errno);
1061d62bc4baSyz147064 			goto rollback2;
1062d62bc4baSyz147064 		}
1063d62bc4baSyz147064 
10643bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (dzp->diz_is_ppa_hack) {
10653bc21d0aSAruna Ramakrishna - Sun Microsystems 			if ((status = dladm_name2info(link, &linkid, NULL, NULL,
10663bc21d0aSAruna Ramakrishna - Sun Microsystems 			    NULL)) != DLADM_STATUS_OK) {
10673bc21d0aSAruna Ramakrishna - Sun Microsystems 				return (status);
10683bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
10693bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
10703bc21d0aSAruna Ramakrishna - Sun Microsystems 
1071d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_new, linkid, B_TRUE);
1072d62bc4baSyz147064 	} else {
10733bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
10743bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1075f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
1076f4b3ec61Sdh155122 			goto rollback2;
1077f4b3ec61Sdh155122 	}
1078f4b3ec61Sdh155122 
1079f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1080f4b3ec61Sdh155122 
1081f4b3ec61Sdh155122 rollback2:
1082f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID)
1083d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_TRUE);
1084d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID)
1085d62bc4baSyz147064 		(void) zone_add_datalink(zid_old, link);
1086f4b3ec61Sdh155122 rollback1:
10873bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new != GLOBAL_ZONEID) {
10883bc21d0aSAruna Ramakrishna - Sun Microsystems 		dzp->diz_zid = zid_old;
10893bc21d0aSAruna Ramakrishna - Sun Microsystems 		(void) i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
10903bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
10913bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
10923bc21d0aSAruna Ramakrishna - Sun Microsystems 
1093f4b3ec61Sdh155122 	return (status);
1094f4b3ec61Sdh155122 }
1095f4b3ec61Sdh155122 
1096f4b3ec61Sdh155122 /* ARGSUSED */
1097f4b3ec61Sdh155122 static dladm_status_t
1098e7801d59Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
10996b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1100f4b3ec61Sdh155122 {
11013bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*zone_name;
11023bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		linkname[MAXLINKNAMELEN];
11033bc21d0aSAruna Ramakrishna - Sun Microsystems 	zoneid_t	zoneid;
11043bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
11053bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status = DLADM_STATUS_OK;
11063bc21d0aSAruna Ramakrishna - Sun Microsystems 	boolean_t	is_ppa_hack = B_FALSE;
11073bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t	*dzp;
1108f4b3ec61Sdh155122 
1109f4b3ec61Sdh155122 	if (val_cnt != 1)
1110f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
1111f4b3ec61Sdh155122 
11123bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = malloc(sizeof (dld_ioc_zid_t));
11133bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dzp == NULL)
11143bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (DLADM_STATUS_NOMEM);
1115f4b3ec61Sdh155122 
11163bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (prop_val) {
11173bc21d0aSAruna Ramakrishna - Sun Microsystems 		/*
11183bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * The prop_val contains zone_name{:linkname}. The linkname is
11193bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * present only when the link is a ppa-hacked vlan.
11203bc21d0aSAruna Ramakrishna - Sun Microsystems 		 */
11213bc21d0aSAruna Ramakrishna - Sun Microsystems 		cp = strchr(*prop_val, ':');
11223bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (cp) {
11233bc21d0aSAruna Ramakrishna - Sun Microsystems 			(void) strlcpy(linkname, cp + 1, MAXLINKNAMELEN);
11243bc21d0aSAruna Ramakrishna - Sun Microsystems 			*cp = '\0';
11253bc21d0aSAruna Ramakrishna - Sun Microsystems 			is_ppa_hack = B_TRUE;
11263bc21d0aSAruna Ramakrishna - Sun Microsystems 		} else {
11273bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = dladm_datalink_id2info(linkid, NULL, NULL,
11283bc21d0aSAruna Ramakrishna - Sun Microsystems 			    NULL, linkname, MAXLINKNAMELEN);
11293bc21d0aSAruna Ramakrishna - Sun Microsystems 			if (status != DLADM_STATUS_OK) {
11303bc21d0aSAruna Ramakrishna - Sun Microsystems 				goto done;
11313bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
11323bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
11333bc21d0aSAruna Ramakrishna - Sun Microsystems 		zone_name = *prop_val;
11343bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
11353bc21d0aSAruna Ramakrishna - Sun Microsystems 		zone_name = GLOBAL_ZONENAME;
11363bc21d0aSAruna Ramakrishna - Sun Microsystems 		if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL,
11373bc21d0aSAruna Ramakrishna - Sun Microsystems 		    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
11383bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
11393bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
11403bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11413bc21d0aSAruna Ramakrishna - Sun Microsystems 
11423bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (strlen(linkname) > MAXLINKNAMELEN) {
11433bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
11443bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
11453bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11463bc21d0aSAruna Ramakrishna - Sun Microsystems 
11473bc21d0aSAruna Ramakrishna - Sun Microsystems 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
11483bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
11493bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
11503bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
11513bc21d0aSAruna Ramakrishna - Sun Microsystems 
11523bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zoneid != GLOBAL_ZONEID) {
1153f4b3ec61Sdh155122 		ushort_t	flags;
1154f4b3ec61Sdh155122 
11553bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
1156f4b3ec61Sdh155122 		    sizeof (flags)) < 0) {
11573bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = dladm_errno2status(errno);
11583bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1159f4b3ec61Sdh155122 		}
1160f4b3ec61Sdh155122 
1161f4b3ec61Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
11623bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = DLADM_STATUS_BADVAL;
11633bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1164f4b3ec61Sdh155122 		}
1165f4b3ec61Sdh155122 	}
1166f4b3ec61Sdh155122 
11673bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
11683bc21d0aSAruna Ramakrishna - Sun Microsystems 
11693bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp->diz_zid = zoneid;
11703bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
11713bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp->diz_is_ppa_hack = is_ppa_hack;
11723bc21d0aSAruna Ramakrishna - Sun Microsystems 
11733bc21d0aSAruna Ramakrishna - Sun Microsystems 	vdp->vd_val = (uintptr_t)dzp;
1174f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
11753bc21d0aSAruna Ramakrishna - Sun Microsystems done:
11763bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dzp);
11773bc21d0aSAruna Ramakrishna - Sun Microsystems 	return (status);
1178f4b3ec61Sdh155122 }
1179f4b3ec61Sdh155122 
1180e7801d59Ssowmini /* ARGSUSED */
1181f4b3ec61Sdh155122 static dladm_status_t
1182e7801d59Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid,
11834045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1184d62bc4baSyz147064 {
11853bc21d0aSAruna Ramakrishna - Sun Microsystems 	struct		dlautopush dlap;
11863bc21d0aSAruna Ramakrishna - Sun Microsystems 	int		i, len;
11873bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status;
11883bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
1189d62bc4baSyz147064 
11903fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
1191*149b7eb2SSowmini Varadhan 		return (DLADM_STATUS_NOTDEFINED);
11924045d941Ssowmini 
1193d62bc4baSyz147064 	*val_cnt = 1;
11943bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
11953bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dip == NULL) {
1196d62bc4baSyz147064 		(*prop_val)[0] = '\0';
1197d62bc4baSyz147064 		goto done;
1198d62bc4baSyz147064 	}
11993bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
1200d62bc4baSyz147064 
12013bc21d0aSAruna Ramakrishna - Sun Microsystems 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
1202d62bc4baSyz147064 		if (i != 0) {
1203d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1204d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
1205d62bc4baSyz147064 			len += 1;
1206d62bc4baSyz147064 		}
1207d62bc4baSyz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
12083bc21d0aSAruna Ramakrishna - Sun Microsystems 		    "%s", dlap.dap_aplist[i]);
12093bc21d0aSAruna Ramakrishna - Sun Microsystems 		len += strlen(dlap.dap_aplist[i]);
12103bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (dlap.dap_anchor - 1 == i) {
1211d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1212d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
1213d62bc4baSyz147064 			    AP_ANCHOR);
1214d62bc4baSyz147064 			len += (strlen(AP_ANCHOR) + 1);
1215d62bc4baSyz147064 		}
1216d62bc4baSyz147064 	}
1217d62bc4baSyz147064 
12183bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
1219d62bc4baSyz147064 done:
1220d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1221d62bc4baSyz147064 }
1222d62bc4baSyz147064 
1223d62bc4baSyz147064 /*
1224d62bc4baSyz147064  * Add the specified module to the dlautopush structure; returns a
1225d62bc4baSyz147064  * DLADM_STATUS_* code.
1226d62bc4baSyz147064  */
1227d62bc4baSyz147064 dladm_status_t
1228d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
1229d62bc4baSyz147064 {
1230d62bc4baSyz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
1231d62bc4baSyz147064 		return (DLADM_STATUS_BADVAL);
1232d62bc4baSyz147064 
1233d62bc4baSyz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
1234d62bc4baSyz147064 		/*
1235d62bc4baSyz147064 		 * We don't allow multiple anchors, and the anchor must
1236d62bc4baSyz147064 		 * be after at least one module.
1237d62bc4baSyz147064 		 */
1238d62bc4baSyz147064 		if (dlap->dap_anchor != 0)
1239d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1240d62bc4baSyz147064 		if (dlap->dap_npush == 0)
1241d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1242d62bc4baSyz147064 
1243d62bc4baSyz147064 		dlap->dap_anchor = dlap->dap_npush;
1244d62bc4baSyz147064 		return (DLADM_STATUS_OK);
1245d62bc4baSyz147064 	}
1246d62bc4baSyz147064 	if (dlap->dap_npush > MAXAPUSH)
1247d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1248d62bc4baSyz147064 
1249d62bc4baSyz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
1250d62bc4baSyz147064 	    FMNAMESZ + 1);
1251d62bc4baSyz147064 
1252d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1253d62bc4baSyz147064 }
1254d62bc4baSyz147064 
1255d62bc4baSyz147064 /*
1256d62bc4baSyz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
1257d62bc4baSyz147064  * autopush modules. The former is used in dladm set-linkprop, and the
1258d62bc4baSyz147064  * latter is used in the autopush(1M) file.
1259d62bc4baSyz147064  */
1260d62bc4baSyz147064 /* ARGSUSED */
1261d62bc4baSyz147064 static dladm_status_t
1262e7801d59Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
12636b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1264d62bc4baSyz147064 {
1265d62bc4baSyz147064 	char			*module;
1266d62bc4baSyz147064 	struct dlautopush	*dlap;
1267d62bc4baSyz147064 	dladm_status_t		status;
1268d62bc4baSyz147064 	char			val[DLADM_PROP_VAL_MAX];
1269d62bc4baSyz147064 	char			delimiters[4];
1270d62bc4baSyz147064 
1271d62bc4baSyz147064 	if (val_cnt != 1)
1272d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1273d62bc4baSyz147064 
12743bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (prop_val != NULL) {
1275d62bc4baSyz147064 		dlap = malloc(sizeof (struct dlautopush));
1276d62bc4baSyz147064 		if (dlap == NULL)
1277d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
1278d62bc4baSyz147064 
1279d62bc4baSyz147064 		(void) memset(dlap, 0, sizeof (struct dlautopush));
1280d62bc4baSyz147064 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
1281d62bc4baSyz147064 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
1282d62bc4baSyz147064 		module = strtok(val, delimiters);
1283d62bc4baSyz147064 		while (module != NULL) {
1284d62bc4baSyz147064 			status = i_dladm_add_ap_module(module, dlap);
1285d62bc4baSyz147064 			if (status != DLADM_STATUS_OK)
1286d62bc4baSyz147064 				return (status);
1287d62bc4baSyz147064 			module = strtok(NULL, delimiters);
1288d62bc4baSyz147064 		}
1289d62bc4baSyz147064 
1290d62bc4baSyz147064 		vdp->vd_val = (uintptr_t)dlap;
12913bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
12923bc21d0aSAruna Ramakrishna - Sun Microsystems 		vdp->vd_val = 0;
12933bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1294d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1295d62bc4baSyz147064 }
1296d62bc4baSyz147064 
1297bcb5c89dSSowmini Varadhan #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
1298bcb5c89dSSowmini Varadhan 
1299e7801d59Ssowmini /* ARGSUSED */
1300d62bc4baSyz147064 static dladm_status_t
1301e7801d59Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid,
1302e7801d59Ssowmini     char **prop_val, uint_t *val_cnt, uint_t id)
1303d62bc4baSyz147064 {
1304d62bc4baSyz147064 	wl_rates_t	*wrp;
1305d62bc4baSyz147064 	uint_t		i;
1306d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1307d62bc4baSyz147064 
1308bcb5c89dSSowmini Varadhan 	wrp = malloc(WLDP_BUFSIZE);
1309bcb5c89dSSowmini Varadhan 	if (wrp == NULL)
1310bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
1311d62bc4baSyz147064 
1312bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_param(linkid, wrp, id, WLDP_BUFSIZE, B_FALSE);
1313d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1314d62bc4baSyz147064 		goto done;
1315d62bc4baSyz147064 
1316d62bc4baSyz147064 	if (wrp->wl_rates_num > *val_cnt) {
1317d62bc4baSyz147064 		status = DLADM_STATUS_TOOSMALL;
1318d62bc4baSyz147064 		goto done;
1319d62bc4baSyz147064 	}
1320d62bc4baSyz147064 
1321d62bc4baSyz147064 	if (wrp->wl_rates_rates[0] == 0) {
1322d62bc4baSyz147064 		prop_val[0][0] = '\0';
1323d62bc4baSyz147064 		*val_cnt = 1;
1324d62bc4baSyz147064 		goto done;
1325d62bc4baSyz147064 	}
1326d62bc4baSyz147064 
1327d62bc4baSyz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
1328d62bc4baSyz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
1329d62bc4baSyz147064 		    wrp->wl_rates_rates[i] % 2,
1330d62bc4baSyz147064 		    (float)wrp->wl_rates_rates[i] / 2);
1331d62bc4baSyz147064 	}
1332d62bc4baSyz147064 	*val_cnt = wrp->wl_rates_num;
1333d62bc4baSyz147064 
1334d62bc4baSyz147064 done:
1335bcb5c89dSSowmini Varadhan 	free(wrp);
1336d62bc4baSyz147064 	return (status);
1337d62bc4baSyz147064 }
1338d62bc4baSyz147064 
1339d62bc4baSyz147064 static dladm_status_t
1340e7801d59Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid,
13414045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1342d62bc4baSyz147064 {
13436b9e797cSsowmini 	if (media != DL_WIFI)
13443bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (i_dladm_speed_get(pd, linkid, prop_val,
13453bc21d0aSAruna Ramakrishna - Sun Microsystems 		    val_cnt, flags));
13466b9e797cSsowmini 
1347e7801d59Ssowmini 	return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
1348bcb5c89dSSowmini Varadhan 	    MAC_PROP_WL_DESIRED_RATES));
1349d62bc4baSyz147064 }
1350d62bc4baSyz147064 
13514045d941Ssowmini /* ARGSUSED */
1352d62bc4baSyz147064 static dladm_status_t
1353e7801d59Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid,
13544045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1355d62bc4baSyz147064 {
13566b9e797cSsowmini 	switch (media) {
13576b9e797cSsowmini 	case DL_ETHER:
13584045d941Ssowmini 		/*
13594045d941Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
13604045d941Ssowmini 		 * links can have a speed of 5.5 Gbps.
13614045d941Ssowmini 		 */
13624045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
13636b9e797cSsowmini 
13646b9e797cSsowmini 	case DL_WIFI:
1365e7801d59Ssowmini 		return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
1366bcb5c89dSSowmini Varadhan 		    MAC_PROP_WL_SUPPORTED_RATES));
13676b9e797cSsowmini 	default:
13686b9e797cSsowmini 		return (DLADM_STATUS_BADARG);
13696b9e797cSsowmini 	}
1370d62bc4baSyz147064 }
1371d62bc4baSyz147064 
1372d62bc4baSyz147064 static dladm_status_t
1373d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates)
1374f4b3ec61Sdh155122 {
1375f4b3ec61Sdh155122 	int		i;
1376d62bc4baSyz147064 	uint_t		len;
1377d62bc4baSyz147064 	wl_rates_t	*wrp;
1378d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1379d62bc4baSyz147064 
1380bcb5c89dSSowmini Varadhan 	wrp = malloc(WLDP_BUFSIZE);
1381bcb5c89dSSowmini Varadhan 	if (wrp == NULL)
1382d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1383d62bc4baSyz147064 
1384bcb5c89dSSowmini Varadhan 	bzero(wrp, WLDP_BUFSIZE);
1385d62bc4baSyz147064 	for (i = 0; i < rates->wr_cnt; i++)
1386d62bc4baSyz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
1387d62bc4baSyz147064 	wrp->wl_rates_num = rates->wr_cnt;
1388d62bc4baSyz147064 
1389d62bc4baSyz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
1390d62bc4baSyz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
1391bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_param(linkid, wrp, MAC_PROP_WL_DESIRED_RATES,
1392bcb5c89dSSowmini Varadhan 	    len, B_TRUE);
1393d62bc4baSyz147064 
1394bcb5c89dSSowmini Varadhan 	free(wrp);
1395d62bc4baSyz147064 	return (status);
1396d62bc4baSyz147064 }
1397d62bc4baSyz147064 
1398e7801d59Ssowmini /* ARGSUSED */
1399d62bc4baSyz147064 static dladm_status_t
1400e7801d59Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid,
14016b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1402d62bc4baSyz147064 {
1403d62bc4baSyz147064 	dladm_wlan_rates_t	rates;
1404f4b3ec61Sdh155122 	dladm_status_t		status;
1405f4b3ec61Sdh155122 
14066b9e797cSsowmini 	/*
14076b9e797cSsowmini 	 * can currently set rate on WIFI links only.
14086b9e797cSsowmini 	 */
14096b9e797cSsowmini 	if (media != DL_WIFI)
14106b9e797cSsowmini 		return (DLADM_STATUS_PROPRDONLY);
14116b9e797cSsowmini 
1412d62bc4baSyz147064 	if (val_cnt != 1)
1413d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1414f4b3ec61Sdh155122 
1415d62bc4baSyz147064 	rates.wr_cnt = 1;
1416d62bc4baSyz147064 	rates.wr_rates[0] = vdp[0].vd_val;
1417f4b3ec61Sdh155122 
1418d62bc4baSyz147064 	status = do_set_rate(linkid, &rates);
1419f4b3ec61Sdh155122 
1420d62bc4baSyz147064 done:
1421d62bc4baSyz147064 	return (status);
1422d62bc4baSyz147064 }
1423d62bc4baSyz147064 
1424d62bc4baSyz147064 /* ARGSUSED */
1425d62bc4baSyz147064 static dladm_status_t
1426e7801d59Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
14276b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1428d62bc4baSyz147064 {
1429d62bc4baSyz147064 	int		i;
1430d62bc4baSyz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
1431d62bc4baSyz147064 	char		*buf, **modval;
1432d62bc4baSyz147064 	dladm_status_t	status;
1433d62bc4baSyz147064 
1434d62bc4baSyz147064 	if (val_cnt != 1)
1435d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1436d62bc4baSyz147064 
1437d62bc4baSyz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
1438d62bc4baSyz147064 	    MAX_SUPPORT_RATES);
1439d62bc4baSyz147064 	if (buf == NULL) {
1440d62bc4baSyz147064 		status = DLADM_STATUS_NOMEM;
1441d62bc4baSyz147064 		goto done;
1442d62bc4baSyz147064 	}
1443d62bc4baSyz147064 
1444d62bc4baSyz147064 	modval = (char **)(void *)buf;
1445d62bc4baSyz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
1446d62bc4baSyz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
1447d62bc4baSyz147064 		    i * DLADM_STRSIZE;
1448d62bc4baSyz147064 	}
1449d62bc4baSyz147064 
14504045d941Ssowmini 	status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media, 0);
1451d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1452d62bc4baSyz147064 		goto done;
1453d62bc4baSyz147064 
1454d62bc4baSyz147064 	for (i = 0; i < modval_cnt; i++) {
1455d62bc4baSyz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
1456e7801d59Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
1457e7801d59Ssowmini 			    (atof(*prop_val) * 2);
1458f4b3ec61Sdh155122 			status = DLADM_STATUS_OK;
1459f4b3ec61Sdh155122 			break;
1460f4b3ec61Sdh155122 		}
1461d62bc4baSyz147064 	}
1462d62bc4baSyz147064 	if (i == modval_cnt)
1463d62bc4baSyz147064 		status = DLADM_STATUS_BADVAL;
1464d62bc4baSyz147064 done:
1465d62bc4baSyz147064 	free(buf);
1466d62bc4baSyz147064 	return (status);
1467d62bc4baSyz147064 }
1468f4b3ec61Sdh155122 
1469d62bc4baSyz147064 static dladm_status_t
1470bcb5c89dSSowmini Varadhan do_get_phyconf(datalink_id_t linkid, void *buf, int buflen)
1471d62bc4baSyz147064 {
1472bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_PHY_CONFIG,
1473bcb5c89dSSowmini Varadhan 	    buflen, B_FALSE));
1474d62bc4baSyz147064 }
1475d62bc4baSyz147064 
1476e7801d59Ssowmini /* ARGSUSED */
1477d62bc4baSyz147064 static dladm_status_t
1478e7801d59Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid,
14794045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1480d62bc4baSyz147064 {
1481d62bc4baSyz147064 	uint32_t	channel;
1482bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1483d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1484bcb5c89dSSowmini Varadhan 	wl_phy_conf_t	wl_phy_conf;
1485d62bc4baSyz147064 
1486bcb5c89dSSowmini Varadhan 	if ((status = do_get_phyconf(linkid, buf, sizeof (buf)))
1487bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1488d62bc4baSyz147064 		goto done;
1489d62bc4baSyz147064 
1490bcb5c89dSSowmini Varadhan 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
1491bcb5c89dSSowmini Varadhan 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
1492d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1493d62bc4baSyz147064 		goto done;
1494d62bc4baSyz147064 	}
1495d62bc4baSyz147064 
1496d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
1497d62bc4baSyz147064 	*val_cnt = 1;
1498d62bc4baSyz147064 
1499d62bc4baSyz147064 done:
1500d62bc4baSyz147064 	return (status);
1501d62bc4baSyz147064 }
1502d62bc4baSyz147064 
1503d62bc4baSyz147064 static dladm_status_t
1504bcb5c89dSSowmini Varadhan do_get_powermode(datalink_id_t linkid, void *buf, int buflen)
1505d62bc4baSyz147064 {
1506bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_POWER_MODE,
1507bcb5c89dSSowmini Varadhan 	    buflen, B_FALSE));
1508d62bc4baSyz147064 }
1509d62bc4baSyz147064 
1510e7801d59Ssowmini /* ARGSUSED */
1511d62bc4baSyz147064 static dladm_status_t
1512e7801d59Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid,
15134045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1514d62bc4baSyz147064 {
1515bcb5c89dSSowmini Varadhan 	wl_ps_mode_t	mode;
1516d62bc4baSyz147064 	const char	*s;
1517bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1518d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1519d62bc4baSyz147064 
1520bcb5c89dSSowmini Varadhan 	if ((status = do_get_powermode(linkid, buf, sizeof (buf)))
1521bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1522d62bc4baSyz147064 		goto done;
1523d62bc4baSyz147064 
1524bcb5c89dSSowmini Varadhan 	(void) memcpy(&mode, buf, sizeof (mode));
1525bcb5c89dSSowmini Varadhan 	switch (mode.wl_ps_mode) {
1526d62bc4baSyz147064 	case WL_PM_AM:
1527d62bc4baSyz147064 		s = "off";
1528f4b3ec61Sdh155122 		break;
1529d62bc4baSyz147064 	case WL_PM_MPS:
1530d62bc4baSyz147064 		s = "max";
1531d62bc4baSyz147064 		break;
1532d62bc4baSyz147064 	case WL_PM_FAST:
1533d62bc4baSyz147064 		s = "fast";
1534f4b3ec61Sdh155122 		break;
1535f4b3ec61Sdh155122 	default:
1536d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1537d62bc4baSyz147064 		goto done;
1538f4b3ec61Sdh155122 	}
1539d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
1540d62bc4baSyz147064 	*val_cnt = 1;
1541d62bc4baSyz147064 
1542d62bc4baSyz147064 done:
1543d62bc4baSyz147064 	return (status);
1544d62bc4baSyz147064 }
1545d62bc4baSyz147064 
1546d62bc4baSyz147064 static dladm_status_t
1547d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm)
1548d62bc4baSyz147064 {
1549d62bc4baSyz147064 	wl_ps_mode_t    ps_mode;
1550d62bc4baSyz147064 
1551d62bc4baSyz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
1552d62bc4baSyz147064 
1553d62bc4baSyz147064 	switch (*pm) {
1554d62bc4baSyz147064 	case DLADM_WLAN_PM_OFF:
1555d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
1556d62bc4baSyz147064 		break;
1557d62bc4baSyz147064 	case DLADM_WLAN_PM_MAX:
1558d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
1559d62bc4baSyz147064 		break;
1560d62bc4baSyz147064 	case DLADM_WLAN_PM_FAST:
1561d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
1562d62bc4baSyz147064 		break;
1563d62bc4baSyz147064 	default:
1564d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
1565d62bc4baSyz147064 	}
1566bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, &ps_mode, MAC_PROP_WL_POWER_MODE,
1567bcb5c89dSSowmini Varadhan 	    sizeof (ps_mode), B_TRUE));
1568d62bc4baSyz147064 }
1569d62bc4baSyz147064 
1570d62bc4baSyz147064 /* ARGSUSED */
1571d62bc4baSyz147064 static dladm_status_t
1572e7801d59Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid,
15736b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1574d62bc4baSyz147064 {
1575d62bc4baSyz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
1576d62bc4baSyz147064 	dladm_status_t status;
1577d62bc4baSyz147064 
1578d62bc4baSyz147064 	if (val_cnt != 1)
1579d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1580d62bc4baSyz147064 
1581d62bc4baSyz147064 	status = do_set_powermode(linkid, &powermode);
1582f4b3ec61Sdh155122 
1583f4b3ec61Sdh155122 	return (status);
1584f4b3ec61Sdh155122 }
1585f4b3ec61Sdh155122 
1586f4b3ec61Sdh155122 static dladm_status_t
1587bcb5c89dSSowmini Varadhan do_get_radio(datalink_id_t linkid, void *buf, int buflen)
1588f4b3ec61Sdh155122 {
1589bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_RADIO, buflen,
1590bcb5c89dSSowmini Varadhan 	    B_FALSE));
1591d62bc4baSyz147064 }
1592d62bc4baSyz147064 
1593e7801d59Ssowmini /* ARGSUSED */
1594d62bc4baSyz147064 static dladm_status_t
1595e7801d59Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid,
15964045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1597d62bc4baSyz147064 {
1598d62bc4baSyz147064 	wl_radio_t	radio;
1599d62bc4baSyz147064 	const char	*s;
1600bcb5c89dSSowmini Varadhan 	char		buf[WLDP_BUFSIZE];
1601d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1602d62bc4baSyz147064 
1603bcb5c89dSSowmini Varadhan 	if ((status = do_get_radio(linkid, buf, sizeof (buf)))
1604bcb5c89dSSowmini Varadhan 	    != DLADM_STATUS_OK)
1605d62bc4baSyz147064 		goto done;
1606d62bc4baSyz147064 
1607bcb5c89dSSowmini Varadhan 	(void) memcpy(&radio, buf, sizeof (radio));
1608d62bc4baSyz147064 	switch (radio) {
1609d62bc4baSyz147064 	case B_TRUE:
1610d62bc4baSyz147064 		s = "on";
1611d62bc4baSyz147064 		break;
1612d62bc4baSyz147064 	case B_FALSE:
1613d62bc4baSyz147064 		s = "off";
1614d62bc4baSyz147064 		break;
1615d62bc4baSyz147064 	default:
1616d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1617d62bc4baSyz147064 		goto done;
1618d62bc4baSyz147064 	}
1619d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
1620d62bc4baSyz147064 	*val_cnt = 1;
1621d62bc4baSyz147064 
1622d62bc4baSyz147064 done:
1623d62bc4baSyz147064 	return (status);
1624d62bc4baSyz147064 }
1625d62bc4baSyz147064 
1626d62bc4baSyz147064 static dladm_status_t
1627d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio)
1628d62bc4baSyz147064 {
1629d62bc4baSyz147064 	wl_radio_t r;
1630d62bc4baSyz147064 
1631d62bc4baSyz147064 	switch (*radio) {
1632d62bc4baSyz147064 	case DLADM_WLAN_RADIO_ON:
1633d62bc4baSyz147064 		r = B_TRUE;
1634d62bc4baSyz147064 		break;
1635d62bc4baSyz147064 	case DLADM_WLAN_RADIO_OFF:
1636d62bc4baSyz147064 		r = B_FALSE;
1637d62bc4baSyz147064 		break;
1638d62bc4baSyz147064 	default:
1639d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
1640d62bc4baSyz147064 	}
1641bcb5c89dSSowmini Varadhan 	return (i_dladm_wlan_param(linkid, &r, MAC_PROP_WL_RADIO,
1642bcb5c89dSSowmini Varadhan 	    sizeof (r), B_TRUE));
1643d62bc4baSyz147064 }
1644d62bc4baSyz147064 
1645d62bc4baSyz147064 /* ARGSUSED */
1646d62bc4baSyz147064 static dladm_status_t
1647e7801d59Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid,
16486b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
1649d62bc4baSyz147064 {
1650d62bc4baSyz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
1651f4b3ec61Sdh155122 	dladm_status_t status;
1652f4b3ec61Sdh155122 
1653d62bc4baSyz147064 	if (val_cnt != 1)
1654d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1655f4b3ec61Sdh155122 
1656d62bc4baSyz147064 	status = do_set_radio(linkid, &radio);
1657f4b3ec61Sdh155122 
1658d62bc4baSyz147064 	return (status);
1659d62bc4baSyz147064 }
1660f4b3ec61Sdh155122 
1661d62bc4baSyz147064 static dladm_status_t
1662d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name,
1663d62bc4baSyz147064     char **prop_val, uint_t val_cnt)
1664d62bc4baSyz147064 {
1665d62bc4baSyz147064 	char		buf[MAXLINELEN];
1666d62bc4baSyz147064 	int		i;
1667d62bc4baSyz147064 	dladm_conf_t	conf;
1668d62bc4baSyz147064 	dladm_status_t	status;
1669d62bc4baSyz147064 
1670d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
1671f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
1672f4b3ec61Sdh155122 		return (status);
1673f4b3ec61Sdh155122 
1674d62bc4baSyz147064 	/*
1675d62bc4baSyz147064 	 * reset case.
1676d62bc4baSyz147064 	 */
1677d62bc4baSyz147064 	if (val_cnt == 0) {
1678d62bc4baSyz147064 		status = dladm_unset_conf_field(conf, prop_name);
1679d62bc4baSyz147064 		if (status == DLADM_STATUS_OK)
1680d62bc4baSyz147064 			status = dladm_write_conf(conf);
1681d62bc4baSyz147064 		goto done;
1682f4b3ec61Sdh155122 	}
1683f4b3ec61Sdh155122 
1684d62bc4baSyz147064 	buf[0] = '\0';
1685d62bc4baSyz147064 	for (i = 0; i < val_cnt; i++) {
1686d62bc4baSyz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
1687d62bc4baSyz147064 		if (i != val_cnt - 1)
1688d62bc4baSyz147064 			(void) strlcat(buf, ",", MAXLINELEN);
1689d62bc4baSyz147064 	}
1690f4b3ec61Sdh155122 
1691d62bc4baSyz147064 	status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf);
1692d62bc4baSyz147064 	if (status == DLADM_STATUS_OK)
1693d62bc4baSyz147064 		status = dladm_write_conf(conf);
1694d62bc4baSyz147064 
1695d62bc4baSyz147064 done:
1696d62bc4baSyz147064 	dladm_destroy_conf(conf);
1697f4b3ec61Sdh155122 	return (status);
1698f4b3ec61Sdh155122 }
1699f4b3ec61Sdh155122 
1700f4b3ec61Sdh155122 static dladm_status_t
1701d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name,
1702d62bc4baSyz147064     char **prop_val, uint_t *val_cntp)
1703f4b3ec61Sdh155122 {
1704d62bc4baSyz147064 	char		buf[MAXLINELEN], *str;
1705d62bc4baSyz147064 	uint_t		cnt = 0;
1706d62bc4baSyz147064 	dladm_conf_t	conf;
1707d62bc4baSyz147064 	dladm_status_t	status;
1708f4b3ec61Sdh155122 
1709d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
1710d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1711f4b3ec61Sdh155122 		return (status);
1712d62bc4baSyz147064 
1713d62bc4baSyz147064 	status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN);
1714d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1715d62bc4baSyz147064 		goto done;
1716d62bc4baSyz147064 
1717d62bc4baSyz147064 	str = strtok(buf, ",");
1718d62bc4baSyz147064 	while (str != NULL) {
1719d62bc4baSyz147064 		if (cnt == *val_cntp) {
1720d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
1721d62bc4baSyz147064 			goto done;
1722d62bc4baSyz147064 		}
1723d62bc4baSyz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
1724d62bc4baSyz147064 		str = strtok(NULL, ",");
1725f4b3ec61Sdh155122 	}
1726f4b3ec61Sdh155122 
1727d62bc4baSyz147064 	*val_cntp = cnt;
1728f4b3ec61Sdh155122 
1729d62bc4baSyz147064 done:
1730d62bc4baSyz147064 	dladm_destroy_conf(conf);
1731d62bc4baSyz147064 	return (status);
1732f4b3ec61Sdh155122 }
1733e7801d59Ssowmini 
1734bcb5c89dSSowmini Varadhan static link_attr_t *
1735e7801d59Ssowmini dladm_name2prop(const char *prop_name)
1736e7801d59Ssowmini {
1737bcb5c89dSSowmini Varadhan 	link_attr_t *p;
1738e7801d59Ssowmini 
1739bcb5c89dSSowmini Varadhan 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
1740e7801d59Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
1741e7801d59Ssowmini 			break;
1742e7801d59Ssowmini 	}
1743e7801d59Ssowmini 	return (p);
1744e7801d59Ssowmini }
1745e7801d59Ssowmini 
1746bcb5c89dSSowmini Varadhan static link_attr_t *
1747bcb5c89dSSowmini Varadhan dladm_id2prop(mac_prop_id_t propid)
1748bcb5c89dSSowmini Varadhan {
1749bcb5c89dSSowmini Varadhan 	link_attr_t *p;
1750bcb5c89dSSowmini Varadhan 
1751bcb5c89dSSowmini Varadhan 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
1752bcb5c89dSSowmini Varadhan 		if (p->pp_id == propid)
1753bcb5c89dSSowmini Varadhan 			break;
1754bcb5c89dSSowmini Varadhan 	}
1755bcb5c89dSSowmini Varadhan 	return (p);
1756bcb5c89dSSowmini Varadhan }
1757e7801d59Ssowmini 
17583fd94f8cSam223141 static dld_ioc_macprop_t *
1759bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
1760bcb5c89dSSowmini Varadhan     const char *prop_name, mac_prop_id_t propid, uint_t flags,
1761bcb5c89dSSowmini Varadhan     dladm_status_t *status)
1762e7801d59Ssowmini {
1763e7801d59Ssowmini 	int dsize;
17643fd94f8cSam223141 	dld_ioc_macprop_t *dip;
1765e7801d59Ssowmini 
1766e7801d59Ssowmini 	*status = DLADM_STATUS_OK;
17673fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
1768e7801d59Ssowmini 	dip = malloc(dsize);
1769e7801d59Ssowmini 	if (dip == NULL) {
1770e7801d59Ssowmini 		*status = DLADM_STATUS_NOMEM;
1771e7801d59Ssowmini 		return (NULL);
1772e7801d59Ssowmini 	}
1773e7801d59Ssowmini 	bzero(dip, dsize);
1774e7801d59Ssowmini 	dip->pr_valsize = valsize;
17754045d941Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
17763fd94f8cSam223141 	dip->pr_version = MAC_PROP_VERSION;
17776b9e797cSsowmini 	dip->pr_linkid = linkid;
1778bcb5c89dSSowmini Varadhan 	dip->pr_num = propid;
17794045d941Ssowmini 	dip->pr_flags = flags;
1780e7801d59Ssowmini 	return (dip);
1781e7801d59Ssowmini }
1782e7801d59Ssowmini 
1783bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *
1784bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
1785bcb5c89dSSowmini Varadhan     const char *prop_name, uint_t flags, dladm_status_t *status)
1786bcb5c89dSSowmini Varadhan {
1787bcb5c89dSSowmini Varadhan 	link_attr_t *p;
1788bcb5c89dSSowmini Varadhan 
1789bcb5c89dSSowmini Varadhan 	p = dladm_name2prop(prop_name);
1790bcb5c89dSSowmini Varadhan 	valsize = MAX(p->pp_valsize, valsize);
1791bcb5c89dSSowmini Varadhan 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
1792bcb5c89dSSowmini Varadhan 	    flags, status));
1793bcb5c89dSSowmini Varadhan }
1794bcb5c89dSSowmini Varadhan 
1795bcb5c89dSSowmini Varadhan static dld_ioc_macprop_t *
1796bcb5c89dSSowmini Varadhan i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
1797bcb5c89dSSowmini Varadhan     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
1798bcb5c89dSSowmini Varadhan {
1799bcb5c89dSSowmini Varadhan 	link_attr_t *p;
1800bcb5c89dSSowmini Varadhan 
1801bcb5c89dSSowmini Varadhan 	p = dladm_id2prop(propid);
1802bcb5c89dSSowmini Varadhan 	valsize = MAX(p->pp_valsize, valsize);
1803bcb5c89dSSowmini Varadhan 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
1804bcb5c89dSSowmini Varadhan 	    flags, status));
1805bcb5c89dSSowmini Varadhan }
1806bcb5c89dSSowmini Varadhan 
1807e7801d59Ssowmini /* ARGSUSED */
1808e7801d59Ssowmini static dladm_status_t
18093bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_set_public_prop(prop_desc_t *pd, datalink_id_t linkid,
18106b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1811e7801d59Ssowmini {
18123fd94f8cSam223141 	dld_ioc_macprop_t	*dip;
1813e7801d59Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
1814e7801d59Ssowmini 	uint8_t		u8;
1815e7801d59Ssowmini 	uint16_t	u16;
1816e7801d59Ssowmini 	uint32_t	u32;
1817e7801d59Ssowmini 	void		*val;
1818e7801d59Ssowmini 
1819bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(0, linkid, pd->pd_name, 0, &status);
1820e7801d59Ssowmini 	if (dip == NULL)
1821e7801d59Ssowmini 		return (status);
1822e7801d59Ssowmini 
1823e7801d59Ssowmini 	if (pd->pd_flags & PD_CHECK_ALLOC)
1824e7801d59Ssowmini 		val = (void *)vdp->vd_val;
1825e7801d59Ssowmini 	else {
1826e7801d59Ssowmini 		/*
1827e7801d59Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
1828e7801d59Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
1829e7801d59Ssowmini 		 */
1830e7801d59Ssowmini 		switch (dip->pr_valsize) {
1831e7801d59Ssowmini 		case 1:
1832e7801d59Ssowmini 			u8 = vdp->vd_val;
1833e7801d59Ssowmini 			val = &u8;
1834e7801d59Ssowmini 			break;
1835e7801d59Ssowmini 		case 2:
1836e7801d59Ssowmini 			u16 = vdp->vd_val;
1837e7801d59Ssowmini 			val = &u16;
1838e7801d59Ssowmini 			break;
1839e7801d59Ssowmini 		case 4:
1840e7801d59Ssowmini 			u32 = vdp->vd_val;
1841e7801d59Ssowmini 			val = &u32;
1842e7801d59Ssowmini 			break;
1843e7801d59Ssowmini 		default:
1844e7801d59Ssowmini 			val = &vdp->vd_val;
1845e7801d59Ssowmini 			break;
1846e7801d59Ssowmini 		}
1847e7801d59Ssowmini 	}
1848e7801d59Ssowmini 
18493bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (val != NULL)
1850e7801d59Ssowmini 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
18513bc21d0aSAruna Ramakrishna - Sun Microsystems 	else
18523bc21d0aSAruna Ramakrishna - Sun Microsystems 		dip->pr_valsize = 0;
18533bc21d0aSAruna Ramakrishna - Sun Microsystems 
1854bcb5c89dSSowmini Varadhan 	status = i_dladm_macprop(dip, B_TRUE);
1855bcb5c89dSSowmini Varadhan 
1856bcb5c89dSSowmini Varadhan done:
1857bcb5c89dSSowmini Varadhan 	free(dip);
1858bcb5c89dSSowmini Varadhan 	return (status);
1859bcb5c89dSSowmini Varadhan }
1860bcb5c89dSSowmini Varadhan 
1861bcb5c89dSSowmini Varadhan dladm_status_t
1862bcb5c89dSSowmini Varadhan i_dladm_macprop(void *dip, boolean_t set)
1863bcb5c89dSSowmini Varadhan {
1864bcb5c89dSSowmini Varadhan 	int fd;
1865bcb5c89dSSowmini Varadhan 	dladm_status_t status = DLADM_STATUS_OK;
1866bcb5c89dSSowmini Varadhan 
1867e7801d59Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
1868e7801d59Ssowmini 		status = dladm_errno2status(errno);
1869bcb5c89dSSowmini Varadhan 		return (status);
1870e7801d59Ssowmini 	}
1871bcb5c89dSSowmini Varadhan 	if (ioctl(fd, (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
1872e7801d59Ssowmini 		status = dladm_errno2status(errno);
1873e7801d59Ssowmini 
1874e7801d59Ssowmini 	(void) close(fd);
1875e7801d59Ssowmini 	return (status);
1876e7801d59Ssowmini }
1877e7801d59Ssowmini 
18783fd94f8cSam223141 static dld_ioc_macprop_t *
18793bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags,
18804045d941Ssowmini     dladm_status_t *status)
1881e7801d59Ssowmini {
18823fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
18834045d941Ssowmini 
1884bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
18854045d941Ssowmini 	if (dip == NULL)
18864045d941Ssowmini 		return (NULL);
1887e7801d59Ssowmini 
1888bcb5c89dSSowmini Varadhan 	*status = i_dladm_macprop(dip, B_FALSE);
18894045d941Ssowmini 	if (*status != DLADM_STATUS_OK) {
18904045d941Ssowmini 		free(dip);
18914045d941Ssowmini 		return (NULL);
18924045d941Ssowmini 	}
18934045d941Ssowmini 	return (dip);
1894e7801d59Ssowmini }
1895e7801d59Ssowmini 
1896e7801d59Ssowmini /* ARGSUSED */
1897e7801d59Ssowmini static dladm_status_t
18983bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_defmtu_check(struct prop_desc *pd, datalink_id_t linkid,
18993bc21d0aSAruna Ramakrishna - Sun Microsystems     char **prop_val, uint_t val_cnt, val_desc_t *v, datalink_media_t media)
1900e7801d59Ssowmini {
1901e7801d59Ssowmini 	if (val_cnt != 1)
1902e7801d59Ssowmini 		return (DLADM_STATUS_BADVAL);
19034045d941Ssowmini 	v->vd_val = atoi(prop_val[0]);
1904e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1905e7801d59Ssowmini }
1906e7801d59Ssowmini 
1907e7801d59Ssowmini /* ARGSUSED */
1908e7801d59Ssowmini static dladm_status_t
19093bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_duplex_get(struct prop_desc *pd, datalink_id_t linkid,
19104045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1911e7801d59Ssowmini {
1912e7801d59Ssowmini 	link_duplex_t   link_duplex;
1913e7801d59Ssowmini 	dladm_status_t  status;
1914e7801d59Ssowmini 
1915e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "link_duplex",
1916e7801d59Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
1917e7801d59Ssowmini 		return (status);
1918e7801d59Ssowmini 
1919e7801d59Ssowmini 	switch (link_duplex) {
1920e7801d59Ssowmini 	case LINK_DUPLEX_FULL:
1921e7801d59Ssowmini 		(void) strcpy(*prop_val, "full");
1922e7801d59Ssowmini 		break;
1923e7801d59Ssowmini 	case LINK_DUPLEX_HALF:
1924e7801d59Ssowmini 		(void) strcpy(*prop_val, "half");
1925e7801d59Ssowmini 		break;
1926e7801d59Ssowmini 	default:
1927e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
1928e7801d59Ssowmini 		break;
1929e7801d59Ssowmini 	}
1930e7801d59Ssowmini 	*val_cnt = 1;
1931e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1932e7801d59Ssowmini }
1933e7801d59Ssowmini 
1934e7801d59Ssowmini /* ARGSUSED */
1935e7801d59Ssowmini static dladm_status_t
19363bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_speed_get(struct prop_desc *pd, datalink_id_t linkid,
19374045d941Ssowmini     char **prop_val, uint_t *val_cnt, uint_t flags)
1938e7801d59Ssowmini {
1939e7801d59Ssowmini 	uint64_t	ifspeed = 0;
1940e7801d59Ssowmini 	dladm_status_t status;
1941e7801d59Ssowmini 
1942e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "ifspeed",
1943e7801d59Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
1944e7801d59Ssowmini 		return (status);
19454045d941Ssowmini 
19466b9e797cSsowmini 	if ((ifspeed % 1000000) != 0) {
19476b9e797cSsowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
19486b9e797cSsowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
19496b9e797cSsowmini 	} else {
1950e7801d59Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
1951e7801d59Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
19526b9e797cSsowmini 	}
1953e7801d59Ssowmini 	*val_cnt = 1;
1954e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1955e7801d59Ssowmini }
1956e7801d59Ssowmini 
1957e7801d59Ssowmini /* ARGSUSED */
1958e7801d59Ssowmini static dladm_status_t
19593bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_status_get(struct prop_desc *pd, datalink_id_t linkid,
19604045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1961e7801d59Ssowmini {
1962e7801d59Ssowmini 	link_state_t	link_state;
1963e7801d59Ssowmini 	dladm_status_t	status;
19644045d941Ssowmini 	uchar_t 	*cp;
19653fd94f8cSam223141 	dld_ioc_macprop_t  *dip;
1966e7801d59Ssowmini 
19673bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19684045d941Ssowmini 	if (status != DLADM_STATUS_OK)
1969e7801d59Ssowmini 		return (status);
19704045d941Ssowmini 	cp = (uchar_t *)dip->pr_val;
19714045d941Ssowmini 	(void) memcpy(&link_state, cp, sizeof (link_state));
1972e7801d59Ssowmini 
1973e7801d59Ssowmini 	switch (link_state) {
1974e7801d59Ssowmini 	case LINK_STATE_UP:
1975e7801d59Ssowmini 		(void) strcpy(*prop_val, "up");
1976e7801d59Ssowmini 		break;
1977e7801d59Ssowmini 	case LINK_STATE_DOWN:
1978e7801d59Ssowmini 		(void) strcpy(*prop_val, "down");
1979e7801d59Ssowmini 		break;
1980e7801d59Ssowmini 	default:
1981e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
1982e7801d59Ssowmini 		break;
1983e7801d59Ssowmini 	}
1984e7801d59Ssowmini 	*val_cnt = 1;
19854045d941Ssowmini 	free(dip);
1986e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1987e7801d59Ssowmini }
1988e7801d59Ssowmini 
1989e7801d59Ssowmini /* ARGSUSED */
1990e7801d59Ssowmini static dladm_status_t
19913bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_binary_get(struct prop_desc *pd, datalink_id_t linkid,
19924045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1993e7801d59Ssowmini {
19943fd94f8cSam223141 	dld_ioc_macprop_t *dip;
1995e7801d59Ssowmini 	dladm_status_t status;
1996e7801d59Ssowmini 
19973bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19984045d941Ssowmini 	if (dip == NULL)
1999e7801d59Ssowmini 		return (status);
2000e7801d59Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
2001e7801d59Ssowmini 	free(dip);
2002e7801d59Ssowmini 	*val_cnt = 1;
2003e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2004e7801d59Ssowmini }
2005e7801d59Ssowmini 
20066b9e797cSsowmini /* ARGSUSED */
2007e7801d59Ssowmini static dladm_status_t
20083bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_uint32_get(struct prop_desc *pd, datalink_id_t linkid,
20094045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
2010e7801d59Ssowmini {
20113fd94f8cSam223141 	dld_ioc_macprop_t *dip;
20124045d941Ssowmini 	uint32_t v  = 0;
2013e7801d59Ssowmini 	uchar_t *cp;
2014e7801d59Ssowmini 	dladm_status_t status;
2015e7801d59Ssowmini 
20163bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
20174045d941Ssowmini 	if (dip == NULL)
2018e7801d59Ssowmini 		return (status);
2019e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
2020e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
20214045d941Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
2022e7801d59Ssowmini 	free(dip);
2023e7801d59Ssowmini 	*val_cnt = 1;
2024e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2025e7801d59Ssowmini }
2026e7801d59Ssowmini 
20276b9e797cSsowmini /* ARGSUSED */
2028e7801d59Ssowmini static dladm_status_t
20293bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_flowctl_get(struct prop_desc *pd, datalink_id_t linkid,
20304045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
2031e7801d59Ssowmini {
20323fd94f8cSam223141 	dld_ioc_macprop_t *dip;
2033e7801d59Ssowmini 	link_flowctrl_t v;
2034e7801d59Ssowmini 	dladm_status_t status;
2035e7801d59Ssowmini 	uchar_t *cp;
2036e7801d59Ssowmini 
20373bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
20384045d941Ssowmini 	if (dip == NULL)
2039e7801d59Ssowmini 		return (status);
2040e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
2041e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
2042e7801d59Ssowmini 	switch (v) {
2043e7801d59Ssowmini 	case LINK_FLOWCTRL_NONE:
2044e7801d59Ssowmini 		(void) sprintf(*prop_val, "no");
2045e7801d59Ssowmini 		break;
2046e7801d59Ssowmini 	case LINK_FLOWCTRL_RX:
2047e7801d59Ssowmini 		(void) sprintf(*prop_val, "rx");
2048e7801d59Ssowmini 		break;
2049e7801d59Ssowmini 	case LINK_FLOWCTRL_TX:
2050e7801d59Ssowmini 		(void) sprintf(*prop_val, "tx");
2051e7801d59Ssowmini 		break;
2052e7801d59Ssowmini 	case LINK_FLOWCTRL_BI:
2053e7801d59Ssowmini 		(void) sprintf(*prop_val, "bi");
2054e7801d59Ssowmini 		break;
2055e7801d59Ssowmini 	}
2056e7801d59Ssowmini 	free(dip);
2057e7801d59Ssowmini 	*val_cnt = 1;
2058e7801d59Ssowmini 	return (DLADM_STATUS_OK);
2059e7801d59Ssowmini }
2060e7801d59Ssowmini 
2061e7801d59Ssowmini 
2062e7801d59Ssowmini /* ARGSUSED */
2063e7801d59Ssowmini static dladm_status_t
20643bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_set_prop(datalink_id_t linkid, const char *prop_name,
2065e7801d59Ssowmini     char **prop_val, uint_t val_cnt, uint_t flags)
2066e7801d59Ssowmini {
2067bcb5c89dSSowmini Varadhan 	int		i, slen;
2068eae72b5bSSebastien Roy 	int 		bufsize = 0;
20693fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2070e7801d59Ssowmini 	uchar_t 	*dp;
2071bcb5c89dSSowmini Varadhan 	link_attr_t *p;
20724045d941Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
2073e7801d59Ssowmini 
2074e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2075e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2076e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2077e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
20783fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2079e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2080e7801d59Ssowmini 
2081e7801d59Ssowmini 	/*
2082e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2083e7801d59Ssowmini 	 * allocate a enough space for each property + its separator (',').
2084e7801d59Ssowmini 	 */
2085e7801d59Ssowmini 	for (i = 0; i < val_cnt; i++) {
2086e7801d59Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
2087e7801d59Ssowmini 	}
20884045d941Ssowmini 
20894045d941Ssowmini 	if (prop_val == NULL) {
20904045d941Ssowmini 		/*
20914045d941Ssowmini 		 * getting default value. so use more buffer space.
20924045d941Ssowmini 		 */
2093bcb5c89dSSowmini Varadhan 		bufsize += DLADM_PROP_BUF_CHUNK;
20944045d941Ssowmini 	}
20954045d941Ssowmini 
2096bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
20973fd94f8cSam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
2098e7801d59Ssowmini 	if (dip == NULL)
2099e7801d59Ssowmini 		return (status);
2100e7801d59Ssowmini 
2101e7801d59Ssowmini 	dp = (uchar_t *)dip->pr_val;
2102e7801d59Ssowmini 	slen = 0;
2103bcb5c89dSSowmini Varadhan 
21044045d941Ssowmini 	if (prop_val == NULL) {
2105bcb5c89dSSowmini Varadhan 		status = i_dladm_macprop(dip, B_FALSE);
21064045d941Ssowmini 	} else {
2107e7801d59Ssowmini 		for (i = 0; i < val_cnt; i++) {
2108e7801d59Ssowmini 			int plen = 0;
2109e7801d59Ssowmini 
2110e7801d59Ssowmini 			plen = strlen(prop_val[i]);
2111e7801d59Ssowmini 			bcopy(prop_val[i], dp, plen);
2112e7801d59Ssowmini 			slen += plen;
2113e7801d59Ssowmini 			/*
2114e7801d59Ssowmini 			 * add a "," separator and update dp.
2115e7801d59Ssowmini 			 */
2116e7801d59Ssowmini 			if (i != (val_cnt -1))
2117e7801d59Ssowmini 				dp[slen++] = ',';
2118e7801d59Ssowmini 			dp += (plen + 1);
2119e7801d59Ssowmini 		}
2120bcb5c89dSSowmini Varadhan 		status = i_dladm_macprop(dip, B_TRUE);
2121e7801d59Ssowmini 	}
21224045d941Ssowmini 
2123e7801d59Ssowmini 	free(dip);
2124e7801d59Ssowmini 	return (status);
2125e7801d59Ssowmini }
2126e7801d59Ssowmini 
2127e7801d59Ssowmini static dladm_status_t
21283bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_prop(datalink_id_t linkid, const char *prop_name,
21294045d941Ssowmini     char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags)
2130e7801d59Ssowmini {
2131e7801d59Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
21323fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2133bcb5c89dSSowmini Varadhan 	link_attr_t *p;
2134e7801d59Ssowmini 	char tmp = '\0';
2135e7801d59Ssowmini 
2136e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2137e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2138e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2139e7801d59Ssowmini 
2140e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
21413fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2142e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2143e7801d59Ssowmini 
21444045d941Ssowmini 	if (type == DLADM_PROP_VAL_MODIFIABLE) {
2145e7801d59Ssowmini 		*prop_val = &tmp;
2146e7801d59Ssowmini 		*val_cnt = 1;
2147e7801d59Ssowmini 		return (DLADM_STATUS_OK);
2148e7801d59Ssowmini 	}
2149e7801d59Ssowmini 
2150e7801d59Ssowmini 	/*
2151e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2152e7801d59Ssowmini 	 */
2153bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
2154bcb5c89dSSowmini Varadhan 	    dld_flags, &status);
2155e7801d59Ssowmini 	if (dip == NULL)
2156e7801d59Ssowmini 		return (status);
2157e7801d59Ssowmini 
2158bcb5c89dSSowmini Varadhan 	if ((status = i_dladm_macprop(dip, B_FALSE)) == DLADM_STATUS_OK) {
2159e7801d59Ssowmini 		(void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX);
2160e7801d59Ssowmini 		*val_cnt = 1;
2161e7801d59Ssowmini 	}
21624045d941Ssowmini 	free(dip);
21634045d941Ssowmini 	return (status);
21644045d941Ssowmini }
21654045d941Ssowmini 
21664045d941Ssowmini 
21674045d941Ssowmini static dladm_status_t
21684045d941Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid,
21694045d941Ssowmini     datalink_media_t media, uint_t flags)
21704045d941Ssowmini {
21714045d941Ssowmini 	dladm_status_t status;
21724045d941Ssowmini 	char **prop_vals = NULL, *buf;
21734045d941Ssowmini 	size_t bufsize;
21744045d941Ssowmini 	uint_t cnt;
21754045d941Ssowmini 	int i;
21764045d941Ssowmini 
21774045d941Ssowmini 	/*
21784045d941Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
21794045d941Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
21804045d941Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
21814045d941Ssowmini 	 */
21824045d941Ssowmini 	bufsize =
21834045d941Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
21844045d941Ssowmini 	buf = malloc(bufsize);
21854045d941Ssowmini 	prop_vals = (char **)(void *)buf;
21864045d941Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
21874045d941Ssowmini 		prop_vals[i] = buf +
21884045d941Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
21894045d941Ssowmini 		    i * DLADM_PROP_VAL_MAX;
21904045d941Ssowmini 	}
219113a55820Sar224390 
219213a55820Sar224390 	/*
21933bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
21943bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * string, the "" itself is used to reset the property (exceptions
21953bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * are zone and autopush, which populate vdp->vd_val). So
21963bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
21973bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * down on the setprop using the global values in the table. For
21983bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * other cases (vd_name is ""), doing reset-linkprop will cause
21993bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm to do a getprop to find the default value and then do
22003bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * a setprop to reset the value to default.
220113a55820Sar224390 	 */
22023fd94f8cSam223141 	status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media,
22033fd94f8cSam223141 	    MAC_PROP_DEFAULT);
22044045d941Ssowmini 	if (status == DLADM_STATUS_OK) {
22054045d941Ssowmini 		status = i_dladm_set_single_prop(linkid, pdp->pd_class,
22064045d941Ssowmini 		    media, pdp, prop_vals, cnt, flags);
22074045d941Ssowmini 	}
22084045d941Ssowmini 	free(buf);
2209e7801d59Ssowmini 	return (status);
2210e7801d59Ssowmini }
2211bcb5c89dSSowmini Varadhan 
2212bcb5c89dSSowmini Varadhan int
2213bcb5c89dSSowmini Varadhan macprop_to_wifi(mac_prop_id_t wl_prop)
2214bcb5c89dSSowmini Varadhan {
2215bcb5c89dSSowmini Varadhan 	switch (wl_prop) {
2216bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ESSID:
2217bcb5c89dSSowmini Varadhan 		return (WL_ESSID);
2218bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_BSSID:
2219bcb5c89dSSowmini Varadhan 		return (WL_BSSID);
2220bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_BSSTYPE:
2221bcb5c89dSSowmini Varadhan 		return (WL_BSS_TYPE);
2222bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_LINKSTATUS:
2223bcb5c89dSSowmini Varadhan 		return (WL_LINKSTATUS);
2224bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_DESIRED_RATES:
2225bcb5c89dSSowmini Varadhan 		return (WL_DESIRED_RATES);
2226bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SUPPORTED_RATES:
2227bcb5c89dSSowmini Varadhan 		return (WL_SUPPORTED_RATES);
2228bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_AUTH_MODE:
2229bcb5c89dSSowmini Varadhan 		return (WL_AUTH_MODE);
2230bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ENCRYPTION:
2231bcb5c89dSSowmini Varadhan 		return (WL_ENCRYPTION);
2232bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_RSSI:
2233bcb5c89dSSowmini Varadhan 		return (WL_RSSI);
2234bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_PHY_CONFIG:
2235bcb5c89dSSowmini Varadhan 		return (WL_PHY_CONFIG);
2236bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_CAPABILITY:
2237bcb5c89dSSowmini Varadhan 		return (WL_CAPABILITY);
2238bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_WPA:
2239bcb5c89dSSowmini Varadhan 		return (WL_WPA);
2240bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SCANRESULTS:
2241bcb5c89dSSowmini Varadhan 		return (WL_SCANRESULTS);
2242bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_POWER_MODE:
2243bcb5c89dSSowmini Varadhan 		return (WL_POWER_MODE);
2244bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_RADIO:
2245bcb5c89dSSowmini Varadhan 		return (WL_RADIO);
2246bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_ESS_LIST:
2247bcb5c89dSSowmini Varadhan 		return (WL_ESS_LIST);
2248bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_KEY_TAB:
2249bcb5c89dSSowmini Varadhan 		return (WL_WEP_KEY_TAB);
2250bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_CREATE_IBSS:
2251bcb5c89dSSowmini Varadhan 		return (WL_CREATE_IBSS);
2252bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_SETOPTIE:
2253bcb5c89dSSowmini Varadhan 		return (WL_SETOPTIE);
2254bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_DELKEY:
2255bcb5c89dSSowmini Varadhan 		return (WL_DELKEY);
2256bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_KEY:
2257bcb5c89dSSowmini Varadhan 		return (WL_KEY);
2258bcb5c89dSSowmini Varadhan 	case MAC_PROP_WL_MLME:
2259bcb5c89dSSowmini Varadhan 		return (WL_MLME);
2260bcb5c89dSSowmini Varadhan 	default:
2261bcb5c89dSSowmini Varadhan 		return (-1);
2262bcb5c89dSSowmini Varadhan 	}
2263bcb5c89dSSowmini Varadhan }
2264bcb5c89dSSowmini Varadhan 
2265bcb5c89dSSowmini Varadhan dladm_status_t
2266bcb5c89dSSowmini Varadhan i_dladm_wlan_param(datalink_id_t linkid, void *buf, mac_prop_id_t cmd,
2267bcb5c89dSSowmini Varadhan     size_t len, boolean_t set)
2268bcb5c89dSSowmini Varadhan {
2269bcb5c89dSSowmini Varadhan 	uint32_t		flags;
2270bcb5c89dSSowmini Varadhan 	dladm_status_t		status;
2271bcb5c89dSSowmini Varadhan 	uint32_t		media;
2272bcb5c89dSSowmini Varadhan 	dld_ioc_macprop_t	*dip;
2273bcb5c89dSSowmini Varadhan 	void			*dp;
2274bcb5c89dSSowmini Varadhan 
2275bcb5c89dSSowmini Varadhan 	if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media,
2276bcb5c89dSSowmini Varadhan 	    NULL, 0)) != DLADM_STATUS_OK) {
2277bcb5c89dSSowmini Varadhan 		return (status);
2278bcb5c89dSSowmini Varadhan 	}
2279bcb5c89dSSowmini Varadhan 
2280bcb5c89dSSowmini Varadhan 	if (media != DL_WIFI)
2281bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_BADARG);
2282bcb5c89dSSowmini Varadhan 
2283bcb5c89dSSowmini Varadhan 	if (!(flags & DLADM_OPT_ACTIVE))
2284bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_TEMPONLY);
2285bcb5c89dSSowmini Varadhan 
2286bcb5c89dSSowmini Varadhan 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
2287bcb5c89dSSowmini Varadhan 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
2288bcb5c89dSSowmini Varadhan 
2289bcb5c89dSSowmini Varadhan 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
2290bcb5c89dSSowmini Varadhan 	if (dip == NULL)
2291bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2292bcb5c89dSSowmini Varadhan 
2293bcb5c89dSSowmini Varadhan 	dp = (uchar_t *)dip->pr_val;
2294bcb5c89dSSowmini Varadhan 	if (set)
2295bcb5c89dSSowmini Varadhan 		(void) memcpy(dp, buf, len);
2296bcb5c89dSSowmini Varadhan 
2297bcb5c89dSSowmini Varadhan 	status = i_dladm_macprop(dip, set);
2298bcb5c89dSSowmini Varadhan 	if (status == DLADM_STATUS_NOTSUP) {
2299bcb5c89dSSowmini Varadhan 		if (set) {
2300bcb5c89dSSowmini Varadhan 			status = i_dladm_wlan_set_legacy_ioctl(linkid,
2301bcb5c89dSSowmini Varadhan 			    buf, len, macprop_to_wifi(cmd));
2302bcb5c89dSSowmini Varadhan 		} else {
2303bcb5c89dSSowmini Varadhan 			status = i_dladm_wlan_get_legacy_ioctl(linkid,
2304bcb5c89dSSowmini Varadhan 			    buf, len, macprop_to_wifi(cmd));
2305bcb5c89dSSowmini Varadhan 		}
2306bcb5c89dSSowmini Varadhan 	} else if (status == DLADM_STATUS_OK) {
2307bcb5c89dSSowmini Varadhan 		if (!set)
2308bcb5c89dSSowmini Varadhan 			(void) memcpy(buf, dp, len);
2309bcb5c89dSSowmini Varadhan 	}
2310bcb5c89dSSowmini Varadhan 
2311bcb5c89dSSowmini Varadhan 	free(dip);
2312bcb5c89dSSowmini Varadhan 	return (status);
2313bcb5c89dSSowmini Varadhan }
2314bcb5c89dSSowmini Varadhan 
2315bcb5c89dSSowmini Varadhan static dladm_status_t
2316bcb5c89dSSowmini Varadhan i_dladm_wlan_get_legacy_ioctl(datalink_id_t linkid, void *buf, uint_t buflen,
2317bcb5c89dSSowmini Varadhan     uint_t id)
2318bcb5c89dSSowmini Varadhan {
2319bcb5c89dSSowmini Varadhan 	wldp_t *gbuf;
2320bcb5c89dSSowmini Varadhan 	dladm_status_t status;
2321bcb5c89dSSowmini Varadhan 
2322bcb5c89dSSowmini Varadhan 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
2323bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2324bcb5c89dSSowmini Varadhan 
2325bcb5c89dSSowmini Varadhan 	(void) memset(gbuf, 0, MAX_BUF_LEN);
2326bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, MAX_BUF_LEN,
2327bcb5c89dSSowmini Varadhan 	    WLAN_GET_PARAM, sizeof (wldp_t));
2328bcb5c89dSSowmini Varadhan 	if (status == DLADM_STATUS_OK)
2329bcb5c89dSSowmini Varadhan 		(void) memcpy(buf, gbuf->wldp_buf, buflen);
2330bcb5c89dSSowmini Varadhan 
2331bcb5c89dSSowmini Varadhan 	free(gbuf);
2332bcb5c89dSSowmini Varadhan 	return (status);
2333bcb5c89dSSowmini Varadhan }
2334bcb5c89dSSowmini Varadhan 
2335bcb5c89dSSowmini Varadhan static dladm_status_t
2336bcb5c89dSSowmini Varadhan i_dladm_wlan_set_legacy_ioctl(datalink_id_t linkid,  void *buf, uint_t buflen,
2337bcb5c89dSSowmini Varadhan     uint_t id)
2338bcb5c89dSSowmini Varadhan {
2339bcb5c89dSSowmini Varadhan 	wldp_t *gbuf;
2340bcb5c89dSSowmini Varadhan 	dladm_status_t status = DLADM_STATUS_OK;
2341bcb5c89dSSowmini Varadhan 
2342bcb5c89dSSowmini Varadhan 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
2343bcb5c89dSSowmini Varadhan 		return (DLADM_STATUS_NOMEM);
2344bcb5c89dSSowmini Varadhan 
2345bcb5c89dSSowmini Varadhan 	(void) memset(gbuf, 0, MAX_BUF_LEN);
2346bcb5c89dSSowmini Varadhan 	(void) memcpy(gbuf->wldp_buf, buf, buflen);
2347bcb5c89dSSowmini Varadhan 	buflen += WIFI_BUF_OFFSET;
2348bcb5c89dSSowmini Varadhan 	status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, buflen,
2349bcb5c89dSSowmini Varadhan 	    WLAN_SET_PARAM, buflen);
2350bcb5c89dSSowmini Varadhan 
2351bcb5c89dSSowmini Varadhan 	free(gbuf);
2352bcb5c89dSSowmini Varadhan 	return (status);
2353bcb5c89dSSowmini Varadhan }
2354