13147Sxc151355 /*
23147Sxc151355  * CDDL HEADER START
33147Sxc151355  *
43147Sxc151355  * The contents of this file are subject to the terms of the
53147Sxc151355  * Common Development and Distribution License (the "License").
63147Sxc151355  * You may not use this file except in compliance with the License.
73147Sxc151355  *
83147Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93147Sxc151355  * or http://www.opensolaris.org/os/licensing.
103147Sxc151355  * See the License for the specific language governing permissions
113147Sxc151355  * and limitations under the License.
123147Sxc151355  *
133147Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
143147Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153147Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
163147Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
173147Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
183147Sxc151355  *
193147Sxc151355  * CDDL HEADER END
203147Sxc151355  */
213147Sxc151355 /*
228874SSebastien.Roy@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233147Sxc151355  * Use is subject to license terms.
243147Sxc151355  */
253147Sxc151355 
263147Sxc151355 #include <stdlib.h>
273147Sxc151355 #include <strings.h>
283147Sxc151355 #include <errno.h>
293147Sxc151355 #include <ctype.h>
305895Syz147064 #include <stddef.h>
313448Sdh155122 #include <sys/types.h>
323147Sxc151355 #include <sys/stat.h>
333448Sdh155122 #include <sys/dld.h>
343448Sdh155122 #include <sys/zone.h>
353448Sdh155122 #include <fcntl.h>
363448Sdh155122 #include <unistd.h>
373448Sdh155122 #include <libdevinfo.h>
383448Sdh155122 #include <zone.h>
393871Syz147064 #include <libdllink.h>
403147Sxc151355 #include <libdladm_impl.h>
415895Syz147064 #include <libdlwlan_impl.h>
423871Syz147064 #include <libdlwlan.h>
435895Syz147064 #include <libdlvlan.h>
448275SEric Cheng #include <libdlvnic.h>
458275SEric Cheng #include <libintl.h>
463448Sdh155122 #include <dlfcn.h>
473448Sdh155122 #include <link.h>
485895Syz147064 #include <inet/wifi_ioctl.h>
495903Ssowmini #include <libdladm.h>
508275SEric Cheng #include <libdlstat.h>
515903Ssowmini #include <sys/param.h>
528275SEric Cheng #include <sys/debug.h>
538275SEric Cheng #include <sys/dld.h>
548275SEric Cheng #include <sys/mac_flow.h>
555903Ssowmini #include <inttypes.h>
565903Ssowmini #include <sys/ethernet.h>
577663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
587663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
593448Sdh155122 
605895Syz147064 /*
615895Syz147064  * The linkprop get() callback.
628275SEric Cheng  * - pd: 	pointer to the prop_desc_t
635895Syz147064  * - propstrp:	a property string array to keep the returned property.
645895Syz147064  *		Caller allocated.
655895Syz147064  * - cntp:	number of returned properties.
665895Syz147064  *		Caller also uses it to indicate how many it expects.
675895Syz147064  */
685903Ssowmini struct prop_desc;
698275SEric Cheng typedef struct prop_desc prop_desc_t;
708275SEric Cheng 
718453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
725960Ssowmini 			datalink_id_t, char **propstp, uint_t *cntp,
738118SVasumathi.Sundaram@Sun.COM 			datalink_media_t, uint_t, uint_t *);
745895Syz147064 
755895Syz147064 /*
765895Syz147064  * The linkprop set() callback.
775895Syz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
785895Syz147064  * - cnt:	number of properties to be set.
795903Ssowmini  * - flags: 	additional flags passed down the system call.
805903Ssowmini  *
815903Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
825903Ssowmini  * a format suitable for kernel consumption. This may require allocation
835903Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
845903Ssowmini  * by all other pd_sets) which invokes the ioctl.
855895Syz147064  */
868453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
878275SEric Cheng 			    val_desc_t *propval, uint_t cnt, uint_t flags,
888275SEric Cheng 			    datalink_media_t);
893448Sdh155122 
905895Syz147064 /*
915895Syz147064  * The linkprop check() callback.
925895Syz147064  * - propstrp:	property string array which keeps the property to be checked.
935895Syz147064  * - cnt:	number of properties.
945895Syz147064  * - propval:	return value; the property values of the given property strings.
955903Ssowmini  *
965903Ssowmini  * pd_check checks that the input values are valid. It does so by
975903Ssowmini  * iteraring through the pd_modval list for the property. If
985903Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
995903Ssowmini  * specific to this property can be used. If the input values are
1005903Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
1015903Ssowmini  * with either a val_desc_t found on the pd_modval list or something
1025903Ssowmini  * generated on the fly.
1035895Syz147064  */
1048453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
1058453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **propstrp, uint_t cnt,
1068453SAnurag.Maskey@Sun.COM 			    val_desc_t *propval, datalink_media_t);
1073448Sdh155122 
1087663SSowmini.Varadhan@Sun.COM typedef struct link_attr_s {
1096789Sam223141 	mac_prop_id_t	pp_id;
1105903Ssowmini 	size_t		pp_valsize;
1115903Ssowmini 	char		*pp_name;
1127663SSowmini.Varadhan@Sun.COM } link_attr_t;
1135903Ssowmini 
1147663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
1158275SEric Cheng 			    const char *, uint_t, dladm_status_t *);
1167663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
1178275SEric Cheng 			    mac_prop_id_t, uint_t, dladm_status_t *);
1188453SAnurag.Maskey@Sun.COM static dld_ioc_macprop_t *i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
1198453SAnurag.Maskey@Sun.COM 			    char *, uint_t, dladm_status_t *, uint_t *);
1208453SAnurag.Maskey@Sun.COM 
121*9692SRishi.Srivatsavai@Sun.COM static dladm_status_t i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
1228453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
1238460SArtem.Kachitchkin@Sun.COM static dladm_status_t i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
1248453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *, dladm_prop_type_t,
1258453SAnurag.Maskey@Sun.COM 			    uint_t);
1267663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_name2prop(const char *);
1277663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_id2prop(mac_prop_id_t);
1288275SEric Cheng 
1295895Syz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
1305895Syz147064 			do_get_rate_prop, do_get_channel_prop,
1315903Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
1327342SAruna.Ramakrishna@Sun.COM 			i_dladm_duplex_get, i_dladm_status_get,
1337342SAruna.Ramakrishna@Sun.COM 			i_dladm_binary_get, i_dladm_uint32_get,
1348460SArtem.Kachitchkin@Sun.COM 			i_dladm_flowctl_get, i_dladm_maxbw_get,
1358874SSebastien.Roy@Sun.COM 			i_dladm_cpus_get, i_dladm_priority_get,
1369514SGirish.Moodalbail@Sun.COM 			i_dladm_tagmode_get, i_dladm_range_get;
1378275SEric Cheng 
1387342SAruna.Ramakrishna@Sun.COM static pd_setf_t	do_set_zone, do_set_rate_prop,
1395903Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
1408275SEric Cheng 			i_dladm_set_public_prop, do_set_res, do_set_cpus;
1418275SEric Cheng 
1425903Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
1438275SEric Cheng 			i_dladm_defmtu_check, do_check_maxbw, do_check_cpus,
1448275SEric Cheng 			do_check_priority;
1458275SEric Cheng 
1468453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_speed_get(dladm_handle_t, prop_desc_t *,
1478453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **, uint_t *, uint_t, uint_t *);
1488453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_wlan_get_legacy_ioctl(dladm_handle_t,
1498453SAnurag.Maskey@Sun.COM 			    datalink_id_t, void *, uint_t, uint_t);
1508453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_wlan_set_legacy_ioctl(dladm_handle_t,
1518453SAnurag.Maskey@Sun.COM 			    datalink_id_t, void *, uint_t, uint_t);
1528453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1538275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1548275SEric Cheng 
1558275SEric Cheng struct prop_desc {
1565895Syz147064 	/*
1575895Syz147064 	 * link property name
1585895Syz147064 	 */
1595895Syz147064 	char			*pd_name;
1605895Syz147064 
1615895Syz147064 	/*
1625895Syz147064 	 * default property value, can be set to { "", NULL }
1635895Syz147064 	 */
1645895Syz147064 	val_desc_t		pd_defval;
1655895Syz147064 
1665895Syz147064 	/*
1675895Syz147064 	 * list of optional property values, can be NULL.
1685895Syz147064 	 *
1695895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1705895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1715895Syz147064 	 */
1725895Syz147064 	val_desc_t		*pd_optval;
1735895Syz147064 
1745895Syz147064 	/*
1755895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1765895Syz147064 	 */
1775895Syz147064 	uint_t			pd_noptval;
1785895Syz147064 
1795895Syz147064 	/*
1805895Syz147064 	 * callback to set link property;
1815895Syz147064 	 * set to NULL if this property is read-only
1825895Syz147064 	 */
1835895Syz147064 	pd_setf_t		*pd_set;
1845895Syz147064 
1855895Syz147064 	/*
1865895Syz147064 	 * callback to get modifiable link property
1875895Syz147064 	 */
1885895Syz147064 	pd_getf_t		*pd_getmod;
1895895Syz147064 
1905895Syz147064 	/*
1915895Syz147064 	 * callback to get current link property
1925895Syz147064 	 */
1935895Syz147064 	pd_getf_t		*pd_get;
1945895Syz147064 
1955895Syz147064 	/*
1965895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
1975895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
1985895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
1995895Syz147064 	 * valid.
2005895Syz147064 	 */
2015895Syz147064 	pd_checkf_t		*pd_check;
2025895Syz147064 
2035895Syz147064 	uint_t			pd_flags;
2045903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2055903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
2065895Syz147064 	/*
2075895Syz147064 	 * indicate link classes this property applies to.
2085895Syz147064 	 */
2095895Syz147064 	datalink_class_t	pd_class;
2105895Syz147064 
2115895Syz147064 	/*
2125895Syz147064 	 * indicate link media type this property applies to.
2135895Syz147064 	 */
2145895Syz147064 	datalink_media_t	pd_dmedia;
2158275SEric Cheng };
2163448Sdh155122 
2176789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2185903Ssowmini 
2197663SSowmini.Varadhan@Sun.COM /*
2207663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2217663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2227663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2237663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2247663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2257663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2267663SSowmini.Varadhan@Sun.COM  */
2277663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2287663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2295903Ssowmini 
2307663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2317663SSowmini.Varadhan@Sun.COM 
2327663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2337663SSowmini.Varadhan@Sun.COM 
2347663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2355903Ssowmini 
2367663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2375903Ssowmini 
2387663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2397663SSowmini.Varadhan@Sun.COM 
2407663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2415903Ssowmini 
2427663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2437663SSowmini.Varadhan@Sun.COM 
2449449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),	"adv_10gfdx_cap"},
2459449Sxiuyan.wang@Sun.COM 
2469449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),	"en_10gfdx_cap"},
2479449Sxiuyan.wang@Sun.COM 
2487663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2497663SSowmini.Varadhan@Sun.COM 
2507663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2515903Ssowmini 
2527663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2535903Ssowmini 
2547663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2557663SSowmini.Varadhan@Sun.COM 
2567663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2577342SAruna.Ramakrishna@Sun.COM 
2587663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2597663SSowmini.Varadhan@Sun.COM 
2607663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2617663SSowmini.Varadhan@Sun.COM 
2627663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2637342SAruna.Ramakrishna@Sun.COM 
2647663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2657663SSowmini.Varadhan@Sun.COM 
2667663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2675903Ssowmini 
2687663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2697663SSowmini.Varadhan@Sun.COM 
2707663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2715903Ssowmini 
2727663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2737663SSowmini.Varadhan@Sun.COM 
2747663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2755903Ssowmini 
2767663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2777663SSowmini.Varadhan@Sun.COM 
2787663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2797663SSowmini.Varadhan@Sun.COM 
2807663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2817663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2825903Ssowmini 
2837663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2847663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2857663SSowmini.Varadhan@Sun.COM 
2867663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2875903Ssowmini 
2887663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
2897663SSowmini.Varadhan@Sun.COM 
2907663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
2915903Ssowmini 
2927663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
2937663SSowmini.Varadhan@Sun.COM 
2947663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
2955903Ssowmini 
2967663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
2977663SSowmini.Varadhan@Sun.COM 
2987663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
2997663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
3005903Ssowmini 
3017663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
3027663SSowmini.Varadhan@Sun.COM 
3037663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
3045903Ssowmini 
3057663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3067663SSowmini.Varadhan@Sun.COM 
3077663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3085903Ssowmini 
3097663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3107663SSowmini.Varadhan@Sun.COM 
3117663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3127663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3135903Ssowmini 
3147663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3157663SSowmini.Varadhan@Sun.COM 
3167663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3175903Ssowmini 
3187663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3197663SSowmini.Varadhan@Sun.COM 
3208275SEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
3218275SEric Cheng 
3228275SEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
3238275SEric Cheng 
3248275SEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
3258275SEric Cheng 
3268874SSebastien.Roy@Sun.COM 	{ MAC_PROP_TAGMODE,	sizeof (link_tagmode_t),	"tagmode"},
3278874SSebastien.Roy@Sun.COM 
3287663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3298275SEric Cheng 
3305903Ssowmini };
3315903Ssowmini 
3325903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3335903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3345903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3355903Ssowmini };
3365903Ssowmini static  val_desc_t	link_status_vals[] = {
3375903Ssowmini 	{ "up",		LINK_STATE_UP		},
3385903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3395903Ssowmini };
3405903Ssowmini static  val_desc_t	link_01_vals[] = {
3415903Ssowmini 	{ "1",		1			},
3425903Ssowmini 	{ "0",		0			}
3435903Ssowmini };
3445903Ssowmini static  val_desc_t	link_flow_vals[] = {
3455903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3465903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3475903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3485903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3495903Ssowmini };
3508275SEric Cheng static  val_desc_t	link_priority_vals[] = {
3518275SEric Cheng 	{ "low",	MPL_LOW	},
3528275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
3538275SEric Cheng 	{ "high",	MPL_HIGH	}
3548275SEric Cheng };
3555903Ssowmini 
3568874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
3578874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
3588874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
3598874SSebastien.Roy@Sun.COM };
3608874SSebastien.Roy@Sun.COM 
3615895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
3625895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
3635895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
3645895Syz147064 };
3655895Syz147064 
3665895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
3675895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
3685895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
3695895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
3705895Syz147064 };
3715895Syz147064 
3728275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
3738275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
3748275SEric Cheng 
3753448Sdh155122 static prop_desc_t	prop_table[] = {
3765903Ssowmini 	{ "channel",	{ NULL, 0 },
3775903Ssowmini 	    NULL, 0, NULL, NULL,
3785895Syz147064 	    do_get_channel_prop, NULL, 0,
3795903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3805895Syz147064 
3815895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
3825895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
3835895Syz147064 	    do_set_powermode_prop, NULL,
3845895Syz147064 	    do_get_powermode_prop, NULL, 0,
3855903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3865895Syz147064 
3875895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
3885895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
3895895Syz147064 	    do_set_radio_prop, NULL,
3905895Syz147064 	    do_get_radio_prop, NULL, 0,
3915903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3925895Syz147064 
3935895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
3945895Syz147064 	    do_set_rate_prop, do_get_rate_mod,
3955895Syz147064 	    do_get_rate_prop, do_check_rate, 0,
3965960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
3975895Syz147064 
3986512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
3997342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL,
4007342SAruna.Ramakrishna@Sun.COM 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
4015903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4025895Syz147064 
4036512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
4043448Sdh155122 	    do_set_zone, NULL,
4057342SAruna.Ramakrishna@Sun.COM 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4065903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4075903Ssowmini 
4088275SEric Cheng 	{ "duplex",	{ "", 0 },
4095903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
4107342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_duplex_get, NULL,
4115903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4125903Ssowmini 
4138275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4145903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4157342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_status_get, NULL,
4166512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4175903Ssowmini 
4185903Ssowmini 	{ "adv_autoneg_cap", { "1", 1 },
4195903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4207342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4215903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4225903Ssowmini 
4236512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4249514SGirish.Moodalbail@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get,
4259514SGirish.Moodalbail@Sun.COM 	    i_dladm_uint32_get, i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL,
4267342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4275903Ssowmini 
4286512Ssowmini 	{ "flowctrl", { "", 0 },
4295903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4307342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
4315903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4325903Ssowmini 
4339449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
4349449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4359449Sxiuyan.wang@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4369449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4379449Sxiuyan.wang@Sun.COM 
4389449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
4399449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4409449Sxiuyan.wang@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4419449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4429449Sxiuyan.wang@Sun.COM 
4436512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4446512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4457342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4465903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4475903Ssowmini 
4486512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
4495903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4507342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4515903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4525903Ssowmini 
4536512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
4545903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4557342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4565903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4575903Ssowmini 
4586512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
4595903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4607342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4615903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4625903Ssowmini 
4636512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
4645903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4657342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4665903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4675903Ssowmini 
4686512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
4695903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4707342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4715903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4725903Ssowmini 
4736512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
4745903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4757342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4765903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4775903Ssowmini 
4786512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
4795903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4807342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4815903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4825903Ssowmini 
4836512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
4845903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4857342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4865903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4875903Ssowmini 
4886512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
4895903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4907342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4915903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4925903Ssowmini 
4936512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
4945903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4957342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4965903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4975903Ssowmini 
4986512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
4995903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5007342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5018275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5028275SEric Cheng 
5038275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
5048275SEric Cheng 	    do_set_res, NULL,
5058460SArtem.Kachitchkin@Sun.COM 	    i_dladm_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
5068275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5078275SEric Cheng 
5088275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
5098275SEric Cheng 	    do_set_cpus, NULL,
5108460SArtem.Kachitchkin@Sun.COM 	    i_dladm_cpus_get, do_check_cpus, 0,
5118275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5128275SEric Cheng 
5138275SEric Cheng 	{ "priority", { "high", RESET_VAL },
5148275SEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
5158460SArtem.Kachitchkin@Sun.COM 	    i_dladm_priority_get, do_check_priority, PD_CHECK_ALLOC,
5168275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5178874SSebastien.Roy@Sun.COM 
5188874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
5198874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
5208874SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_tagmode_get,
5218874SSebastien.Roy@Sun.COM 	    NULL, 0,
5228874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
5238874SSebastien.Roy@Sun.COM 	    DL_ETHER }
5243448Sdh155122 };
5253448Sdh155122 
5265895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
5275895Syz147064 
5288275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
5298275SEric Cheng 	{"maxbw",	do_extract_maxbw},
5308275SEric Cheng 	{"priority",	do_extract_priority},
5318275SEric Cheng 	{"cpus",	do_extract_cpus}
5328275SEric Cheng };
5338275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
5348275SEric Cheng 	sizeof (resource_prop_t))
5358275SEric Cheng 
5367663SSowmini.Varadhan@Sun.COM /*
5377663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
5387663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
5397663SSowmini.Varadhan@Sun.COM  */
5407663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
5417663SSowmini.Varadhan@Sun.COM 
5428453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
5438453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
5448453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
5458453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
5468460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
5478460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
5488460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
5498453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
5508453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
5518453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
5528453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
5538453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
5548453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
5558453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
5568275SEric Cheng 
5575895Syz147064 /*
5585895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
5595895Syz147064  * rates to be retrieved. However, we cannot increase it at this
5605895Syz147064  * time because it will break binary compatibility with unbundled
5615895Syz147064  * WiFi drivers and utilities. So for now we define an additional
5625895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
5635895Syz147064  */
5645895Syz147064 #define	MAX_SUPPORT_RATES	64
5655895Syz147064 
5665895Syz147064 #define	AP_ANCHOR	"[anchor]"
5675895Syz147064 #define	AP_DELIMITER	'.'
5685895Syz147064 
5695895Syz147064 static dladm_status_t
5705895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
5715895Syz147064     val_desc_t *vdp)
5725895Syz147064 {
5735895Syz147064 	int		i, j;
5745895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
5753147Sxc151355 
5765895Syz147064 	for (j = 0; j < val_cnt; j++) {
5775895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
5785895Syz147064 			if (strcasecmp(*prop_val,
5795895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
5805895Syz147064 				break;
5815895Syz147064 			}
5825895Syz147064 		}
5835895Syz147064 		if (i == pdp->pd_noptval) {
5845895Syz147064 			status = DLADM_STATUS_BADVAL;
5855895Syz147064 			goto done;
5865895Syz147064 		}
5875895Syz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
5885895Syz147064 	}
5895895Syz147064 
5905895Syz147064 done:
5915895Syz147064 	return (status);
5925895Syz147064 }
5935895Syz147064 
5945895Syz147064 static dladm_status_t
5958453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
5968453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
5978453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
5983147Sxc151355 {
5995895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6005895Syz147064 	val_desc_t	*vdp = NULL;
6015895Syz147064 	boolean_t	needfree = B_FALSE;
6025895Syz147064 	uint_t		cnt, i;
6033147Sxc151355 
6045895Syz147064 	if (!(pdp->pd_class & class))
6055895Syz147064 		return (DLADM_STATUS_BADARG);
6065895Syz147064 
6075895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
6083147Sxc151355 		return (DLADM_STATUS_BADARG);
6093147Sxc151355 
6105895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
6115895Syz147064 		return (DLADM_STATUS_TEMPONLY);
6125895Syz147064 
6135895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
6145895Syz147064 		return (DLADM_STATUS_OK);
6155895Syz147064 
6165895Syz147064 	if (pdp->pd_set == NULL)
6175895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
6183448Sdh155122 
6195895Syz147064 	if (prop_val != NULL) {
6205895Syz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
6215895Syz147064 		if (vdp == NULL)
6225895Syz147064 			return (DLADM_STATUS_NOMEM);
6235895Syz147064 
6245895Syz147064 		if (pdp->pd_check != NULL) {
6258275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
6268453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
6278453SAnurag.Maskey@Sun.COM 			    val_cnt, vdp, media);
6285895Syz147064 		} else if (pdp->pd_optval != NULL) {
6295895Syz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
6305895Syz147064 		} else {
6313448Sdh155122 			status = DLADM_STATUS_BADARG;
6323147Sxc151355 		}
6335895Syz147064 
6343147Sxc151355 		if (status != DLADM_STATUS_OK)
6355895Syz147064 			goto done;
6365895Syz147064 
6375895Syz147064 		cnt = val_cnt;
6385895Syz147064 	} else {
6398275SEric Cheng 		boolean_t	defval = B_FALSE;
6408275SEric Cheng 
6415895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
6425895Syz147064 			return (DLADM_STATUS_NOTSUP);
6435895Syz147064 
6447342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
6458275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
6468275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
6476512Ssowmini 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
6486512Ssowmini 				return (DLADM_STATUS_NOMEM);
6497342SAruna.Ramakrishna@Sun.COM 
6508275SEric Cheng 			if (defval) {
6518275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
6528275SEric Cheng 				    sizeof (val_desc_t));
6538275SEric Cheng 			} else if (pdp->pd_check != NULL) {
6548453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
6558453SAnurag.Maskey@Sun.COM 				    prop_val, cnt, vdp, media);
6567342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
6577342SAruna.Ramakrishna@Sun.COM 					goto done;
6587342SAruna.Ramakrishna@Sun.COM 			}
6596512Ssowmini 		} else {
6608453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
6616512Ssowmini 			    media, flags);
6626512Ssowmini 			return (status);
6636512Ssowmini 		}
6645895Syz147064 	}
6658453SAnurag.Maskey@Sun.COM 	status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags, media);
6665895Syz147064 	if (needfree) {
6675895Syz147064 		for (i = 0; i < cnt; i++)
6685903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
6693147Sxc151355 	}
6705895Syz147064 done:
6715895Syz147064 	free(vdp);
6725895Syz147064 	return (status);
6735895Syz147064 }
6745895Syz147064 
6755895Syz147064 static dladm_status_t
6768453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
6778453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
6785895Syz147064 {
6795895Syz147064 	int			i;
6805895Syz147064 	boolean_t		found = B_FALSE;
6815895Syz147064 	datalink_class_t	class;
6825895Syz147064 	uint32_t		media;
6835895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
6845895Syz147064 
6858453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
6868453SAnurag.Maskey@Sun.COM 	    NULL, 0);
6875895Syz147064 	if (status != DLADM_STATUS_OK)
6885895Syz147064 		return (status);
6895895Syz147064 
6905895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
6915895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
6925895Syz147064 		dladm_status_t	s;
6935895Syz147064 
6945895Syz147064 		if (prop_name != NULL &&
6955895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
6965895Syz147064 			continue;
6975895Syz147064 		found = B_TRUE;
6988453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
6998453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
7003448Sdh155122 
7015895Syz147064 		if (prop_name != NULL) {
7025895Syz147064 			status = s;
7035895Syz147064 			break;
7045895Syz147064 		} else {
7055895Syz147064 			if (s != DLADM_STATUS_OK &&
7065895Syz147064 			    s != DLADM_STATUS_NOTSUP)
7075895Syz147064 				status = s;
7085895Syz147064 		}
7095895Syz147064 	}
7105903Ssowmini 	if (!found) {
7115903Ssowmini 		if (prop_name[0] == '_') {
7125903Ssowmini 			/* other private properties */
713*9692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
714*9692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
7155903Ssowmini 		} else  {
7165903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
7175903Ssowmini 		}
7185903Ssowmini 	}
7195895Syz147064 
7205895Syz147064 	return (status);
7215895Syz147064 }
7225895Syz147064 
7235895Syz147064 /*
7245895Syz147064  * Set/reset link property for specific link
7255895Syz147064  */
7265895Syz147064 dladm_status_t
7278453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
7288453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
7295895Syz147064 {
7305895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
7315895Syz147064 
7325895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
7335895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
7345895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
7355895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
7365895Syz147064 		return (DLADM_STATUS_BADARG);
7375895Syz147064 	}
7385895Syz147064 
739*9692SRishi.Srivatsavai@Sun.COM 	/*
740*9692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
741*9692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
742*9692SRishi.Srivatsavai@Sun.COM 	 */
7438453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
7445895Syz147064 	    val_cnt, flags);
7455895Syz147064 	if (status != DLADM_STATUS_OK)
7465895Syz147064 		return (status);
7475895Syz147064 
7485895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
7498453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
7503147Sxc151355 		    prop_val, val_cnt);
7513147Sxc151355 	}
7523147Sxc151355 	return (status);
7533147Sxc151355 }
7543147Sxc151355 
7555895Syz147064 /*
7568460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
7578460SArtem.Kachitchkin@Sun.COM  *
7588460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
7598460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
7608460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
7618460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
7625895Syz147064  */
7633147Sxc151355 dladm_status_t
7648453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
7658453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
7663147Sxc151355 {
7675895Syz147064 	dladm_status_t		status;
7685895Syz147064 	datalink_class_t	class;
7695895Syz147064 	uint_t			media;
7705895Syz147064 	int			i;
7715895Syz147064 
7725895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
7735895Syz147064 		return (DLADM_STATUS_BADARG);
7745895Syz147064 
7758453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
7768453SAnurag.Maskey@Sun.COM 	    NULL, 0);
7775895Syz147064 	if (status != DLADM_STATUS_OK)
7785895Syz147064 		return (status);
7795895Syz147064 
7808460SArtem.Kachitchkin@Sun.COM 	/* public */
7815895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
7825895Syz147064 		if (!(prop_table[i].pd_class & class))
7835895Syz147064 			continue;
7845895Syz147064 
7855895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
7865895Syz147064 			continue;
7875895Syz147064 
7888453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
7895895Syz147064 		    DLADM_WALK_TERMINATE) {
7905895Syz147064 			break;
7915895Syz147064 		}
7925895Syz147064 	}
7935895Syz147064 
7948460SArtem.Kachitchkin@Sun.COM 	/* private */
7958460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
7968460SArtem.Kachitchkin@Sun.COM 
7978460SArtem.Kachitchkin@Sun.COM 	return (status);
7985895Syz147064 }
7993448Sdh155122 
8005895Syz147064 /*
8015895Syz147064  * Get linkprop of the given specific link.
8025895Syz147064  */
8035895Syz147064 dladm_status_t
8048453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8058453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
8068453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
8075895Syz147064 {
8085895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
8095895Syz147064 	datalink_class_t	class;
8105895Syz147064 	uint_t			media;
8115895Syz147064 	prop_desc_t		*pdp;
8126512Ssowmini 	uint_t			cnt, dld_flags = 0;
8135895Syz147064 	int			i;
8148118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
8155895Syz147064 
8166512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
8179514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_DEFAULT;
8189514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
8199514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_POSSIBLE;
8206512Ssowmini 
8215895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
8225895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
8235895Syz147064 		return (DLADM_STATUS_BADARG);
8245895Syz147064 
8255895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
8265895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
8275895Syz147064 			break;
8285895Syz147064 
8295903Ssowmini 	if (i == DLADM_MAX_PROPS) {
8305903Ssowmini 		if (prop_name[0] == '_') {
8315903Ssowmini 			/*
8325903Ssowmini 			 * private property.
8335903Ssowmini 			 */
8348460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
8358460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
8368460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
8378460SArtem.Kachitchkin@Sun.COM 			else
8388460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
8398460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
8408460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
8415903Ssowmini 		} else {
8425903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
8435903Ssowmini 		}
8445903Ssowmini 	}
8455895Syz147064 
8465895Syz147064 	pdp = &prop_table[i];
8475895Syz147064 
8488453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
8498453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8505895Syz147064 	if (status != DLADM_STATUS_OK)
8515895Syz147064 		return (status);
8525895Syz147064 
8535895Syz147064 	if (!(pdp->pd_class & class))
8545895Syz147064 		return (DLADM_STATUS_BADARG);
8555895Syz147064 
8565895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
8573147Sxc151355 		return (DLADM_STATUS_BADARG);
8583147Sxc151355 
8595895Syz147064 	switch (type) {
8605895Syz147064 	case DLADM_PROP_VAL_CURRENT:
8618453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
8628453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
8638118SVasumathi.Sundaram@Sun.COM 		break;
8648118SVasumathi.Sundaram@Sun.COM 
8658118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
8668118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
8678118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
8688118SVasumathi.Sundaram@Sun.COM 		} else {
8698453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
8708453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
8718118SVasumathi.Sundaram@Sun.COM 		}
8728118SVasumathi.Sundaram@Sun.COM 
8738118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
8749055SMichael.Lim@Sun.COM 		*val_cntp = 1;
8758275SEric Cheng 		if (status == DLADM_STATUS_OK)
8768275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
8775895Syz147064 		break;
8785895Syz147064 
8795895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
8806768Sar224390 		/*
8816768Sar224390 		 * If defaults are not defined for the property,
8826768Sar224390 		 * pd_defval.vd_name should be null. If the driver
8836768Sar224390 		 * has to be contacted for the value, vd_name should
8846768Sar224390 		 * be the empty string (""). Otherwise, dladm will
8856768Sar224390 		 * just print whatever is in the table.
8866768Sar224390 		 */
8875895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
8885895Syz147064 			status = DLADM_STATUS_NOTSUP;
8895895Syz147064 			break;
8905895Syz147064 		}
8916512Ssowmini 
8926512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
8938453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
8948453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
8956512Ssowmini 		} else {
8966512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
8976512Ssowmini 		}
8985895Syz147064 		*val_cntp = 1;
8995895Syz147064 		break;
9003448Sdh155122 
9015895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
9025895Syz147064 		if (pdp->pd_getmod != NULL) {
9038453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
9048118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
9055895Syz147064 			break;
9065895Syz147064 		}
9075895Syz147064 		cnt = pdp->pd_noptval;
9085895Syz147064 		if (cnt == 0) {
9095895Syz147064 			status = DLADM_STATUS_NOTSUP;
9105895Syz147064 		} else if (cnt > *val_cntp) {
9115895Syz147064 			status = DLADM_STATUS_TOOSMALL;
9125895Syz147064 		} else {
9135895Syz147064 			for (i = 0; i < cnt; i++) {
9145895Syz147064 				(void) strcpy(prop_val[i],
9155895Syz147064 				    pdp->pd_optval[i].vd_name);
9165895Syz147064 			}
9175895Syz147064 			*val_cntp = cnt;
9185895Syz147064 		}
9195895Syz147064 		break;
9205895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
9215895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
9225895Syz147064 			return (DLADM_STATUS_TEMPONLY);
9238453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
9245895Syz147064 		    prop_val, val_cntp);
9255895Syz147064 		break;
9265895Syz147064 	default:
9275895Syz147064 		status = DLADM_STATUS_BADARG;
9285895Syz147064 		break;
9293147Sxc151355 	}
9303448Sdh155122 
9315895Syz147064 	return (status);
9325895Syz147064 }
9335895Syz147064 
9345895Syz147064 /*ARGSUSED*/
9355895Syz147064 static int
9368453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
9378453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
9385895Syz147064 {
9395895Syz147064 	char	*buf, **propvals;
9405895Syz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
9415895Syz147064 
9425895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
9435895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
9445895Syz147064 		return (DLADM_WALK_CONTINUE);
9455895Syz147064 	}
9465895Syz147064 
9475895Syz147064 	propvals = (char **)(void *)buf;
9485895Syz147064 	for (i = 0; i < valcnt; i++) {
9495895Syz147064 		propvals[i] = buf +
9505895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
9515895Syz147064 		    i * DLADM_PROP_VAL_MAX;
9525895Syz147064 	}
9535895Syz147064 
9548453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
9558453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
9565895Syz147064 		goto done;
9575895Syz147064 	}
9585895Syz147064 
9598453SAnurag.Maskey@Sun.COM 	(void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
9605895Syz147064 	    DLADM_OPT_ACTIVE);
9615895Syz147064 
9625895Syz147064 done:
9635895Syz147064 	if (buf != NULL)
9645895Syz147064 		free(buf);
9655895Syz147064 
9665895Syz147064 	return (DLADM_WALK_CONTINUE);
9675895Syz147064 }
9685895Syz147064 
9695895Syz147064 /*ARGSUSED*/
9705895Syz147064 static int
9718453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
9725895Syz147064 {
9738275SEric Cheng 	datalink_class_t	class;
9748275SEric Cheng 	dladm_status_t		status;
9758275SEric Cheng 
9768453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
9778453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9788275SEric Cheng 	if (status != DLADM_STATUS_OK)
9798275SEric Cheng 		return (DLADM_WALK_TERMINATE);
9808275SEric Cheng 
9818275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
9828453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
9838275SEric Cheng 
9845895Syz147064 	return (DLADM_WALK_CONTINUE);
9855895Syz147064 }
9865895Syz147064 
9875895Syz147064 dladm_status_t
9888453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9898453SAnurag.Maskey@Sun.COM     boolean_t any_media)
9905895Syz147064 {
9916916Sartem 	datalink_media_t	dmedia;
9926916Sartem 	uint32_t		media;
9936916Sartem 
9946916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
9956916Sartem 
9965895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
9978453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
9988453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
9998453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
10008453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
10018453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
10026916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
10038453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, NULL,
10048453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
10053448Sdh155122 	}
10063448Sdh155122 	return (DLADM_STATUS_OK);
10073147Sxc151355 }
10083147Sxc151355 
10095903Ssowmini /* ARGSUSED */
10105895Syz147064 static dladm_status_t
10118453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
10128275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
10138275SEric Cheng     uint_t flags, uint_t *perm_flags)
10143147Sxc151355 {
10158275SEric Cheng 	char			zone_name[ZONENAME_MAX];
10168275SEric Cheng 	zoneid_t		zid;
10178275SEric Cheng 	dladm_status_t		status;
10188275SEric Cheng 	char			*cp;
10197342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
10203147Sxc151355 
10216512Ssowmini 	if (flags != 0)
10226512Ssowmini 		return (DLADM_STATUS_NOTSUP);
10236512Ssowmini 
10248453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
10258275SEric Cheng 	    &status, perm_flags);
10265895Syz147064 	if (status != DLADM_STATUS_OK)
10273448Sdh155122 		return (status);
10283448Sdh155122 
10297342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
10307342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
10317342SAruna.Ramakrishna@Sun.COM 	free(dip);
10327342SAruna.Ramakrishna@Sun.COM 
10335895Syz147064 	*val_cnt = 1;
10345895Syz147064 	if (zid != GLOBAL_ZONEID) {
10358118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
10365895Syz147064 			return (dladm_errno2status(errno));
10378118SVasumathi.Sundaram@Sun.COM 		}
10383147Sxc151355 
10395895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
10403147Sxc151355 	} else {
10415895Syz147064 		*prop_val[0] = '\0';
10423147Sxc151355 	}
10433147Sxc151355 
10443448Sdh155122 	return (DLADM_STATUS_OK);
10453448Sdh155122 }
10463448Sdh155122 
10473448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
10483448Sdh155122 
10493448Sdh155122 static int
10503448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
10513448Sdh155122 {
10523448Sdh155122 	char			root[MAXPATHLEN];
10533448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
10543448Sdh155122 	void			*dlhandle;
10553448Sdh155122 	void			*sym;
10563448Sdh155122 	int			ret;
10573448Sdh155122 
10583448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
10593448Sdh155122 		return (-1);
10603448Sdh155122 
10613448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
10623448Sdh155122 		(void) dlclose(dlhandle);
10633448Sdh155122 		return (-1);
10643448Sdh155122 	}
10653448Sdh155122 
10663448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
10673448Sdh155122 
10683448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
10693448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
10703448Sdh155122 	(void) dlclose(dlhandle);
10713448Sdh155122 	return (ret);
10723448Sdh155122 }
10733448Sdh155122 
10743448Sdh155122 static dladm_status_t
10758453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
10768453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
10773448Sdh155122 {
10783448Sdh155122 	char		path[MAXPATHLEN];
10795895Syz147064 	char		name[MAXLINKNAMELEN];
10803448Sdh155122 	di_prof_t	prof = NULL;
10813448Sdh155122 	char		zone_name[ZONENAME_MAX];
10823448Sdh155122 	dladm_status_t	status;
10835895Syz147064 	int		ret;
10843448Sdh155122 
10853448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
10863448Sdh155122 		return (dladm_errno2status(errno));
10873448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
10883448Sdh155122 		return (dladm_errno2status(errno));
10893448Sdh155122 	if (di_prof_init(path, &prof) != 0)
10903448Sdh155122 		return (dladm_errno2status(errno));
10913448Sdh155122 
10928453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
10935895Syz147064 	if (status != DLADM_STATUS_OK)
10945895Syz147064 		goto cleanup;
10955895Syz147064 
10965895Syz147064 	if (add)
10975895Syz147064 		ret = di_prof_add_dev(prof, name);
10985895Syz147064 	else
10995895Syz147064 		ret = di_prof_add_exclude(prof, name);
11005895Syz147064 
11015895Syz147064 	if (ret != 0) {
11023448Sdh155122 		status = dladm_errno2status(errno);
11033448Sdh155122 		goto cleanup;
11043448Sdh155122 	}
11053448Sdh155122 
11063448Sdh155122 	if (di_prof_commit(prof) != 0)
11073448Sdh155122 		status = dladm_errno2status(errno);
11083448Sdh155122 cleanup:
11093448Sdh155122 	if (prof)
11103448Sdh155122 		di_prof_fini(prof);
11113448Sdh155122 
11123448Sdh155122 	return (status);
11133448Sdh155122 }
11143448Sdh155122 
11155903Ssowmini /* ARGSUSED */
11163448Sdh155122 static dladm_status_t
11178453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
11188453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
11193448Sdh155122 {
11208275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
11218275SEric Cheng 	zoneid_t		zid_old, zid_new;
11228275SEric Cheng 	char			link[MAXLINKNAMELEN];
11238275SEric Cheng 	char			*cp;
11247342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
11257342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
11263448Sdh155122 
11273448Sdh155122 	if (val_cnt != 1)
11283448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
11293448Sdh155122 
11307342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
11317342SAruna.Ramakrishna@Sun.COM 
11328453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
11338275SEric Cheng 	    &status, NULL);
11348275SEric Cheng 	if (status != DLADM_STATUS_OK)
11358275SEric Cheng 		return (status);
11368275SEric Cheng 
11378275SEric Cheng 	cp = dip->pr_val;
11388275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
11398275SEric Cheng 	free(dip);
11407342SAruna.Ramakrishna@Sun.COM 
11417342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
11427342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
11433448Sdh155122 
11443448Sdh155122 	/* Do nothing if setting to current value */
11453448Sdh155122 	if (zid_new == zid_old)
11465895Syz147064 		return (status);
11475895Syz147064 
11485895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
11495895Syz147064 		/*
11505895Syz147064 		 * If the new zoneid is the global zone, we could destroy
11515895Syz147064 		 * the link (in the case of an implicitly-created VLAN) as a
11527342SAruna.Ramakrishna@Sun.COM 		 * result of setting the zoneid. In that case, we defer the
11537342SAruna.Ramakrishna@Sun.COM 		 * operation to the end of this function to avoid recreating
11547342SAruna.Ramakrishna@Sun.COM 		 * the VLAN and getting a different linkid during the rollback
11557342SAruna.Ramakrishna@Sun.COM 		 * if other operation fails.
11565895Syz147064 		 *
11577342SAruna.Ramakrishna@Sun.COM 		 * Otherwise, this operation will hold a reference to the
11585895Syz147064 		 * link and prevent a link renaming, so we need to do it
11595895Syz147064 		 * before other operations.
11605895Syz147064 		 */
11618453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
11628453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
11635895Syz147064 		if (status != DLADM_STATUS_OK)
11645895Syz147064 			return (status);
11655895Syz147064 	}
11665895Syz147064 
11673448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
11685895Syz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
11693448Sdh155122 		    errno != ENXIO) {
11703448Sdh155122 			status = dladm_errno2status(errno);
11713448Sdh155122 			goto rollback1;
11723448Sdh155122 		}
11733448Sdh155122 
11745895Syz147064 		/*
11755895Syz147064 		 * It is okay to fail to update the /dev entry (some
11765895Syz147064 		 * vanity-named links do not have a /dev entry).
11775895Syz147064 		 */
11788453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
11798453SAnurag.Maskey@Sun.COM 		    B_FALSE);
11805895Syz147064 	}
11815895Syz147064 
11825895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
11835895Syz147064 		if (zone_add_datalink(zid_new, link) != 0) {
11845895Syz147064 			status = dladm_errno2status(errno);
11855895Syz147064 			goto rollback2;
11865895Syz147064 		}
11875895Syz147064 
11888453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
11895895Syz147064 	} else {
11908453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
11918453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
11923448Sdh155122 		if (status != DLADM_STATUS_OK)
11933448Sdh155122 			goto rollback2;
11943448Sdh155122 	}
11953448Sdh155122 
11963448Sdh155122 	return (DLADM_STATUS_OK);
11973448Sdh155122 
11983448Sdh155122 rollback2:
11993448Sdh155122 	if (zid_old != GLOBAL_ZONEID)
12008453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid, B_TRUE);
12015895Syz147064 	if (zid_old != GLOBAL_ZONEID)
12025895Syz147064 		(void) zone_add_datalink(zid_old, link);
12033448Sdh155122 rollback1:
12047342SAruna.Ramakrishna@Sun.COM 	if (zid_new != GLOBAL_ZONEID) {
12057342SAruna.Ramakrishna@Sun.COM 		dzp->diz_zid = zid_old;
12068453SAnurag.Maskey@Sun.COM 		(void) i_dladm_set_public_prop(handle, pdp, linkid, vdp,
12078453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
12087342SAruna.Ramakrishna@Sun.COM 	}
12097342SAruna.Ramakrishna@Sun.COM 
12103448Sdh155122 	return (status);
12113448Sdh155122 }
12123448Sdh155122 
12133448Sdh155122 /* ARGSUSED */
12143448Sdh155122 static dladm_status_t
12158453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12168453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
12173448Sdh155122 {
12187342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
12197342SAruna.Ramakrishna@Sun.COM 	char		linkname[MAXLINKNAMELEN];
12207342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
12217342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
12227342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
12233448Sdh155122 
12243448Sdh155122 	if (val_cnt != 1)
12253448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
12263448Sdh155122 
12277342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
12287342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
12297342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
12303448Sdh155122 
12318453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
12328275SEric Cheng 	    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
12338275SEric Cheng 		goto done;
12347342SAruna.Ramakrishna@Sun.COM 	}
12357342SAruna.Ramakrishna@Sun.COM 
12368275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
12377342SAruna.Ramakrishna@Sun.COM 	if (strlen(linkname) > MAXLINKNAMELEN) {
12387342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
12397342SAruna.Ramakrishna@Sun.COM 		goto done;
12407342SAruna.Ramakrishna@Sun.COM 	}
12417342SAruna.Ramakrishna@Sun.COM 
12427342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
12437342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
12447342SAruna.Ramakrishna@Sun.COM 		goto done;
12457342SAruna.Ramakrishna@Sun.COM 	}
12467342SAruna.Ramakrishna@Sun.COM 
12477342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
12483448Sdh155122 		ushort_t	flags;
12493448Sdh155122 
12507342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
12513448Sdh155122 		    sizeof (flags)) < 0) {
12527342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
12537342SAruna.Ramakrishna@Sun.COM 			goto done;
12543448Sdh155122 		}
12553448Sdh155122 
12563448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
12577342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
12587342SAruna.Ramakrishna@Sun.COM 			goto done;
12593448Sdh155122 		}
12603448Sdh155122 	}
12613448Sdh155122 
12627342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
12637342SAruna.Ramakrishna@Sun.COM 
12647342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
12657342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
12667342SAruna.Ramakrishna@Sun.COM 
12677342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
12685895Syz147064 	return (DLADM_STATUS_OK);
12697342SAruna.Ramakrishna@Sun.COM done:
12707342SAruna.Ramakrishna@Sun.COM 	free(dzp);
12717342SAruna.Ramakrishna@Sun.COM 	return (status);
12725895Syz147064 }
12735895Syz147064 
12745903Ssowmini /* ARGSUSED */
12755895Syz147064 static dladm_status_t
12768460SArtem.Kachitchkin@Sun.COM i_dladm_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12778275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12788275SEric Cheng     uint_t flags, uint_t *perm_flags)
12798275SEric Cheng {
12808275SEric Cheng 	dld_ioc_macprop_t	*dip;
12818275SEric Cheng 	mac_resource_props_t	mrp;
12828275SEric Cheng 	dladm_status_t		status;
12838275SEric Cheng 
12848453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
12858275SEric Cheng 	    &status, perm_flags);
12868275SEric Cheng 	if (dip == NULL)
12878275SEric Cheng 		return (status);
12888275SEric Cheng 
12898275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
12908275SEric Cheng 	free(dip);
12918275SEric Cheng 
12928275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
12938275SEric Cheng 		(*prop_val)[0] = '\0';
12948275SEric Cheng 	} else {
12958275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
12968275SEric Cheng 	}
12978275SEric Cheng 	*val_cnt = 1;
12988275SEric Cheng 	return (DLADM_STATUS_OK);
12998275SEric Cheng }
13008275SEric Cheng 
13018275SEric Cheng /* ARGSUSED */
13028275SEric Cheng static dladm_status_t
13038453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13048453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
13058275SEric Cheng {
13068275SEric Cheng 	uint64_t	*maxbw;
13078275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
13088275SEric Cheng 
13098275SEric Cheng 	if (val_cnt != 1)
13108275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
13118275SEric Cheng 
13128275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
13138275SEric Cheng 	if (maxbw == NULL)
13148275SEric Cheng 		return (DLADM_STATUS_NOMEM);
13158275SEric Cheng 
13168275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
13178275SEric Cheng 	if (status != DLADM_STATUS_OK) {
13188275SEric Cheng 		free(maxbw);
13198275SEric Cheng 		return (status);
13208275SEric Cheng 	}
13218275SEric Cheng 
13228275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
13238275SEric Cheng 		free(maxbw);
13248275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
13258275SEric Cheng 	}
13268275SEric Cheng 
13278275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
13288275SEric Cheng 	return (DLADM_STATUS_OK);
13298275SEric Cheng }
13308275SEric Cheng 
13318275SEric Cheng /* ARGSUSED */
13328275SEric Cheng dladm_status_t
13338275SEric Cheng do_extract_maxbw(val_desc_t *vdp, void *arg, uint_t cnt)
13348275SEric Cheng {
13358275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
13368275SEric Cheng 
13378275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
13388275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
13398275SEric Cheng 
13408275SEric Cheng 	return (DLADM_STATUS_OK);
13418275SEric Cheng }
13428275SEric Cheng 
13438275SEric Cheng /* ARGSUSED */
13448275SEric Cheng static dladm_status_t
13458460SArtem.Kachitchkin@Sun.COM i_dladm_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13468275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
13478275SEric Cheng     uint_t flags, uint_t *perm_flags)
13488275SEric Cheng {
13498275SEric Cheng 	dld_ioc_macprop_t	*dip;
13508275SEric Cheng 	mac_resource_props_t	mrp;
13518275SEric Cheng 	int			i;
13528275SEric Cheng 	uint32_t		ncpus;
13538275SEric Cheng 	uchar_t			*cp;
13548275SEric Cheng 	dladm_status_t		status;
13558275SEric Cheng 
13568453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13578275SEric Cheng 	    &status, perm_flags);
13588275SEric Cheng 	if (dip == NULL)
13598275SEric Cheng 		return (status);
13608275SEric Cheng 
13618275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
13628275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
13638275SEric Cheng 	free(dip);
13648275SEric Cheng 
13658275SEric Cheng 	ncpus = mrp.mrp_ncpus;
13668275SEric Cheng 
13678275SEric Cheng 	if (ncpus > *val_cnt)
13688275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
13698275SEric Cheng 
13708275SEric Cheng 	if (ncpus == 0) {
13718275SEric Cheng 		(*prop_val)[0] = '\0';
13728275SEric Cheng 		*val_cnt = 1;
13738275SEric Cheng 		return (DLADM_STATUS_OK);
13748275SEric Cheng 	}
13758275SEric Cheng 
13768275SEric Cheng 	*val_cnt = ncpus;
13778275SEric Cheng 	for (i = 0; i < ncpus; i++) {
13788275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
13798275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
13808275SEric Cheng 	}
13818275SEric Cheng 	return (DLADM_STATUS_OK);
13828275SEric Cheng }
13838275SEric Cheng 
13848275SEric Cheng /* ARGSUSED */
13858275SEric Cheng static dladm_status_t
13868453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13878453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13888275SEric Cheng {
13898275SEric Cheng 	mac_resource_props_t	mrp;
13908275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
13918275SEric Cheng 	dld_ioc_macprop_t	*dip;
13928275SEric Cheng 
13938275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
13948275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
13958275SEric Cheng 	    flags, &status);
13968275SEric Cheng 
13978275SEric Cheng 	if (dip == NULL)
13988275SEric Cheng 		return (status);
13998275SEric Cheng 
14008275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
14018275SEric Cheng 		switch (dip->pr_num) {
14028275SEric Cheng 		case MAC_PROP_MAXBW:
14038275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
14048275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
14058275SEric Cheng 			break;
14068275SEric Cheng 		case MAC_PROP_PRIO:
14078275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
14088275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
14098275SEric Cheng 			break;
14108275SEric Cheng 		default:
14118275SEric Cheng 			free(dip);
14128275SEric Cheng 			return (DLADM_STATUS_BADARG);
14138275SEric Cheng 		}
14148275SEric Cheng 	} else {
14158275SEric Cheng 		switch (dip->pr_num) {
14168275SEric Cheng 		case MAC_PROP_MAXBW:
14178275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
14188275SEric Cheng 			    sizeof (uint64_t));
14198275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
14208275SEric Cheng 			break;
14218275SEric Cheng 		case MAC_PROP_PRIO:
14228275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
14238275SEric Cheng 			    sizeof (mac_priority_level_t));
14248275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
14258275SEric Cheng 			break;
14268275SEric Cheng 		default:
14278275SEric Cheng 			free(dip);
14288275SEric Cheng 			return (DLADM_STATUS_BADARG);
14298275SEric Cheng 		}
14308275SEric Cheng 	}
14318275SEric Cheng 
14328275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
14338453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
14348275SEric Cheng 	free(dip);
14358275SEric Cheng 	return (status);
14368275SEric Cheng }
14378275SEric Cheng 
14388275SEric Cheng /* ARGSUSED */
14398275SEric Cheng static dladm_status_t
14408453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14418453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
14428275SEric Cheng {
14438275SEric Cheng 	mac_resource_props_t	mrp;
14448275SEric Cheng 	dladm_status_t		status;
14458275SEric Cheng 	dld_ioc_macprop_t	*dip;
14468275SEric Cheng 	datalink_class_t	class;
14478275SEric Cheng 
14488275SEric Cheng 	/*
14498275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
14508275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
14518275SEric Cheng 	 * the phys_info test only on physical links.
14528275SEric Cheng 	 */
14538453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
14548275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
14558275SEric Cheng 		return (status);
14568275SEric Cheng 	}
14578275SEric Cheng 
14588275SEric Cheng 	/*
14598275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
14608275SEric Cheng 	 * if possible when the setup is complete in MAC.
14618275SEric Cheng 	 */
14628275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
14638275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
14648275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
14658275SEric Cheng 		mac_resource_props_t	*vmrp;
14668275SEric Cheng 
14678275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
14688275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
14698275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
14708275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
14718275SEric Cheng 		}
14728275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
14738275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
14748275SEric Cheng 		mrp.mrp_intr_cpu = -1;
14758275SEric Cheng 	}
14768275SEric Cheng 
14778275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
14788275SEric Cheng 	    flags, &status);
14798275SEric Cheng 	if (dip == NULL)
14808275SEric Cheng 		return (status);
14818275SEric Cheng 
14828275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
14838453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
14848275SEric Cheng 	free(dip);
14858275SEric Cheng 	return (status);
14868275SEric Cheng }
14878275SEric Cheng 
14888275SEric Cheng /* ARGSUSED */
14898275SEric Cheng static dladm_status_t
14908453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14918453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14928275SEric Cheng {
14938275SEric Cheng 	uint32_t		cpuid;
14948275SEric Cheng 	int			i, j, rc;
14958275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
14968275SEric Cheng 	mac_resource_props_t	*mrp;
14978275SEric Cheng 
14988275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
14998275SEric Cheng 	if (mrp == NULL)
15008275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15018275SEric Cheng 
15028275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
15038275SEric Cheng 		errno = 0;
15048275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
15058275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
15068275SEric Cheng 			free(mrp);
15078275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
15088275SEric Cheng 		}
15098275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
15108275SEric Cheng 		if (rc < 1) {
15118275SEric Cheng 			free(mrp);
15128275SEric Cheng 			return (DLADM_STATUS_CPUERR);
15138275SEric Cheng 		}
15148275SEric Cheng 		if (rc != P_ONLINE) {
15158275SEric Cheng 			free(mrp);
15168275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
15178275SEric Cheng 		}
15188275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
15198275SEric Cheng 	}
15208275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
15218275SEric Cheng 
15228275SEric Cheng 	/* Check for duplicates */
15238275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
15248275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
15258275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
15268275SEric Cheng 				free(mrp);
15278275SEric Cheng 				return (DLADM_STATUS_BADARG);
15288275SEric Cheng 			}
15298275SEric Cheng 		}
15308275SEric Cheng 	}
15318275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
15328275SEric Cheng 
15338275SEric Cheng 	return (DLADM_STATUS_OK);
15348275SEric Cheng }
15358275SEric Cheng 
15368275SEric Cheng /* ARGSUSED */
15378275SEric Cheng dladm_status_t
15388275SEric Cheng do_extract_cpus(val_desc_t *vdp, void *arg, uint_t cnt)
15398275SEric Cheng {
15408275SEric Cheng 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
15418275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
15428275SEric Cheng 	int			i;
15438275SEric Cheng 
15448275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
15458275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
15468275SEric Cheng 	}
15478275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
15488275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
15498275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
15509055SMichael.Lim@Sun.COM 	mrp->mrp_intr_cpu = -1;
15518275SEric Cheng 
15528275SEric Cheng 	return (DLADM_STATUS_OK);
15538275SEric Cheng }
15548275SEric Cheng 
15558275SEric Cheng /* ARGSUSED */
15568275SEric Cheng static dladm_status_t
15578460SArtem.Kachitchkin@Sun.COM i_dladm_priority_get(dladm_handle_t handle, prop_desc_t *pdp,
15588460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
15598460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
15608275SEric Cheng {
15618275SEric Cheng 	dld_ioc_macprop_t	*dip;
15628275SEric Cheng 	mac_resource_props_t	mrp;
15638275SEric Cheng 	mac_priority_level_t	pri;
15648275SEric Cheng 	dladm_status_t		status;
15658275SEric Cheng 
15668453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15678275SEric Cheng 	    &status, perm_flags);
15688275SEric Cheng 	if (dip == NULL)
15698275SEric Cheng 		return (status);
15708275SEric Cheng 
15718275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
15728275SEric Cheng 	free(dip);
15738275SEric Cheng 
15748275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
15758275SEric Cheng 	    mrp.mrp_priority;
15768275SEric Cheng 
15778275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
15788275SEric Cheng 	*val_cnt = 1;
15798275SEric Cheng 	return (DLADM_STATUS_OK);
15808275SEric Cheng }
15818275SEric Cheng 
15828275SEric Cheng /* ARGSUSED */
15838275SEric Cheng static dladm_status_t
15848453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15858453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
15868275SEric Cheng {
15878275SEric Cheng 	mac_priority_level_t	*pri;
15888275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15898275SEric Cheng 
15908275SEric Cheng 	if (val_cnt != 1)
15918275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15928275SEric Cheng 
15938275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
15948275SEric Cheng 	if (pri == NULL)
15958275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15968275SEric Cheng 
15978275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
15988275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15998275SEric Cheng 		free(pri);
16008275SEric Cheng 		return (status);
16018275SEric Cheng 	}
16028275SEric Cheng 
16038275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
16048275SEric Cheng 		free(pri);
16058275SEric Cheng 		return (DLADM_STATUS_BADVAL);
16068275SEric Cheng 	}
16078275SEric Cheng 
16088275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
16098275SEric Cheng 	return (DLADM_STATUS_OK);
16108275SEric Cheng }
16118275SEric Cheng 
16128275SEric Cheng /* ARGSUSED */
16138275SEric Cheng dladm_status_t
16148275SEric Cheng do_extract_priority(val_desc_t *vdp, void *arg, uint_t cnt)
16158275SEric Cheng {
16168275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
16178275SEric Cheng 
16188275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
16198275SEric Cheng 	    sizeof (mac_priority_level_t));
16208275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
16218275SEric Cheng 
16228275SEric Cheng 	return (DLADM_STATUS_OK);
16238275SEric Cheng }
16248275SEric Cheng 
16258275SEric Cheng /* ARGSUSED */
16268275SEric Cheng static dladm_status_t
16278453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16288275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
16298275SEric Cheng     uint_t flags, uint_t *perm_flags)
16305895Syz147064 {
16317342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
16327342SAruna.Ramakrishna@Sun.COM 	int		i, len;
16337342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
16347342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
16355895Syz147064 
16366789Sam223141 	if (flags & MAC_PROP_DEFAULT)
16377776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
16386512Ssowmini 
16395895Syz147064 	*val_cnt = 1;
16408453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
16418275SEric Cheng 	    &status, perm_flags);
16427342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
16435895Syz147064 		(*prop_val)[0] = '\0';
16448275SEric Cheng 		return (DLADM_STATUS_OK);
16455895Syz147064 	}
16467342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
16475895Syz147064 
16487342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
16495895Syz147064 		if (i != 0) {
16505895Syz147064 			(void) snprintf(*prop_val + len,
16515895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
16525895Syz147064 			len += 1;
16535895Syz147064 		}
16545895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
16557342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
16567342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
16577342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
16585895Syz147064 			(void) snprintf(*prop_val + len,
16595895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
16605895Syz147064 			    AP_ANCHOR);
16615895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
16625895Syz147064 		}
16635895Syz147064 	}
16647342SAruna.Ramakrishna@Sun.COM 	free(dip);
16655895Syz147064 done:
16665895Syz147064 	return (DLADM_STATUS_OK);
16675895Syz147064 }
16685895Syz147064 
16695895Syz147064 /*
16705895Syz147064  * Add the specified module to the dlautopush structure; returns a
16715895Syz147064  * DLADM_STATUS_* code.
16725895Syz147064  */
16735895Syz147064 dladm_status_t
16745895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
16755895Syz147064 {
16765895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
16775895Syz147064 		return (DLADM_STATUS_BADVAL);
16785895Syz147064 
16795895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
16805895Syz147064 		/*
16815895Syz147064 		 * We don't allow multiple anchors, and the anchor must
16825895Syz147064 		 * be after at least one module.
16835895Syz147064 		 */
16845895Syz147064 		if (dlap->dap_anchor != 0)
16855895Syz147064 			return (DLADM_STATUS_BADVAL);
16865895Syz147064 		if (dlap->dap_npush == 0)
16875895Syz147064 			return (DLADM_STATUS_BADVAL);
16885895Syz147064 
16895895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
16905895Syz147064 		return (DLADM_STATUS_OK);
16915895Syz147064 	}
16928957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
16935895Syz147064 		return (DLADM_STATUS_BADVALCNT);
16945895Syz147064 
16955895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
16965895Syz147064 	    FMNAMESZ + 1);
16975895Syz147064 
16985895Syz147064 	return (DLADM_STATUS_OK);
16995895Syz147064 }
17005895Syz147064 
17015895Syz147064 /*
17025895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
17035895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
17045895Syz147064  * latter is used in the autopush(1M) file.
17055895Syz147064  */
17065895Syz147064 /* ARGSUSED */
17075895Syz147064 static dladm_status_t
17088453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17098453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17105895Syz147064 {
17115895Syz147064 	char			*module;
17125895Syz147064 	struct dlautopush	*dlap;
17135895Syz147064 	dladm_status_t		status;
17145895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
17155895Syz147064 	char			delimiters[4];
17165895Syz147064 
17175895Syz147064 	if (val_cnt != 1)
17185895Syz147064 		return (DLADM_STATUS_BADVALCNT);
17195895Syz147064 
17207342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
17217342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
17227342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
17237342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
17243448Sdh155122 
17257342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
17267342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
17277342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
17287342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
17297342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
17307342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
17317342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
17327342SAruna.Ramakrishna@Sun.COM 				return (status);
17337342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
17347342SAruna.Ramakrishna@Sun.COM 		}
17357342SAruna.Ramakrishna@Sun.COM 
17367342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
17377342SAruna.Ramakrishna@Sun.COM 	} else {
17387342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
17395895Syz147064 	}
17403448Sdh155122 	return (DLADM_STATUS_OK);
17413448Sdh155122 }
17423448Sdh155122 
17437663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
17447663SSowmini.Varadhan@Sun.COM 
17455903Ssowmini /* ARGSUSED */
17463448Sdh155122 static dladm_status_t
17478453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
17488453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
17498453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
17503448Sdh155122 {
17515895Syz147064 	wl_rates_t	*wrp;
17525895Syz147064 	uint_t		i;
17535895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
17545895Syz147064 
17557663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
17567663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
17577663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
17585895Syz147064 
17598453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
17608453SAnurag.Maskey@Sun.COM 	    B_FALSE);
17615895Syz147064 	if (status != DLADM_STATUS_OK)
17625895Syz147064 		goto done;
17635895Syz147064 
17645895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
17655895Syz147064 		status = DLADM_STATUS_TOOSMALL;
17665895Syz147064 		goto done;
17675895Syz147064 	}
17685895Syz147064 
17695895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
17705895Syz147064 		prop_val[0][0] = '\0';
17715895Syz147064 		*val_cnt = 1;
17725895Syz147064 		goto done;
17735895Syz147064 	}
17745895Syz147064 
17755895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
17765895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
17775895Syz147064 		    wrp->wl_rates_rates[i] % 2,
17785895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
17795895Syz147064 	}
17805895Syz147064 	*val_cnt = wrp->wl_rates_num;
17818275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
17823448Sdh155122 
17835895Syz147064 done:
17847663SSowmini.Varadhan@Sun.COM 	free(wrp);
17855895Syz147064 	return (status);
17865895Syz147064 }
17875895Syz147064 
17885895Syz147064 static dladm_status_t
17898453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17908275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
17918275SEric Cheng     uint_t flags, uint_t *perm_flags)
17925895Syz147064 {
17938118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
17948453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
17958275SEric Cheng 		    val_cnt, flags, perm_flags));
17968118SVasumathi.Sundaram@Sun.COM 	}
17975960Ssowmini 
17988453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
17998275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
18005895Syz147064 }
18015895Syz147064 
18026512Ssowmini /* ARGSUSED */
18035895Syz147064 static dladm_status_t
18048453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18058275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
18068275SEric Cheng     uint_t flags, uint_t *perm_flags)
18075895Syz147064 {
18085960Ssowmini 	switch (media) {
18095960Ssowmini 	case DL_ETHER:
18106512Ssowmini 		/*
18116512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
18126512Ssowmini 		 * links can have a speed of 5.5 Gbps.
18136512Ssowmini 		 */
18146512Ssowmini 		return (DLADM_STATUS_NOTSUP);
18155960Ssowmini 
18165960Ssowmini 	case DL_WIFI:
18178453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
18188453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
18195960Ssowmini 	default:
18205960Ssowmini 		return (DLADM_STATUS_BADARG);
18215960Ssowmini 	}
18225895Syz147064 }
18235895Syz147064 
18245895Syz147064 static dladm_status_t
18258453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
18268453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
18275895Syz147064 {
18285895Syz147064 	int		i;
18295895Syz147064 	uint_t		len;
18305895Syz147064 	wl_rates_t	*wrp;
18315895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
18325895Syz147064 
18337663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
18347663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
18355895Syz147064 		return (DLADM_STATUS_NOMEM);
18365895Syz147064 
18377663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
18385895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
18395895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
18405895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
18415895Syz147064 
18425895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
18435895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
18448453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
18458453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
18465895Syz147064 
18477663SSowmini.Varadhan@Sun.COM 	free(wrp);
18485895Syz147064 	return (status);
18495895Syz147064 }
18503448Sdh155122 
18515903Ssowmini /* ARGSUSED */
18525895Syz147064 static dladm_status_t
18538453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18545960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
18555895Syz147064 {
18565895Syz147064 	dladm_wlan_rates_t	rates;
18575895Syz147064 	dladm_status_t		status;
18585895Syz147064 
18595960Ssowmini 	/*
18605960Ssowmini 	 * can currently set rate on WIFI links only.
18615960Ssowmini 	 */
18625960Ssowmini 	if (media != DL_WIFI)
18635960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
18645960Ssowmini 
18655895Syz147064 	if (val_cnt != 1)
18665895Syz147064 		return (DLADM_STATUS_BADVALCNT);
18675895Syz147064 
18685895Syz147064 	rates.wr_cnt = 1;
18695895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
18705895Syz147064 
18718453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
18725895Syz147064 
18735895Syz147064 done:
18745895Syz147064 	return (status);
18755895Syz147064 }
18763448Sdh155122 
18775895Syz147064 /* ARGSUSED */
18785895Syz147064 static dladm_status_t
18798453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18808453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
18815895Syz147064 {
18825895Syz147064 	int		i;
18835895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
18845895Syz147064 	char		*buf, **modval;
18855895Syz147064 	dladm_status_t	status;
18868118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
18875895Syz147064 
18885895Syz147064 	if (val_cnt != 1)
18895895Syz147064 		return (DLADM_STATUS_BADVALCNT);
18905895Syz147064 
18915895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
18925895Syz147064 	    MAX_SUPPORT_RATES);
18935895Syz147064 	if (buf == NULL) {
18945895Syz147064 		status = DLADM_STATUS_NOMEM;
18955895Syz147064 		goto done;
18965895Syz147064 	}
18973448Sdh155122 
18985895Syz147064 	modval = (char **)(void *)buf;
18995895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
19005895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
19015895Syz147064 		    i * DLADM_STRSIZE;
19025895Syz147064 	}
19035895Syz147064 
19048453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
19058453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
19065895Syz147064 	if (status != DLADM_STATUS_OK)
19075895Syz147064 		goto done;
19085895Syz147064 
19095895Syz147064 	for (i = 0; i < modval_cnt; i++) {
19105895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
19115903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
19125903Ssowmini 			    (atof(*prop_val) * 2);
19135895Syz147064 			status = DLADM_STATUS_OK;
19143448Sdh155122 			break;
19153448Sdh155122 		}
19165895Syz147064 	}
19175895Syz147064 	if (i == modval_cnt)
19185895Syz147064 		status = DLADM_STATUS_BADVAL;
19195895Syz147064 done:
19205895Syz147064 	free(buf);
19215895Syz147064 	return (status);
19225895Syz147064 }
19235895Syz147064 
19245895Syz147064 static dladm_status_t
19258453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
19268453SAnurag.Maskey@Sun.COM     int buflen)
19275895Syz147064 {
19288453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
19297663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
19305895Syz147064 }
19315895Syz147064 
19325903Ssowmini /* ARGSUSED */
19335895Syz147064 static dladm_status_t
19348453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
19358453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
19368453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
19375895Syz147064 {
19385895Syz147064 	uint32_t	channel;
19397663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
19405895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
19417663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
19425895Syz147064 
19438453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
19447663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
19455895Syz147064 		goto done;
19465895Syz147064 
19477663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
19487663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
19495895Syz147064 		status = DLADM_STATUS_NOTFOUND;
19505895Syz147064 		goto done;
19515895Syz147064 	}
19525895Syz147064 
19535895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
19545895Syz147064 	*val_cnt = 1;
19558275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
19565895Syz147064 done:
19575895Syz147064 	return (status);
19585895Syz147064 }
19595895Syz147064 
19605895Syz147064 static dladm_status_t
19618453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
19628453SAnurag.Maskey@Sun.COM     int buflen)
19635895Syz147064 {
19648453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
19657663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
19665895Syz147064 }
19675895Syz147064 
19685903Ssowmini /* ARGSUSED */
19695895Syz147064 static dladm_status_t
19708453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
19718453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
19728453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
19735895Syz147064 {
19747663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
19755895Syz147064 	const char	*s;
19767663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
19775895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
19785895Syz147064 
19798453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
19807663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
19815895Syz147064 		goto done;
19825895Syz147064 
19837663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
19847663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
19855895Syz147064 	case WL_PM_AM:
19865895Syz147064 		s = "off";
19875895Syz147064 		break;
19885895Syz147064 	case WL_PM_MPS:
19895895Syz147064 		s = "max";
19905895Syz147064 		break;
19915895Syz147064 	case WL_PM_FAST:
19925895Syz147064 		s = "fast";
19933448Sdh155122 		break;
19943448Sdh155122 	default:
19955895Syz147064 		status = DLADM_STATUS_NOTFOUND;
19965895Syz147064 		goto done;
19975895Syz147064 	}
19985895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
19995895Syz147064 	*val_cnt = 1;
20008275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
20015895Syz147064 done:
20025895Syz147064 	return (status);
20035895Syz147064 }
20045895Syz147064 
20055895Syz147064 static dladm_status_t
20068453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
20078453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
20085895Syz147064 {
20095895Syz147064 	wl_ps_mode_t    ps_mode;
20105895Syz147064 
20115895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
20125895Syz147064 
20135895Syz147064 	switch (*pm) {
20145895Syz147064 	case DLADM_WLAN_PM_OFF:
20155895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
20163448Sdh155122 		break;
20175895Syz147064 	case DLADM_WLAN_PM_MAX:
20185895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
20195895Syz147064 		break;
20205895Syz147064 	case DLADM_WLAN_PM_FAST:
20215895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
20225895Syz147064 		break;
20235895Syz147064 	default:
20245895Syz147064 		return (DLADM_STATUS_NOTSUP);
20253448Sdh155122 	}
20268453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
20278453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
20285895Syz147064 }
20295895Syz147064 
20305895Syz147064 /* ARGSUSED */
20315895Syz147064 static dladm_status_t
20328453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
20338453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
20348453SAnurag.Maskey@Sun.COM     datalink_media_t media)
20355895Syz147064 {
20365895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
20375895Syz147064 	dladm_status_t status;
20385895Syz147064 
20395895Syz147064 	if (val_cnt != 1)
20405895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20415895Syz147064 
20428453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
20433448Sdh155122 
20443448Sdh155122 	return (status);
20453448Sdh155122 }
20463448Sdh155122 
20473448Sdh155122 static dladm_status_t
20488453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
20493448Sdh155122 {
20508453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
20518453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
20525895Syz147064 }
20533448Sdh155122 
20545903Ssowmini /* ARGSUSED */
20555895Syz147064 static dladm_status_t
20568453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20578275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
20588275SEric Cheng     uint_t flags, uint_t *perm_flags)
20595895Syz147064 {
20605895Syz147064 	wl_radio_t	radio;
20615895Syz147064 	const char	*s;
20627663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
20635895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
20643448Sdh155122 
20658453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
20667663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
20675895Syz147064 		goto done;
20683448Sdh155122 
20697663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
20705895Syz147064 	switch (radio) {
20715895Syz147064 	case B_TRUE:
20725895Syz147064 		s = "on";
20735895Syz147064 		break;
20745895Syz147064 	case B_FALSE:
20755895Syz147064 		s = "off";
20765895Syz147064 		break;
20775895Syz147064 	default:
20785895Syz147064 		status = DLADM_STATUS_NOTFOUND;
20795895Syz147064 		goto done;
20805895Syz147064 	}
20815895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
20825895Syz147064 	*val_cnt = 1;
20838275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
20845895Syz147064 done:
20853448Sdh155122 	return (status);
20863448Sdh155122 }
20873448Sdh155122 
20883448Sdh155122 static dladm_status_t
20898453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
20908453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
20913448Sdh155122 {
20925895Syz147064 	wl_radio_t r;
20933448Sdh155122 
20945895Syz147064 	switch (*radio) {
20955895Syz147064 	case DLADM_WLAN_RADIO_ON:
20965895Syz147064 		r = B_TRUE;
20975895Syz147064 		break;
20985895Syz147064 	case DLADM_WLAN_RADIO_OFF:
20995895Syz147064 		r = B_FALSE;
21005895Syz147064 		break;
21015895Syz147064 	default:
21025895Syz147064 		return (DLADM_STATUS_NOTSUP);
21035895Syz147064 	}
21048453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
21057663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
21065895Syz147064 }
21073448Sdh155122 
21085895Syz147064 /* ARGSUSED */
21095895Syz147064 static dladm_status_t
21108453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21115960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
21125895Syz147064 {
21135895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
21145895Syz147064 	dladm_status_t status;
21153448Sdh155122 
21165895Syz147064 	if (val_cnt != 1)
21175895Syz147064 		return (DLADM_STATUS_BADVALCNT);
21185895Syz147064 
21198453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
21203448Sdh155122 
21213448Sdh155122 	return (status);
21223448Sdh155122 }
21233448Sdh155122 
21245895Syz147064 static dladm_status_t
21258453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
21268453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
21273448Sdh155122 {
21285895Syz147064 	char		buf[MAXLINELEN];
21295895Syz147064 	int		i;
21305895Syz147064 	dladm_conf_t	conf;
21315895Syz147064 	dladm_status_t	status;
21323448Sdh155122 
21338453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
21345895Syz147064 	if (status != DLADM_STATUS_OK)
21355895Syz147064 		return (status);
21363448Sdh155122 
21375895Syz147064 	/*
21385895Syz147064 	 * reset case.
21395895Syz147064 	 */
21405895Syz147064 	if (val_cnt == 0) {
21418453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
21425895Syz147064 		if (status == DLADM_STATUS_OK)
21438453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
21445895Syz147064 		goto done;
21455895Syz147064 	}
21463448Sdh155122 
21475895Syz147064 	buf[0] = '\0';
21485895Syz147064 	for (i = 0; i < val_cnt; i++) {
21495895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
21505895Syz147064 		if (i != val_cnt - 1)
21515895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
21523448Sdh155122 	}
21533448Sdh155122 
21548453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
21558453SAnurag.Maskey@Sun.COM 	    buf);
21565895Syz147064 	if (status == DLADM_STATUS_OK)
21578453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
21585895Syz147064 
21595895Syz147064 done:
21608453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
21615895Syz147064 	return (status);
21623448Sdh155122 }
21635895Syz147064 
21645895Syz147064 static dladm_status_t
21658453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
21668453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
21675895Syz147064 {
21685895Syz147064 	char		buf[MAXLINELEN], *str;
21695895Syz147064 	uint_t		cnt = 0;
21705895Syz147064 	dladm_conf_t	conf;
21715895Syz147064 	dladm_status_t	status;
21725895Syz147064 
21738453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
21745895Syz147064 	if (status != DLADM_STATUS_OK)
21755895Syz147064 		return (status);
21765895Syz147064 
21778453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
21785895Syz147064 	if (status != DLADM_STATUS_OK)
21795895Syz147064 		goto done;
21805895Syz147064 
21815895Syz147064 	str = strtok(buf, ",");
21825895Syz147064 	while (str != NULL) {
21835895Syz147064 		if (cnt == *val_cntp) {
21845895Syz147064 			status = DLADM_STATUS_TOOSMALL;
21855895Syz147064 			goto done;
21865895Syz147064 		}
21875895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
21885895Syz147064 		str = strtok(NULL, ",");
21895895Syz147064 	}
21905895Syz147064 
21915895Syz147064 	*val_cntp = cnt;
21925895Syz147064 
21935895Syz147064 done:
21948453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
21955895Syz147064 	return (status);
21965895Syz147064 }
21975903Ssowmini 
21988460SArtem.Kachitchkin@Sun.COM /*
21998460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
22008460SArtem.Kachitchkin@Sun.COM  */
22018460SArtem.Kachitchkin@Sun.COM static dladm_status_t
22028460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
22038460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
22048460SArtem.Kachitchkin@Sun.COM {
22058460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
22068460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
22078460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
22088460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
22098460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
22108460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
22118460SArtem.Kachitchkin@Sun.COM 
22128460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
22138460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
22148460SArtem.Kachitchkin@Sun.COM 
22158460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
22168460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
22178460SArtem.Kachitchkin@Sun.COM 		return (status);
22188460SArtem.Kachitchkin@Sun.COM 
22198460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
22208460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
22218460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
22228460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
22238460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
22248460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
22258460SArtem.Kachitchkin@Sun.COM 				break;
22268460SArtem.Kachitchkin@Sun.COM 		}
22278460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
22288460SArtem.Kachitchkin@Sun.COM 	}
22298460SArtem.Kachitchkin@Sun.COM 
22308460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
22318460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
22328460SArtem.Kachitchkin@Sun.COM }
22338460SArtem.Kachitchkin@Sun.COM 
22347663SSowmini.Varadhan@Sun.COM static link_attr_t *
22355903Ssowmini dladm_name2prop(const char *prop_name)
22365903Ssowmini {
22377663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
22385903Ssowmini 
22397663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
22405903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
22415903Ssowmini 			break;
22425903Ssowmini 	}
22435903Ssowmini 	return (p);
22445903Ssowmini }
22455903Ssowmini 
22467663SSowmini.Varadhan@Sun.COM static link_attr_t *
22477663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
22487663SSowmini.Varadhan@Sun.COM {
22497663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
22507663SSowmini.Varadhan@Sun.COM 
22517663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
22527663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
22537663SSowmini.Varadhan@Sun.COM 			break;
22547663SSowmini.Varadhan@Sun.COM 	}
22557663SSowmini.Varadhan@Sun.COM 	return (p);
22567663SSowmini.Varadhan@Sun.COM }
22575903Ssowmini 
22586789Sam223141 static dld_ioc_macprop_t *
22597663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
22607663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
22617663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
22625903Ssowmini {
22635903Ssowmini 	int dsize;
22646789Sam223141 	dld_ioc_macprop_t *dip;
22655903Ssowmini 
22665903Ssowmini 	*status = DLADM_STATUS_OK;
22676789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
22685903Ssowmini 	dip = malloc(dsize);
22695903Ssowmini 	if (dip == NULL) {
22705903Ssowmini 		*status = DLADM_STATUS_NOMEM;
22715903Ssowmini 		return (NULL);
22725903Ssowmini 	}
22735903Ssowmini 	bzero(dip, dsize);
22745903Ssowmini 	dip->pr_valsize = valsize;
22756512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
22766789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
22775960Ssowmini 	dip->pr_linkid = linkid;
22787663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
22796512Ssowmini 	dip->pr_flags = flags;
22805903Ssowmini 	return (dip);
22815903Ssowmini }
22825903Ssowmini 
22837663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
22847663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
22857663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
22867663SSowmini.Varadhan@Sun.COM {
22877663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
22887663SSowmini.Varadhan@Sun.COM 
22897663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
22907663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
22917663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
22927663SSowmini.Varadhan@Sun.COM 	    flags, status));
22937663SSowmini.Varadhan@Sun.COM }
22947663SSowmini.Varadhan@Sun.COM 
22957663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
22967663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
22977663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
22987663SSowmini.Varadhan@Sun.COM {
22997663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
23007663SSowmini.Varadhan@Sun.COM 
23017663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
23027663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
23037663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
23047663SSowmini.Varadhan@Sun.COM 	    flags, status));
23057663SSowmini.Varadhan@Sun.COM }
23067663SSowmini.Varadhan@Sun.COM 
23075903Ssowmini /* ARGSUSED */
23085903Ssowmini static dladm_status_t
23098453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
23108453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
23118453SAnurag.Maskey@Sun.COM     datalink_media_t media)
23125903Ssowmini {
23136789Sam223141 	dld_ioc_macprop_t	*dip;
23145903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
23155903Ssowmini 	uint8_t		u8;
23165903Ssowmini 	uint16_t	u16;
23175903Ssowmini 	uint32_t	u32;
23185903Ssowmini 	void		*val;
23195903Ssowmini 
23208275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
23215903Ssowmini 	if (dip == NULL)
23225903Ssowmini 		return (status);
23235903Ssowmini 
23248275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
23255903Ssowmini 		val = (void *)vdp->vd_val;
23265903Ssowmini 	else {
23275903Ssowmini 		/*
23285903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
23295903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
23305903Ssowmini 		 */
23315903Ssowmini 		switch (dip->pr_valsize) {
23325903Ssowmini 		case 1:
23335903Ssowmini 			u8 = vdp->vd_val;
23345903Ssowmini 			val = &u8;
23355903Ssowmini 			break;
23365903Ssowmini 		case 2:
23375903Ssowmini 			u16 = vdp->vd_val;
23385903Ssowmini 			val = &u16;
23395903Ssowmini 			break;
23405903Ssowmini 		case 4:
23415903Ssowmini 			u32 = vdp->vd_val;
23425903Ssowmini 			val = &u32;
23435903Ssowmini 			break;
23445903Ssowmini 		default:
23455903Ssowmini 			val = &vdp->vd_val;
23465903Ssowmini 			break;
23475903Ssowmini 		}
23485903Ssowmini 	}
23495903Ssowmini 
23507342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
23517342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
23527342SAruna.Ramakrishna@Sun.COM 	else
23537342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
23547342SAruna.Ramakrishna@Sun.COM 
23558453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
23567663SSowmini.Varadhan@Sun.COM 
23577663SSowmini.Varadhan@Sun.COM done:
23587663SSowmini.Varadhan@Sun.COM 	free(dip);
23597663SSowmini.Varadhan@Sun.COM 	return (status);
23607663SSowmini.Varadhan@Sun.COM }
23617663SSowmini.Varadhan@Sun.COM 
23627663SSowmini.Varadhan@Sun.COM dladm_status_t
23638453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
23647663SSowmini.Varadhan@Sun.COM {
23657663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
23667663SSowmini.Varadhan@Sun.COM 
23678453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
23688453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
23695903Ssowmini 		status = dladm_errno2status(errno);
23708453SAnurag.Maskey@Sun.COM 
23715903Ssowmini 	return (status);
23725903Ssowmini }
23735903Ssowmini 
23746789Sam223141 static dld_ioc_macprop_t *
23758453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
23768453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
23775903Ssowmini {
23786789Sam223141 	dld_ioc_macprop_t *dip = NULL;
23796512Ssowmini 
23807663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
23816512Ssowmini 	if (dip == NULL)
23826512Ssowmini 		return (NULL);
23835903Ssowmini 
23848453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
23856512Ssowmini 	if (*status != DLADM_STATUS_OK) {
23866512Ssowmini 		free(dip);
23876512Ssowmini 		return (NULL);
23886512Ssowmini 	}
23898275SEric Cheng 	if (perm_flags != NULL)
23908275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
23918275SEric Cheng 
23926512Ssowmini 	return (dip);
23935903Ssowmini }
23945903Ssowmini 
23955903Ssowmini /* ARGSUSED */
23965903Ssowmini static dladm_status_t
23978453SAnurag.Maskey@Sun.COM i_dladm_defmtu_check(dladm_handle_t handle, prop_desc_t *pdp,
23988453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
23998453SAnurag.Maskey@Sun.COM     datalink_media_t media)
24005903Ssowmini {
24015903Ssowmini 	if (val_cnt != 1)
24025903Ssowmini 		return (DLADM_STATUS_BADVAL);
24036512Ssowmini 	v->vd_val = atoi(prop_val[0]);
24045903Ssowmini 	return (DLADM_STATUS_OK);
24055903Ssowmini }
24065903Ssowmini 
24075903Ssowmini /* ARGSUSED */
24085903Ssowmini static dladm_status_t
24098453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
24108453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
24118453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24125903Ssowmini {
24135903Ssowmini 	link_duplex_t   link_duplex;
24145903Ssowmini 	dladm_status_t  status;
24155903Ssowmini 
24168453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
24175903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
24185903Ssowmini 		return (status);
24195903Ssowmini 
24205903Ssowmini 	switch (link_duplex) {
24215903Ssowmini 	case LINK_DUPLEX_FULL:
24225903Ssowmini 		(void) strcpy(*prop_val, "full");
24235903Ssowmini 		break;
24245903Ssowmini 	case LINK_DUPLEX_HALF:
24255903Ssowmini 		(void) strcpy(*prop_val, "half");
24265903Ssowmini 		break;
24275903Ssowmini 	default:
24285903Ssowmini 		(void) strcpy(*prop_val, "unknown");
24295903Ssowmini 		break;
24305903Ssowmini 	}
24315903Ssowmini 	*val_cnt = 1;
24325903Ssowmini 	return (DLADM_STATUS_OK);
24335903Ssowmini }
24345903Ssowmini 
24355903Ssowmini /* ARGSUSED */
24365903Ssowmini static dladm_status_t
24378453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
24388275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
24395903Ssowmini {
24405903Ssowmini 	uint64_t	ifspeed = 0;
24415903Ssowmini 	dladm_status_t status;
24425903Ssowmini 
24438453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
24445903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
24455903Ssowmini 		return (status);
24466512Ssowmini 
24475960Ssowmini 	if ((ifspeed % 1000000) != 0) {
24485960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
24495960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
24505960Ssowmini 	} else {
24515960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
24525960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
24535960Ssowmini 	}
24545903Ssowmini 	*val_cnt = 1;
24558275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
24565903Ssowmini 	return (DLADM_STATUS_OK);
24575903Ssowmini }
24585903Ssowmini 
24595903Ssowmini /* ARGSUSED */
24605903Ssowmini static dladm_status_t
24618453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
24628453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
24638453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24645903Ssowmini {
24658275SEric Cheng 	link_state_t		link_state;
24668275SEric Cheng 	dladm_status_t		status;
24678306SSowmini.Varadhan@Sun.COM 
24688453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
24696512Ssowmini 	if (status != DLADM_STATUS_OK)
24705903Ssowmini 		return (status);
24718275SEric Cheng 
24725903Ssowmini 	switch (link_state) {
24735903Ssowmini 	case LINK_STATE_UP:
24745903Ssowmini 		(void) strcpy(*prop_val, "up");
24755903Ssowmini 		break;
24765903Ssowmini 	case LINK_STATE_DOWN:
24775903Ssowmini 		(void) strcpy(*prop_val, "down");
24785903Ssowmini 		break;
24795903Ssowmini 	default:
24805903Ssowmini 		(void) strcpy(*prop_val, "unknown");
24815903Ssowmini 		break;
24825903Ssowmini 	}
24835903Ssowmini 	*val_cnt = 1;
24848306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
24855903Ssowmini 	return (DLADM_STATUS_OK);
24865903Ssowmini }
24875903Ssowmini 
24885903Ssowmini /* ARGSUSED */
24895903Ssowmini static dladm_status_t
24908453SAnurag.Maskey@Sun.COM i_dladm_binary_get(dladm_handle_t handle, prop_desc_t *pdp,
24918453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
24928453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24935903Ssowmini {
24946789Sam223141 	dld_ioc_macprop_t *dip;
24955903Ssowmini 	dladm_status_t status;
24965903Ssowmini 
24978453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
24988275SEric Cheng 	    &status, perm_flags);
24996512Ssowmini 	if (dip == NULL)
25005903Ssowmini 		return (status);
25018275SEric Cheng 
25025903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
25035903Ssowmini 	free(dip);
25045903Ssowmini 	*val_cnt = 1;
25055903Ssowmini 	return (DLADM_STATUS_OK);
25065903Ssowmini }
25075903Ssowmini 
25085960Ssowmini /* ARGSUSED */
25095903Ssowmini static dladm_status_t
25108453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
25118453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
25128453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
25135903Ssowmini {
25146789Sam223141 	dld_ioc_macprop_t *dip;
25158275SEric Cheng 	uint32_t v = 0;
25165903Ssowmini 	uchar_t *cp;
25175903Ssowmini 	dladm_status_t status;
25185903Ssowmini 
25198453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
25208275SEric Cheng 	    &status, perm_flags);
25216512Ssowmini 	if (dip == NULL)
25225903Ssowmini 		return (status);
25238275SEric Cheng 
25245903Ssowmini 	cp = (uchar_t *)dip->pr_val;
25255903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
25266512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
25275903Ssowmini 	free(dip);
25285903Ssowmini 	*val_cnt = 1;
25295903Ssowmini 	return (DLADM_STATUS_OK);
25305903Ssowmini }
25315903Ssowmini 
25329514SGirish.Moodalbail@Sun.COM /*
25339514SGirish.Moodalbail@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
25349514SGirish.Moodalbail@Sun.COM  * for retrieving the property range values.
25359514SGirish.Moodalbail@Sun.COM  */
25369514SGirish.Moodalbail@Sun.COM static int
25379514SGirish.Moodalbail@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
25389514SGirish.Moodalbail@Sun.COM {
25399514SGirish.Moodalbail@Sun.COM 	uint_t count = r->mpr_count;
25409514SGirish.Moodalbail@Sun.COM 
25419514SGirish.Moodalbail@Sun.COM 	*sz = sizeof (mac_propval_range_t);
25429514SGirish.Moodalbail@Sun.COM 	--count;
25439514SGirish.Moodalbail@Sun.COM 
25449514SGirish.Moodalbail@Sun.COM 	switch (r->mpr_type) {
25459514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32:
25469514SGirish.Moodalbail@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
25479514SGirish.Moodalbail@Sun.COM 		return (0);
25489514SGirish.Moodalbail@Sun.COM 	default:
25499514SGirish.Moodalbail@Sun.COM 		break;
25509514SGirish.Moodalbail@Sun.COM 	}
25519514SGirish.Moodalbail@Sun.COM 	*sz = 0;
25529514SGirish.Moodalbail@Sun.COM 	return (EINVAL);
25539514SGirish.Moodalbail@Sun.COM }
25549514SGirish.Moodalbail@Sun.COM 
25559514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
25569514SGirish.Moodalbail@Sun.COM static dladm_status_t
25579514SGirish.Moodalbail@Sun.COM i_dladm_range_get(dladm_handle_t handle, prop_desc_t *pdp,
25589514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
25599514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
25609514SGirish.Moodalbail@Sun.COM {
25619514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
25629514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
25639514SGirish.Moodalbail@Sun.COM 	size_t	sz;
25649514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
25659514SGirish.Moodalbail@Sun.COM 
25669514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
25679514SGirish.Moodalbail@Sun.COM 
25689514SGirish.Moodalbail@Sun.COM 	/*
25699514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
25709514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
25719514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
25729514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
25739514SGirish.Moodalbail@Sun.COM 	 */
25749514SGirish.Moodalbail@Sun.COM retry:
25759514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
25769514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
25779514SGirish.Moodalbail@Sun.COM 		return (status);
25789514SGirish.Moodalbail@Sun.COM 
25799514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
25809514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
25819514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
25829514SGirish.Moodalbail@Sun.COM 			int err;
25839514SGirish.Moodalbail@Sun.COM 
25849514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
25859514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
25869514SGirish.Moodalbail@Sun.COM 				free(dip);
25879514SGirish.Moodalbail@Sun.COM 				goto retry;
25889514SGirish.Moodalbail@Sun.COM 			} else {
25899514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
25909514SGirish.Moodalbail@Sun.COM 			}
25919514SGirish.Moodalbail@Sun.COM 		}
25929514SGirish.Moodalbail@Sun.COM 		free(dip);
25939514SGirish.Moodalbail@Sun.COM 		return (status);
25949514SGirish.Moodalbail@Sun.COM 	}
25959514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
25969514SGirish.Moodalbail@Sun.COM 
25979514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
25989514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
25999514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
26009514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
26019514SGirish.Moodalbail@Sun.COM 
26029514SGirish.Moodalbail@Sun.COM 		ur = &rangep->range_uint32[0];
26039514SGirish.Moodalbail@Sun.COM 
26049514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
26059514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
26069514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
26079514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
26089514SGirish.Moodalbail@Sun.COM 			} else {
26099514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
26109514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
26119514SGirish.Moodalbail@Sun.COM 			}
26129514SGirish.Moodalbail@Sun.COM 		}
26139514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
26149514SGirish.Moodalbail@Sun.COM 		break;
26159514SGirish.Moodalbail@Sun.COM 	}
26169514SGirish.Moodalbail@Sun.COM 	default:
26179514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
26189514SGirish.Moodalbail@Sun.COM 		break;
26199514SGirish.Moodalbail@Sun.COM 	}
26209514SGirish.Moodalbail@Sun.COM 	free(dip);
26219514SGirish.Moodalbail@Sun.COM 	return (status);
26229514SGirish.Moodalbail@Sun.COM }
26239514SGirish.Moodalbail@Sun.COM 
26245960Ssowmini /* ARGSUSED */
26255903Ssowmini static dladm_status_t
26268874SSebastien.Roy@Sun.COM i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
26278874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
26288874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
26298874SSebastien.Roy@Sun.COM {
26308874SSebastien.Roy@Sun.COM 	dld_ioc_macprop_t	*dip;
26318874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
26328874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
26338874SSebastien.Roy@Sun.COM 
26348874SSebastien.Roy@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
26358874SSebastien.Roy@Sun.COM 	    &status, perm_flags);
26368874SSebastien.Roy@Sun.COM 	if (dip == NULL)
26378874SSebastien.Roy@Sun.COM 		return (status);
26388874SSebastien.Roy@Sun.COM 	(void) memcpy(&mode, dip->pr_val, sizeof (mode));
26398874SSebastien.Roy@Sun.COM 	free(dip);
26408874SSebastien.Roy@Sun.COM 
26418874SSebastien.Roy@Sun.COM 	switch (mode) {
26428874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
26438874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
26448874SSebastien.Roy@Sun.COM 		break;
26458874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
26468874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
26478874SSebastien.Roy@Sun.COM 		break;
26488874SSebastien.Roy@Sun.COM 	default:
26498874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
26508874SSebastien.Roy@Sun.COM 	}
26518874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
26528874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
26538874SSebastien.Roy@Sun.COM }
26548874SSebastien.Roy@Sun.COM 
26558874SSebastien.Roy@Sun.COM /* ARGSUSED */
26568874SSebastien.Roy@Sun.COM static dladm_status_t
26578453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
26588453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
26598453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
26605903Ssowmini {
26616789Sam223141 	dld_ioc_macprop_t *dip;
26625903Ssowmini 	link_flowctrl_t v;
26635903Ssowmini 	dladm_status_t status;
26645903Ssowmini 	uchar_t *cp;
26655903Ssowmini 
26668453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
26678275SEric Cheng 	    &status, perm_flags);
26686512Ssowmini 	if (dip == NULL)
26695903Ssowmini 		return (status);
26708275SEric Cheng 
26715903Ssowmini 	cp = (uchar_t *)dip->pr_val;
26725903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
26735903Ssowmini 	switch (v) {
26745903Ssowmini 	case LINK_FLOWCTRL_NONE:
26755903Ssowmini 		(void) sprintf(*prop_val, "no");
26765903Ssowmini 		break;
26775903Ssowmini 	case LINK_FLOWCTRL_RX:
26785903Ssowmini 		(void) sprintf(*prop_val, "rx");
26795903Ssowmini 		break;
26805903Ssowmini 	case LINK_FLOWCTRL_TX:
26815903Ssowmini 		(void) sprintf(*prop_val, "tx");
26825903Ssowmini 		break;
26835903Ssowmini 	case LINK_FLOWCTRL_BI:
26845903Ssowmini 		(void) sprintf(*prop_val, "bi");
26855903Ssowmini 		break;
26865903Ssowmini 	}
26875903Ssowmini 	free(dip);
26885903Ssowmini 	*val_cnt = 1;
26895903Ssowmini 	return (DLADM_STATUS_OK);
26905903Ssowmini }
26915903Ssowmini 
26925903Ssowmini 
26935903Ssowmini /* ARGSUSED */
26945903Ssowmini static dladm_status_t
2695*9692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
26968453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
26978453SAnurag.Maskey@Sun.COM 
26985903Ssowmini {
26997663SSowmini.Varadhan@Sun.COM 	int		i, slen;
27007408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
27016789Sam223141 	dld_ioc_macprop_t *dip = NULL;
27025903Ssowmini 	uchar_t 	*dp;
27037663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
27046512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
27055903Ssowmini 
27065903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
27075903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
27085903Ssowmini 		return (DLADM_STATUS_BADARG);
27095903Ssowmini 	p = dladm_name2prop(prop_name);
27106789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
27115903Ssowmini 		return (DLADM_STATUS_BADARG);
27125903Ssowmini 
2713*9692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
2714*9692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
2715*9692SRishi.Srivatsavai@Sun.COM 
27165903Ssowmini 	/*
27175903Ssowmini 	 * private properties: all parsing is done in the kernel.
27185903Ssowmini 	 * allocate a enough space for each property + its separator (',').
27195903Ssowmini 	 */
27205903Ssowmini 	for (i = 0; i < val_cnt; i++) {
27215903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
27225903Ssowmini 	}
27236512Ssowmini 
27246512Ssowmini 	if (prop_val == NULL) {
27256512Ssowmini 		/*
27266512Ssowmini 		 * getting default value. so use more buffer space.
27276512Ssowmini 		 */
27287663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
27296512Ssowmini 	}
27306512Ssowmini 
27317663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
27326789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
27335903Ssowmini 	if (dip == NULL)
27345903Ssowmini 		return (status);
27355903Ssowmini 
27365903Ssowmini 	dp = (uchar_t *)dip->pr_val;
27375903Ssowmini 	slen = 0;
27387663SSowmini.Varadhan@Sun.COM 
27396512Ssowmini 	if (prop_val == NULL) {
27408453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
27418460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
27426512Ssowmini 	} else {
27436512Ssowmini 		for (i = 0; i < val_cnt; i++) {
27446512Ssowmini 			int plen = 0;
27455903Ssowmini 
27466512Ssowmini 			plen = strlen(prop_val[i]);
27476512Ssowmini 			bcopy(prop_val[i], dp, plen);
27486512Ssowmini 			slen += plen;
27496512Ssowmini 			/*
27506512Ssowmini 			 * add a "," separator and update dp.
27516512Ssowmini 			 */
27526512Ssowmini 			if (i != (val_cnt -1))
27536512Ssowmini 				dp[slen++] = ',';
27546512Ssowmini 			dp += (plen + 1);
27556512Ssowmini 		}
27568460SArtem.Kachitchkin@Sun.COM 	}
27578460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
27588453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
27596512Ssowmini 
27605903Ssowmini 	free(dip);
27616512Ssowmini 	return (status);
27625903Ssowmini }
27635903Ssowmini 
27645903Ssowmini static dladm_status_t
27658460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
27668453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
27678453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
27685903Ssowmini {
27697663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
27706789Sam223141 	dld_ioc_macprop_t *dip = NULL;
27717663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
27725903Ssowmini 
27735903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
27745903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
27755903Ssowmini 		return (DLADM_STATUS_BADARG);
27765903Ssowmini 
27775903Ssowmini 	p = dladm_name2prop(prop_name);
27786789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
27795903Ssowmini 		return (DLADM_STATUS_BADARG);
27805903Ssowmini 
27815903Ssowmini 	/*
27825903Ssowmini 	 * private properties: all parsing is done in the kernel.
27835903Ssowmini 	 */
27847663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
27857663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
27865903Ssowmini 	if (dip == NULL)
27875903Ssowmini 		return (status);
27885903Ssowmini 
27898453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
27908453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
27918118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
27928275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
27938460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
27948460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
27958118SVasumathi.Sundaram@Sun.COM 		} else {
27968118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
27978118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
27988118SVasumathi.Sundaram@Sun.COM 		}
27995903Ssowmini 		*val_cnt = 1;
28008460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
28018460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
28028460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
28035903Ssowmini 	}
28046512Ssowmini 	free(dip);
28055903Ssowmini 	return (status);
28065903Ssowmini }
28076512Ssowmini 
28086512Ssowmini 
28096512Ssowmini static dladm_status_t
28108453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
28118453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
28126512Ssowmini {
28136512Ssowmini 	dladm_status_t status;
28146512Ssowmini 	char **prop_vals = NULL, *buf;
28156512Ssowmini 	size_t bufsize;
28166512Ssowmini 	uint_t cnt;
28176512Ssowmini 	int i;
28188118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
28196512Ssowmini 
28206512Ssowmini 	/*
28216512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
28226512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
28236512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
28246512Ssowmini 	 */
28256512Ssowmini 	bufsize =
28266512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
28276512Ssowmini 	buf = malloc(bufsize);
28286512Ssowmini 	prop_vals = (char **)(void *)buf;
28296512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
28306512Ssowmini 		prop_vals[i] = buf +
28316512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
28326512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
28336512Ssowmini 	}
28346768Sar224390 
28356768Sar224390 	/*
28367342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
28377342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
28387342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
28397342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
28407342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
28417342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
28427342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
28437342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
28446768Sar224390 	 */
28458453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
28468118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
28476512Ssowmini 	if (status == DLADM_STATUS_OK) {
28488118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
28498453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
28508453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
28518118SVasumathi.Sundaram@Sun.COM 		}
28528118SVasumathi.Sundaram@Sun.COM 		else
28538118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
28546512Ssowmini 	}
28556512Ssowmini 	free(buf);
28566512Ssowmini 	return (status);
28576512Ssowmini }
28587663SSowmini.Varadhan@Sun.COM 
28597663SSowmini.Varadhan@Sun.COM int
28607663SSowmini.Varadhan@Sun.COM macprop_to_wifi(mac_prop_id_t wl_prop)
28617663SSowmini.Varadhan@Sun.COM {
28627663SSowmini.Varadhan@Sun.COM 	switch (wl_prop) {
28637663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ESSID:
28647663SSowmini.Varadhan@Sun.COM 		return (WL_ESSID);
28657663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_BSSID:
28667663SSowmini.Varadhan@Sun.COM 		return (WL_BSSID);
28677663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_BSSTYPE:
28687663SSowmini.Varadhan@Sun.COM 		return (WL_BSS_TYPE);
28697663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_LINKSTATUS:
28707663SSowmini.Varadhan@Sun.COM 		return (WL_LINKSTATUS);
28717663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_DESIRED_RATES:
28727663SSowmini.Varadhan@Sun.COM 		return (WL_DESIRED_RATES);
28737663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SUPPORTED_RATES:
28747663SSowmini.Varadhan@Sun.COM 		return (WL_SUPPORTED_RATES);
28757663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_AUTH_MODE:
28767663SSowmini.Varadhan@Sun.COM 		return (WL_AUTH_MODE);
28777663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ENCRYPTION:
28787663SSowmini.Varadhan@Sun.COM 		return (WL_ENCRYPTION);
28797663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_RSSI:
28807663SSowmini.Varadhan@Sun.COM 		return (WL_RSSI);
28817663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_PHY_CONFIG:
28827663SSowmini.Varadhan@Sun.COM 		return (WL_PHY_CONFIG);
28837663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_CAPABILITY:
28847663SSowmini.Varadhan@Sun.COM 		return (WL_CAPABILITY);
28857663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_WPA:
28867663SSowmini.Varadhan@Sun.COM 		return (WL_WPA);
28877663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SCANRESULTS:
28887663SSowmini.Varadhan@Sun.COM 		return (WL_SCANRESULTS);
28897663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_POWER_MODE:
28907663SSowmini.Varadhan@Sun.COM 		return (WL_POWER_MODE);
28917663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_RADIO:
28927663SSowmini.Varadhan@Sun.COM 		return (WL_RADIO);
28937663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ESS_LIST:
28947663SSowmini.Varadhan@Sun.COM 		return (WL_ESS_LIST);
28957663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_KEY_TAB:
28967663SSowmini.Varadhan@Sun.COM 		return (WL_WEP_KEY_TAB);
28977663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_CREATE_IBSS:
28987663SSowmini.Varadhan@Sun.COM 		return (WL_CREATE_IBSS);
28997663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SETOPTIE:
29007663SSowmini.Varadhan@Sun.COM 		return (WL_SETOPTIE);
29017663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_DELKEY:
29027663SSowmini.Varadhan@Sun.COM 		return (WL_DELKEY);
29037663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_KEY:
29047663SSowmini.Varadhan@Sun.COM 		return (WL_KEY);
29057663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_MLME:
29067663SSowmini.Varadhan@Sun.COM 		return (WL_MLME);
29077663SSowmini.Varadhan@Sun.COM 	default:
29087663SSowmini.Varadhan@Sun.COM 		return (-1);
29097663SSowmini.Varadhan@Sun.COM 	}
29107663SSowmini.Varadhan@Sun.COM }
29117663SSowmini.Varadhan@Sun.COM 
29127663SSowmini.Varadhan@Sun.COM dladm_status_t
29138453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
29148453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
29157663SSowmini.Varadhan@Sun.COM {
29167663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
29177663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
29187663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
29197663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
29207663SSowmini.Varadhan@Sun.COM 	void			*dp;
29217663SSowmini.Varadhan@Sun.COM 
29228453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
29238453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
29247663SSowmini.Varadhan@Sun.COM 		return (status);
29257663SSowmini.Varadhan@Sun.COM 	}
29267663SSowmini.Varadhan@Sun.COM 
29277663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
29287663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
29297663SSowmini.Varadhan@Sun.COM 
29307663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
29317663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
29327663SSowmini.Varadhan@Sun.COM 
29337663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
29347663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
29357663SSowmini.Varadhan@Sun.COM 
29367663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
29377663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
29387663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
29397663SSowmini.Varadhan@Sun.COM 
29407663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
29417663SSowmini.Varadhan@Sun.COM 	if (set)
29427663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
29437663SSowmini.Varadhan@Sun.COM 
29448453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
29457663SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_NOTSUP) {
29467663SSowmini.Varadhan@Sun.COM 		if (set) {
29478453SAnurag.Maskey@Sun.COM 			status = i_dladm_wlan_set_legacy_ioctl(handle, linkid,
29487663SSowmini.Varadhan@Sun.COM 			    buf, len, macprop_to_wifi(cmd));
29497663SSowmini.Varadhan@Sun.COM 		} else {
29508453SAnurag.Maskey@Sun.COM 			status = i_dladm_wlan_get_legacy_ioctl(handle, linkid,
29517663SSowmini.Varadhan@Sun.COM 			    buf, len, macprop_to_wifi(cmd));
29527663SSowmini.Varadhan@Sun.COM 		}
29537663SSowmini.Varadhan@Sun.COM 	} else if (status == DLADM_STATUS_OK) {
29547663SSowmini.Varadhan@Sun.COM 		if (!set)
29557663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
29567663SSowmini.Varadhan@Sun.COM 	}
29577663SSowmini.Varadhan@Sun.COM 
29587663SSowmini.Varadhan@Sun.COM 	free(dip);
29597663SSowmini.Varadhan@Sun.COM 	return (status);
29607663SSowmini.Varadhan@Sun.COM }
29617663SSowmini.Varadhan@Sun.COM 
29627663SSowmini.Varadhan@Sun.COM static dladm_status_t
29638453SAnurag.Maskey@Sun.COM i_dladm_wlan_get_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid,
29648453SAnurag.Maskey@Sun.COM     void *buf, uint_t buflen, uint_t id)
29657663SSowmini.Varadhan@Sun.COM {
29667663SSowmini.Varadhan@Sun.COM 	wldp_t *gbuf;
29677663SSowmini.Varadhan@Sun.COM 	dladm_status_t status;
29687663SSowmini.Varadhan@Sun.COM 
29697663SSowmini.Varadhan@Sun.COM 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
29707663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
29717663SSowmini.Varadhan@Sun.COM 
29727663SSowmini.Varadhan@Sun.COM 	(void) memset(gbuf, 0, MAX_BUF_LEN);
29738453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, id,
29748453SAnurag.Maskey@Sun.COM 	    MAX_BUF_LEN, WLAN_GET_PARAM, sizeof (wldp_t));
29757663SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK)
29767663SSowmini.Varadhan@Sun.COM 		(void) memcpy(buf, gbuf->wldp_buf, buflen);
29777663SSowmini.Varadhan@Sun.COM 
29787663SSowmini.Varadhan@Sun.COM 	free(gbuf);
29797663SSowmini.Varadhan@Sun.COM 	return (status);
29807663SSowmini.Varadhan@Sun.COM }
29817663SSowmini.Varadhan@Sun.COM 
29827663SSowmini.Varadhan@Sun.COM static dladm_status_t
29838453SAnurag.Maskey@Sun.COM i_dladm_wlan_set_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid,
29848453SAnurag.Maskey@Sun.COM     void *buf, uint_t buflen, uint_t id)
29857663SSowmini.Varadhan@Sun.COM {
29867663SSowmini.Varadhan@Sun.COM 	wldp_t *gbuf;
29877663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
29887663SSowmini.Varadhan@Sun.COM 
29897663SSowmini.Varadhan@Sun.COM 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
29907663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
29917663SSowmini.Varadhan@Sun.COM 
29927663SSowmini.Varadhan@Sun.COM 	(void) memset(gbuf, 0, MAX_BUF_LEN);
29937663SSowmini.Varadhan@Sun.COM 	(void) memcpy(gbuf->wldp_buf, buf, buflen);
29947663SSowmini.Varadhan@Sun.COM 	buflen += WIFI_BUF_OFFSET;
29958453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, id, buflen,
29967663SSowmini.Varadhan@Sun.COM 	    WLAN_SET_PARAM, buflen);
29977663SSowmini.Varadhan@Sun.COM 
29987663SSowmini.Varadhan@Sun.COM 	free(gbuf);
29997663SSowmini.Varadhan@Sun.COM 	return (status);
30007663SSowmini.Varadhan@Sun.COM }
30018275SEric Cheng 
30028275SEric Cheng dladm_status_t
30038275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
30048275SEric Cheng {
30058460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
30068275SEric Cheng }
30078275SEric Cheng 
30088275SEric Cheng /*
30098275SEric Cheng  * Retrieve the one link property from the database
30108275SEric Cheng  */
30118275SEric Cheng /*ARGSUSED*/
30128275SEric Cheng static int
30138453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
30148453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
30158275SEric Cheng {
30168275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
30178275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
30188275SEric Cheng 
30198275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
30208275SEric Cheng 	/*
30218275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
30228275SEric Cheng 	 * prop_table[n].pd_name.
30238275SEric Cheng 	 */
30248275SEric Cheng 	aip->ai_name = prop_name;
30258275SEric Cheng 
30268453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
30278453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
30288275SEric Cheng 
30298275SEric Cheng 	if (aip->ai_count != 0)
30308275SEric Cheng 		proplist->al_count++;
30318275SEric Cheng 
30328275SEric Cheng 	return (DLADM_WALK_CONTINUE);
30338275SEric Cheng }
30348275SEric Cheng 
30358275SEric Cheng 
30368275SEric Cheng /*
30378275SEric Cheng  * Retrieve all link properties for a link from the database and
30388275SEric Cheng  * return a property list.
30398275SEric Cheng  */
30408275SEric Cheng dladm_status_t
30418453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
30428453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
30438275SEric Cheng {
30448275SEric Cheng 	dladm_arg_list_t	*list;
30458275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
30468275SEric Cheng 
30478275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
30488275SEric Cheng 	if (list == NULL)
30498275SEric Cheng 		return (dladm_errno2status(errno));
30508275SEric Cheng 
30518453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
30528453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
30538275SEric Cheng 
30548275SEric Cheng 	*listp = list;
30558275SEric Cheng 	return (status);
30568275SEric Cheng }
30578275SEric Cheng 
30588275SEric Cheng /*
30598275SEric Cheng  * Retrieve the named property from a proplist, check the value and
30608275SEric Cheng  * convert to a kernel structure.
30618275SEric Cheng  */
30628275SEric Cheng static dladm_status_t
30638453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
30648453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist, const char *name, void *val)
30658275SEric Cheng {
30668275SEric Cheng 	dladm_status_t		status;
30678275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
30688275SEric Cheng 	int			i, j;
30698275SEric Cheng 
30708275SEric Cheng 	/* Find named property in proplist */
30718275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
30728275SEric Cheng 		aip = &proplist->al_info[i];
30738275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
30748275SEric Cheng 			break;
30758275SEric Cheng 	}
30768275SEric Cheng 
30778275SEric Cheng 	/* Property not in list */
30788275SEric Cheng 	if (i == proplist->al_count)
30798275SEric Cheng 		return (DLADM_STATUS_OK);
30808275SEric Cheng 
30818275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
30828275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
30838275SEric Cheng 		val_desc_t	*vdp;
30848275SEric Cheng 
30858275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
30868275SEric Cheng 		if (vdp == NULL)
30878275SEric Cheng 			return (DLADM_STATUS_NOMEM);
30888275SEric Cheng 
30898275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
30908275SEric Cheng 			continue;
30918275SEric Cheng 
30928275SEric Cheng 		if (aip->ai_val == NULL)
30938275SEric Cheng 			return (DLADM_STATUS_BADARG);
30948275SEric Cheng 
30958275SEric Cheng 		/* Check property value */
30968275SEric Cheng 		if (pdp->pd_check != NULL) {
30978453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
30988275SEric Cheng 			    aip->ai_count, vdp, 0);
30998275SEric Cheng 		} else {
31008275SEric Cheng 			status = DLADM_STATUS_BADARG;
31018275SEric Cheng 		}
31028275SEric Cheng 
31038275SEric Cheng 		if (status != DLADM_STATUS_OK)
31048275SEric Cheng 			return (status);
31058275SEric Cheng 
31068275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
31078275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
31088275SEric Cheng 
31098275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
31108275SEric Cheng 				continue;
31118275SEric Cheng 
31128275SEric Cheng 			/* Extract kernel structure */
31138275SEric Cheng 			if (rpp->rp_extract != NULL) {
31148275SEric Cheng 				status = rpp->rp_extract(vdp, val,
31158275SEric Cheng 				    aip->ai_count);
31168275SEric Cheng 			} else {
31178275SEric Cheng 				status = DLADM_STATUS_BADARG;
31188275SEric Cheng 			}
31198275SEric Cheng 			break;
31208275SEric Cheng 		}
31218275SEric Cheng 
31228275SEric Cheng 		if (status != DLADM_STATUS_OK)
31238275SEric Cheng 			return (status);
31248275SEric Cheng 
31258275SEric Cheng 		break;
31268275SEric Cheng 	}
31278275SEric Cheng 	return (status);
31288275SEric Cheng }
31298275SEric Cheng 
31308275SEric Cheng /*
31318275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
31328275SEric Cheng  */
31338275SEric Cheng dladm_status_t
31348453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
31358275SEric Cheng     mac_resource_props_t *mrp)
31368275SEric Cheng {
31378275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
31388275SEric Cheng 
31398453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "maxbw",
31408453SAnurag.Maskey@Sun.COM 	    mrp);
31418275SEric Cheng 	if (status != DLADM_STATUS_OK)
31428275SEric Cheng 		return (status);
31438453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "priority",
31448453SAnurag.Maskey@Sun.COM 	    mrp);
31458275SEric Cheng 	if (status != DLADM_STATUS_OK)
31468275SEric Cheng 		return (status);
31478453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "cpus",
31488453SAnurag.Maskey@Sun.COM 	    mrp);
31498275SEric Cheng 	if (status != DLADM_STATUS_OK)
31508275SEric Cheng 		return (status);
31518275SEric Cheng 	return (status);
31528275SEric Cheng }
31538275SEric Cheng 
31548275SEric Cheng static const char *
31558275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
31568275SEric Cheng {
31578275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
31588275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
31598275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
31608275SEric Cheng 	return (buf);
31618275SEric Cheng }
31628306SSowmini.Varadhan@Sun.COM 
31638306SSowmini.Varadhan@Sun.COM dladm_status_t
31648453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
31658453SAnurag.Maskey@Sun.COM     link_state_t *state)
31668306SSowmini.Varadhan@Sun.COM {
31678306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
31688306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
31698306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
31708306SSowmini.Varadhan@Sun.COM 
31718453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
31728453SAnurag.Maskey@Sun.COM 	    &perms);
31738306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
31748306SSowmini.Varadhan@Sun.COM 		return (status);
31758306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
31768306SSowmini.Varadhan@Sun.COM 	free(dip);
31778306SSowmini.Varadhan@Sun.COM 	return (status);
31788306SSowmini.Varadhan@Sun.COM }
31798460SArtem.Kachitchkin@Sun.COM 
31808460SArtem.Kachitchkin@Sun.COM boolean_t
31818460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
31828460SArtem.Kachitchkin@Sun.COM {
31838460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
31848460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
31858460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
31868460SArtem.Kachitchkin@Sun.COM 		"name",
31878460SArtem.Kachitchkin@Sun.COM 		"class",
31888460SArtem.Kachitchkin@Sun.COM 		"media",
31898460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
31908460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
31918460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
31928460SArtem.Kachitchkin@Sun.COM 
31938460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
31948460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
31958460SArtem.Kachitchkin@Sun.COM 	};
31968460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
31978460SArtem.Kachitchkin@Sun.COM 	int		i;
31988460SArtem.Kachitchkin@Sun.COM 
31998460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
32008460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
32018460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
32028460SArtem.Kachitchkin@Sun.COM 			break;
32038460SArtem.Kachitchkin@Sun.COM 		}
32048460SArtem.Kachitchkin@Sun.COM 	}
32058460SArtem.Kachitchkin@Sun.COM 
32068460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
32078460SArtem.Kachitchkin@Sun.COM }
3208