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 /*
225895Syz147064  * Copyright 2008 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 
71*8453SAnurag.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  */
86*8453SAnurag.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  */
104*8453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
105*8453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **propstrp, uint_t cnt,
106*8453SAnurag.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 *);
118*8453SAnurag.Maskey@Sun.COM static dld_ioc_macprop_t *i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
119*8453SAnurag.Maskey@Sun.COM 			    char *, uint_t, dladm_status_t *, uint_t *);
120*8453SAnurag.Maskey@Sun.COM 
121*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_set_prop(dladm_handle_t, datalink_id_t,
122*8453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
123*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_get_prop(dladm_handle_t, datalink_id_t,
124*8453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *, dladm_prop_type_t,
125*8453SAnurag.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,
1348275SEric Cheng 			i_dladm_flowctl_get, dld_maxbw_get, dld_cpus_get,
1358275SEric Cheng 			dld_priority_get;
1368275SEric Cheng 
1377342SAruna.Ramakrishna@Sun.COM static pd_setf_t	do_set_zone, do_set_rate_prop,
1385903Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
1398275SEric Cheng 			i_dladm_set_public_prop, do_set_res, do_set_cpus;
1408275SEric Cheng 
1415903Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
1428275SEric Cheng 			i_dladm_defmtu_check, do_check_maxbw, do_check_cpus,
1438275SEric Cheng 			do_check_priority;
1448275SEric Cheng 
145*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_speed_get(dladm_handle_t, prop_desc_t *,
146*8453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **, uint_t *, uint_t, uint_t *);
147*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_wlan_get_legacy_ioctl(dladm_handle_t,
148*8453SAnurag.Maskey@Sun.COM 			    datalink_id_t, void *, uint_t, uint_t);
149*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_wlan_set_legacy_ioctl(dladm_handle_t,
150*8453SAnurag.Maskey@Sun.COM 			    datalink_id_t, void *, uint_t, uint_t);
151*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1528275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1538275SEric Cheng 
1548275SEric Cheng struct prop_desc {
1555895Syz147064 	/*
1565895Syz147064 	 * link property name
1575895Syz147064 	 */
1585895Syz147064 	char			*pd_name;
1595895Syz147064 
1605895Syz147064 	/*
1615895Syz147064 	 * default property value, can be set to { "", NULL }
1625895Syz147064 	 */
1635895Syz147064 	val_desc_t		pd_defval;
1645895Syz147064 
1655895Syz147064 	/*
1665895Syz147064 	 * list of optional property values, can be NULL.
1675895Syz147064 	 *
1685895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1695895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1705895Syz147064 	 */
1715895Syz147064 	val_desc_t		*pd_optval;
1725895Syz147064 
1735895Syz147064 	/*
1745895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1755895Syz147064 	 */
1765895Syz147064 	uint_t			pd_noptval;
1775895Syz147064 
1785895Syz147064 	/*
1795895Syz147064 	 * callback to set link property;
1805895Syz147064 	 * set to NULL if this property is read-only
1815895Syz147064 	 */
1825895Syz147064 	pd_setf_t		*pd_set;
1835895Syz147064 
1845895Syz147064 	/*
1855895Syz147064 	 * callback to get modifiable link property
1865895Syz147064 	 */
1875895Syz147064 	pd_getf_t		*pd_getmod;
1885895Syz147064 
1895895Syz147064 	/*
1905895Syz147064 	 * callback to get current link property
1915895Syz147064 	 */
1925895Syz147064 	pd_getf_t		*pd_get;
1935895Syz147064 
1945895Syz147064 	/*
1955895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
1965895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
1975895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
1985895Syz147064 	 * valid.
1995895Syz147064 	 */
2005895Syz147064 	pd_checkf_t		*pd_check;
2015895Syz147064 
2025895Syz147064 	uint_t			pd_flags;
2035903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2045903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
2055895Syz147064 	/*
2065895Syz147064 	 * indicate link classes this property applies to.
2075895Syz147064 	 */
2085895Syz147064 	datalink_class_t	pd_class;
2095895Syz147064 
2105895Syz147064 	/*
2115895Syz147064 	 * indicate link media type this property applies to.
2125895Syz147064 	 */
2135895Syz147064 	datalink_media_t	pd_dmedia;
2148275SEric Cheng };
2153448Sdh155122 
2166789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2175903Ssowmini 
2187663SSowmini.Varadhan@Sun.COM /*
2197663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2207663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2217663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2227663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2237663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2247663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2257663SSowmini.Varadhan@Sun.COM  */
2267663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2277663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2285903Ssowmini 
2297663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2307663SSowmini.Varadhan@Sun.COM 
2317663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2327663SSowmini.Varadhan@Sun.COM 
2337663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2345903Ssowmini 
2357663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2365903Ssowmini 
2377663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2387663SSowmini.Varadhan@Sun.COM 
2397663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2405903Ssowmini 
2417663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2427663SSowmini.Varadhan@Sun.COM 
2437663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2447663SSowmini.Varadhan@Sun.COM 
2457663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2465903Ssowmini 
2477663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2485903Ssowmini 
2497663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2507663SSowmini.Varadhan@Sun.COM 
2517663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2527342SAruna.Ramakrishna@Sun.COM 
2537663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2547663SSowmini.Varadhan@Sun.COM 
2557663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2567663SSowmini.Varadhan@Sun.COM 
2577663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2587342SAruna.Ramakrishna@Sun.COM 
2597663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2607663SSowmini.Varadhan@Sun.COM 
2617663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2625903Ssowmini 
2637663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2647663SSowmini.Varadhan@Sun.COM 
2657663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2665903Ssowmini 
2677663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2687663SSowmini.Varadhan@Sun.COM 
2697663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2705903Ssowmini 
2717663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2727663SSowmini.Varadhan@Sun.COM 
2737663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2747663SSowmini.Varadhan@Sun.COM 
2757663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2767663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2775903Ssowmini 
2787663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2797663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2807663SSowmini.Varadhan@Sun.COM 
2817663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2825903Ssowmini 
2837663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
2847663SSowmini.Varadhan@Sun.COM 
2857663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
2865903Ssowmini 
2877663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
2887663SSowmini.Varadhan@Sun.COM 
2897663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
2905903Ssowmini 
2917663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
2927663SSowmini.Varadhan@Sun.COM 
2937663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
2947663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
2955903Ssowmini 
2967663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
2977663SSowmini.Varadhan@Sun.COM 
2987663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
2995903Ssowmini 
3007663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3017663SSowmini.Varadhan@Sun.COM 
3027663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3035903Ssowmini 
3047663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3057663SSowmini.Varadhan@Sun.COM 
3067663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3077663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3085903Ssowmini 
3097663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3107663SSowmini.Varadhan@Sun.COM 
3117663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3125903Ssowmini 
3137663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3147663SSowmini.Varadhan@Sun.COM 
3158275SEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
3168275SEric Cheng 
3178275SEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
3188275SEric Cheng 
3198275SEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
3208275SEric Cheng 
3217663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3228275SEric Cheng 
3235903Ssowmini };
3245903Ssowmini 
3255903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3265903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3275903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3285903Ssowmini };
3295903Ssowmini static  val_desc_t	link_status_vals[] = {
3305903Ssowmini 	{ "up",		LINK_STATE_UP		},
3315903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3325903Ssowmini };
3335903Ssowmini static  val_desc_t	link_01_vals[] = {
3345903Ssowmini 	{ "1",		1			},
3355903Ssowmini 	{ "0",		0			}
3365903Ssowmini };
3375903Ssowmini static  val_desc_t	link_flow_vals[] = {
3385903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3395903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3405903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3415903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3425903Ssowmini };
3438275SEric Cheng static  val_desc_t	link_priority_vals[] = {
3448275SEric Cheng 	{ "low",	MPL_LOW	},
3458275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
3468275SEric Cheng 	{ "high",	MPL_HIGH	}
3478275SEric Cheng };
3485903Ssowmini 
3495895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
3505895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
3515895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
3525895Syz147064 };
3535895Syz147064 
3545895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
3555895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
3565895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
3575895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
3585895Syz147064 };
3595895Syz147064 
3608275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
3618275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
3628275SEric Cheng 
3633448Sdh155122 static prop_desc_t	prop_table[] = {
3645903Ssowmini 	{ "channel",	{ NULL, 0 },
3655903Ssowmini 	    NULL, 0, NULL, NULL,
3665895Syz147064 	    do_get_channel_prop, NULL, 0,
3675903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3685895Syz147064 
3695895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
3705895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
3715895Syz147064 	    do_set_powermode_prop, NULL,
3725895Syz147064 	    do_get_powermode_prop, NULL, 0,
3735903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3745895Syz147064 
3755895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
3765895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
3775895Syz147064 	    do_set_radio_prop, NULL,
3785895Syz147064 	    do_get_radio_prop, NULL, 0,
3795903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
3805895Syz147064 
3815895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
3825895Syz147064 	    do_set_rate_prop, do_get_rate_mod,
3835895Syz147064 	    do_get_rate_prop, do_check_rate, 0,
3845960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
3855895Syz147064 
3866512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
3877342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL,
3887342SAruna.Ramakrishna@Sun.COM 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
3895903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
3905895Syz147064 
3916512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
3923448Sdh155122 	    do_set_zone, NULL,
3937342SAruna.Ramakrishna@Sun.COM 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
3945903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
3955903Ssowmini 
3968275SEric Cheng 	{ "duplex",	{ "", 0 },
3975903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
3987342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_duplex_get, NULL,
3995903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4005903Ssowmini 
4018275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4025903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4037342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_status_get, NULL,
4046512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4055903Ssowmini 
4065903Ssowmini 	{ "adv_autoneg_cap", { "1", 1 },
4075903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4087342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4095903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4105903Ssowmini 
4116512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4127342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
4137342SAruna.Ramakrishna@Sun.COM 	    i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL,
4147342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4155903Ssowmini 
4166512Ssowmini 	{ "flowctrl", { "", 0 },
4175903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4187342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
4195903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4205903Ssowmini 
4216512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4226512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4237342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4245903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4255903Ssowmini 
4266512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
4275903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4287342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4295903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4305903Ssowmini 
4316512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
4325903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4337342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4345903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4355903Ssowmini 
4366512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
4375903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4387342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4395903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4405903Ssowmini 
4416512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
4425903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4437342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4445903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4455903Ssowmini 
4466512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
4475903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4487342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4495903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4505903Ssowmini 
4516512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
4525903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4537342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4545903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4555903Ssowmini 
4566512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
4575903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4587342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4595903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4605903Ssowmini 
4616512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
4625903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4637342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4645903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4655903Ssowmini 
4666512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
4675903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4687342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4695903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4705903Ssowmini 
4716512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
4725903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4737342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4745903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4755903Ssowmini 
4766512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
4775903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4787342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4798275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4808275SEric Cheng 
4818275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
4828275SEric Cheng 	    do_set_res, NULL,
4838275SEric Cheng 	    dld_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
4848275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4858275SEric Cheng 
4868275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
4878275SEric Cheng 	    do_set_cpus, NULL,
4888275SEric Cheng 	    dld_cpus_get, do_check_cpus, 0,
4898275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4908275SEric Cheng 
4918275SEric Cheng 	{ "priority", { "high", RESET_VAL },
4928275SEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
4938275SEric Cheng 	    dld_priority_get, do_check_priority, PD_CHECK_ALLOC,
4948275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4953448Sdh155122 };
4963448Sdh155122 
4975895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
4985895Syz147064 
4998275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
5008275SEric Cheng 	{"maxbw",	do_extract_maxbw},
5018275SEric Cheng 	{"priority",	do_extract_priority},
5028275SEric Cheng 	{"cpus",	do_extract_cpus}
5038275SEric Cheng };
5048275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
5058275SEric Cheng 	sizeof (resource_prop_t))
5068275SEric Cheng 
5077663SSowmini.Varadhan@Sun.COM /*
5087663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
5097663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
5107663SSowmini.Varadhan@Sun.COM  */
5117663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
5127663SSowmini.Varadhan@Sun.COM 
513*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
514*8453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
515*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
516*8453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
517*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
518*8453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
519*8453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
520*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
521*8453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
522*8453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
523*8453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
5248275SEric Cheng 
5258275SEric Cheng static dladm_status_t	link_proplist_check(dladm_arg_list_t *);
5268275SEric Cheng 
5275895Syz147064 /*
5285895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
5295895Syz147064  * rates to be retrieved. However, we cannot increase it at this
5305895Syz147064  * time because it will break binary compatibility with unbundled
5315895Syz147064  * WiFi drivers and utilities. So for now we define an additional
5325895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
5335895Syz147064  */
5345895Syz147064 #define	MAX_SUPPORT_RATES	64
5355895Syz147064 
5365895Syz147064 #define	AP_ANCHOR	"[anchor]"
5375895Syz147064 #define	AP_DELIMITER	'.'
5385895Syz147064 
5395895Syz147064 static dladm_status_t
5405895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
5415895Syz147064     val_desc_t *vdp)
5425895Syz147064 {
5435895Syz147064 	int		i, j;
5445895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
5453147Sxc151355 
5465895Syz147064 	for (j = 0; j < val_cnt; j++) {
5475895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
5485895Syz147064 			if (strcasecmp(*prop_val,
5495895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
5505895Syz147064 				break;
5515895Syz147064 			}
5525895Syz147064 		}
5535895Syz147064 		if (i == pdp->pd_noptval) {
5545895Syz147064 			status = DLADM_STATUS_BADVAL;
5555895Syz147064 			goto done;
5565895Syz147064 		}
5575895Syz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
5585895Syz147064 	}
5595895Syz147064 
5605895Syz147064 done:
5615895Syz147064 	return (status);
5625895Syz147064 }
5635895Syz147064 
5645895Syz147064 static dladm_status_t
565*8453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
566*8453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
567*8453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
5683147Sxc151355 {
5695895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
5705895Syz147064 	val_desc_t	*vdp = NULL;
5715895Syz147064 	boolean_t	needfree = B_FALSE;
5725895Syz147064 	uint_t		cnt, i;
5733147Sxc151355 
5745895Syz147064 	if (!(pdp->pd_class & class))
5755895Syz147064 		return (DLADM_STATUS_BADARG);
5765895Syz147064 
5775895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
5783147Sxc151355 		return (DLADM_STATUS_BADARG);
5793147Sxc151355 
5805895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
5815895Syz147064 		return (DLADM_STATUS_TEMPONLY);
5825895Syz147064 
5835895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
5845895Syz147064 		return (DLADM_STATUS_OK);
5855895Syz147064 
5865895Syz147064 	if (pdp->pd_set == NULL)
5875895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
5883448Sdh155122 
5895895Syz147064 	if (prop_val != NULL) {
5905895Syz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
5915895Syz147064 		if (vdp == NULL)
5925895Syz147064 			return (DLADM_STATUS_NOMEM);
5935895Syz147064 
5945895Syz147064 		if (pdp->pd_check != NULL) {
5958275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
596*8453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
597*8453SAnurag.Maskey@Sun.COM 			    val_cnt, vdp, media);
5985895Syz147064 		} else if (pdp->pd_optval != NULL) {
5995895Syz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
6005895Syz147064 		} else {
6013448Sdh155122 			status = DLADM_STATUS_BADARG;
6023147Sxc151355 		}
6035895Syz147064 
6043147Sxc151355 		if (status != DLADM_STATUS_OK)
6055895Syz147064 			goto done;
6065895Syz147064 
6075895Syz147064 		cnt = val_cnt;
6085895Syz147064 	} else {
6098275SEric Cheng 		boolean_t	defval = B_FALSE;
6108275SEric Cheng 
6115895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
6125895Syz147064 			return (DLADM_STATUS_NOTSUP);
6135895Syz147064 
6147342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
6158275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
6168275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
6176512Ssowmini 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
6186512Ssowmini 				return (DLADM_STATUS_NOMEM);
6197342SAruna.Ramakrishna@Sun.COM 
6208275SEric Cheng 			if (defval) {
6218275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
6228275SEric Cheng 				    sizeof (val_desc_t));
6238275SEric Cheng 			} else if (pdp->pd_check != NULL) {
624*8453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
625*8453SAnurag.Maskey@Sun.COM 				    prop_val, cnt, vdp, media);
6267342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
6277342SAruna.Ramakrishna@Sun.COM 					goto done;
6287342SAruna.Ramakrishna@Sun.COM 			}
6296512Ssowmini 		} else {
630*8453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
6316512Ssowmini 			    media, flags);
6326512Ssowmini 			return (status);
6336512Ssowmini 		}
6345895Syz147064 	}
635*8453SAnurag.Maskey@Sun.COM 	status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags, media);
6365895Syz147064 	if (needfree) {
6375895Syz147064 		for (i = 0; i < cnt; i++)
6385903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
6393147Sxc151355 	}
6405895Syz147064 done:
6415895Syz147064 	free(vdp);
6425895Syz147064 	return (status);
6435895Syz147064 }
6445895Syz147064 
6455895Syz147064 static dladm_status_t
646*8453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
647*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
6485895Syz147064 {
6495895Syz147064 	int			i;
6505895Syz147064 	boolean_t		found = B_FALSE;
6515895Syz147064 	datalink_class_t	class;
6525895Syz147064 	uint32_t		media;
6535895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
6545895Syz147064 
655*8453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
656*8453SAnurag.Maskey@Sun.COM 	    NULL, 0);
6575895Syz147064 	if (status != DLADM_STATUS_OK)
6585895Syz147064 		return (status);
6595895Syz147064 
6605895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
6615895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
6625895Syz147064 		dladm_status_t	s;
6635895Syz147064 
6645895Syz147064 		if (prop_name != NULL &&
6655895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
6665895Syz147064 			continue;
6675895Syz147064 		found = B_TRUE;
668*8453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
669*8453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
6703448Sdh155122 
6715895Syz147064 		if (prop_name != NULL) {
6725895Syz147064 			status = s;
6735895Syz147064 			break;
6745895Syz147064 		} else {
6755895Syz147064 			if (s != DLADM_STATUS_OK &&
6765895Syz147064 			    s != DLADM_STATUS_NOTSUP)
6775895Syz147064 				status = s;
6785895Syz147064 		}
6795895Syz147064 	}
6805903Ssowmini 	if (!found) {
6815903Ssowmini 		if (prop_name[0] == '_') {
6825903Ssowmini 			/* other private properties */
683*8453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_prop(handle, linkid, prop_name,
684*8453SAnurag.Maskey@Sun.COM 			    prop_val, val_cnt, flags);
6855903Ssowmini 		} else  {
6865903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
6875903Ssowmini 		}
6885903Ssowmini 	}
6895895Syz147064 
6905895Syz147064 	return (status);
6915895Syz147064 }
6925895Syz147064 
6935895Syz147064 /*
6945895Syz147064  * Set/reset link property for specific link
6955895Syz147064  */
6965895Syz147064 dladm_status_t
697*8453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
698*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
6995895Syz147064 {
7005895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
7015895Syz147064 
7025895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
7035895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
7045895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
7055895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
7065895Syz147064 		return (DLADM_STATUS_BADARG);
7075895Syz147064 	}
7085895Syz147064 
709*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
7105895Syz147064 	    val_cnt, flags);
7115895Syz147064 	if (status != DLADM_STATUS_OK)
7125895Syz147064 		return (status);
7135895Syz147064 
7145895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
715*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
7163147Sxc151355 		    prop_val, val_cnt);
7173147Sxc151355 	}
7183147Sxc151355 	return (status);
7193147Sxc151355 }
7203147Sxc151355 
7215895Syz147064 /*
7225895Syz147064  * Walk link properties of the given specific link.
7235895Syz147064  */
7243147Sxc151355 dladm_status_t
725*8453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
726*8453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
7273147Sxc151355 {
7285895Syz147064 	dladm_status_t		status;
7295895Syz147064 	datalink_class_t	class;
7305895Syz147064 	uint_t			media;
7315895Syz147064 	int			i;
7325895Syz147064 
7335895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
7345895Syz147064 		return (DLADM_STATUS_BADARG);
7355895Syz147064 
736*8453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
737*8453SAnurag.Maskey@Sun.COM 	    NULL, 0);
7385895Syz147064 	if (status != DLADM_STATUS_OK)
7395895Syz147064 		return (status);
7405895Syz147064 
7415895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
7425895Syz147064 		if (!(prop_table[i].pd_class & class))
7435895Syz147064 			continue;
7445895Syz147064 
7455895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
7465895Syz147064 			continue;
7475895Syz147064 
748*8453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
7495895Syz147064 		    DLADM_WALK_TERMINATE) {
7505895Syz147064 			break;
7515895Syz147064 		}
7525895Syz147064 	}
7535895Syz147064 
7545895Syz147064 	return (DLADM_STATUS_OK);
7555895Syz147064 }
7563448Sdh155122 
7575895Syz147064 /*
7585895Syz147064  * Get linkprop of the given specific link.
7595895Syz147064  */
7605895Syz147064 dladm_status_t
761*8453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
762*8453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
763*8453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
7645895Syz147064 {
7655895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
7665895Syz147064 	datalink_class_t	class;
7675895Syz147064 	uint_t			media;
7685895Syz147064 	prop_desc_t		*pdp;
7696512Ssowmini 	uint_t			cnt, dld_flags = 0;
7705895Syz147064 	int			i;
7718118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
7725895Syz147064 
7736512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
7746789Sam223141 		dld_flags = MAC_PROP_DEFAULT;
7756512Ssowmini 
7765895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
7775895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
7785895Syz147064 		return (DLADM_STATUS_BADARG);
7795895Syz147064 
7805895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
7815895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
7825895Syz147064 			break;
7835895Syz147064 
7845903Ssowmini 	if (i == DLADM_MAX_PROPS) {
7855903Ssowmini 		if (prop_name[0] == '_') {
7865903Ssowmini 			/*
7875903Ssowmini 			 * private property.
7885903Ssowmini 			 */
789*8453SAnurag.Maskey@Sun.COM 			return (i_dladm_get_prop(handle, linkid, prop_name,
7906512Ssowmini 			    prop_val, val_cntp, type, dld_flags));
7915903Ssowmini 		} else {
7925903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
7935903Ssowmini 		}
7945903Ssowmini 	}
7955895Syz147064 
7965895Syz147064 	pdp = &prop_table[i];
7975895Syz147064 
798*8453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
799*8453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8005895Syz147064 	if (status != DLADM_STATUS_OK)
8015895Syz147064 		return (status);
8025895Syz147064 
8035895Syz147064 	if (!(pdp->pd_class & class))
8045895Syz147064 		return (DLADM_STATUS_BADARG);
8055895Syz147064 
8065895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
8073147Sxc151355 		return (DLADM_STATUS_BADARG);
8083147Sxc151355 
8095895Syz147064 	switch (type) {
8105895Syz147064 	case DLADM_PROP_VAL_CURRENT:
811*8453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
812*8453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
8138118SVasumathi.Sundaram@Sun.COM 		break;
8148118SVasumathi.Sundaram@Sun.COM 
8158118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
8168118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
8178118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
8188118SVasumathi.Sundaram@Sun.COM 			*val_cntp = 1;
8198118SVasumathi.Sundaram@Sun.COM 		} else {
820*8453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
821*8453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
8228118SVasumathi.Sundaram@Sun.COM 		}
8238118SVasumathi.Sundaram@Sun.COM 
8248118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
8258275SEric Cheng 		if (status == DLADM_STATUS_OK)
8268275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
8275895Syz147064 		break;
8285895Syz147064 
8295895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
8306768Sar224390 		/*
8316768Sar224390 		 * If defaults are not defined for the property,
8326768Sar224390 		 * pd_defval.vd_name should be null. If the driver
8336768Sar224390 		 * has to be contacted for the value, vd_name should
8346768Sar224390 		 * be the empty string (""). Otherwise, dladm will
8356768Sar224390 		 * just print whatever is in the table.
8366768Sar224390 		 */
8375895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
8385895Syz147064 			status = DLADM_STATUS_NOTSUP;
8395895Syz147064 			break;
8405895Syz147064 		}
8416512Ssowmini 
8426512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
843*8453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
844*8453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
8456512Ssowmini 		} else {
8466512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
8476512Ssowmini 		}
8485895Syz147064 		*val_cntp = 1;
8495895Syz147064 		break;
8503448Sdh155122 
8515895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
8525895Syz147064 		if (pdp->pd_getmod != NULL) {
853*8453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
8548118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
8555895Syz147064 			break;
8565895Syz147064 		}
8575895Syz147064 		cnt = pdp->pd_noptval;
8585895Syz147064 		if (cnt == 0) {
8595895Syz147064 			status = DLADM_STATUS_NOTSUP;
8605895Syz147064 		} else if (cnt > *val_cntp) {
8615895Syz147064 			status = DLADM_STATUS_TOOSMALL;
8625895Syz147064 		} else {
8635895Syz147064 			for (i = 0; i < cnt; i++) {
8645895Syz147064 				(void) strcpy(prop_val[i],
8655895Syz147064 				    pdp->pd_optval[i].vd_name);
8665895Syz147064 			}
8675895Syz147064 			*val_cntp = cnt;
8685895Syz147064 		}
8695895Syz147064 		break;
8705895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
8715895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
8725895Syz147064 			return (DLADM_STATUS_TEMPONLY);
873*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
8745895Syz147064 		    prop_val, val_cntp);
8755895Syz147064 		break;
8765895Syz147064 	default:
8775895Syz147064 		status = DLADM_STATUS_BADARG;
8785895Syz147064 		break;
8793147Sxc151355 	}
8803448Sdh155122 
8815895Syz147064 	return (status);
8825895Syz147064 }
8835895Syz147064 
8845895Syz147064 /*ARGSUSED*/
8855895Syz147064 static int
886*8453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
887*8453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
8885895Syz147064 {
8895895Syz147064 	char	*buf, **propvals;
8905895Syz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
8915895Syz147064 
8925895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
8935895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
8945895Syz147064 		return (DLADM_WALK_CONTINUE);
8955895Syz147064 	}
8965895Syz147064 
8975895Syz147064 	propvals = (char **)(void *)buf;
8985895Syz147064 	for (i = 0; i < valcnt; i++) {
8995895Syz147064 		propvals[i] = buf +
9005895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
9015895Syz147064 		    i * DLADM_PROP_VAL_MAX;
9025895Syz147064 	}
9035895Syz147064 
904*8453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
905*8453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
9065895Syz147064 		goto done;
9075895Syz147064 	}
9085895Syz147064 
909*8453SAnurag.Maskey@Sun.COM 	(void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
9105895Syz147064 	    DLADM_OPT_ACTIVE);
9115895Syz147064 
9125895Syz147064 done:
9135895Syz147064 	if (buf != NULL)
9145895Syz147064 		free(buf);
9155895Syz147064 
9165895Syz147064 	return (DLADM_WALK_CONTINUE);
9175895Syz147064 }
9185895Syz147064 
9195895Syz147064 /*ARGSUSED*/
9205895Syz147064 static int
921*8453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
9225895Syz147064 {
9238275SEric Cheng 	datalink_class_t	class;
9248275SEric Cheng 	dladm_status_t		status;
9258275SEric Cheng 
926*8453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
927*8453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9288275SEric Cheng 	if (status != DLADM_STATUS_OK)
9298275SEric Cheng 		return (DLADM_WALK_TERMINATE);
9308275SEric Cheng 
9318275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
932*8453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
9338275SEric Cheng 
9345895Syz147064 	return (DLADM_WALK_CONTINUE);
9355895Syz147064 }
9365895Syz147064 
9375895Syz147064 dladm_status_t
938*8453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
939*8453SAnurag.Maskey@Sun.COM     boolean_t any_media)
9405895Syz147064 {
9416916Sartem 	datalink_media_t	dmedia;
9426916Sartem 	uint32_t		media;
9436916Sartem 
9446916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
9456916Sartem 
9465895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
947*8453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
948*8453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
949*8453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
950*8453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
951*8453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
9526916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
953*8453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, NULL,
954*8453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
9553448Sdh155122 	}
9563448Sdh155122 	return (DLADM_STATUS_OK);
9573147Sxc151355 }
9583147Sxc151355 
9595903Ssowmini /* ARGSUSED */
9605895Syz147064 static dladm_status_t
961*8453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
9628275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
9638275SEric Cheng     uint_t flags, uint_t *perm_flags)
9643147Sxc151355 {
9658275SEric Cheng 	char			zone_name[ZONENAME_MAX];
9668275SEric Cheng 	zoneid_t		zid;
9678275SEric Cheng 	dladm_status_t		status;
9688275SEric Cheng 	char			*cp;
9697342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
9703147Sxc151355 
9716512Ssowmini 	if (flags != 0)
9726512Ssowmini 		return (DLADM_STATUS_NOTSUP);
9736512Ssowmini 
974*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
9758275SEric Cheng 	    &status, perm_flags);
9765895Syz147064 	if (status != DLADM_STATUS_OK)
9773448Sdh155122 		return (status);
9783448Sdh155122 
9797342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
9807342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
9817342SAruna.Ramakrishna@Sun.COM 	free(dip);
9827342SAruna.Ramakrishna@Sun.COM 
9835895Syz147064 	*val_cnt = 1;
9845895Syz147064 	if (zid != GLOBAL_ZONEID) {
9858118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
9865895Syz147064 			return (dladm_errno2status(errno));
9878118SVasumathi.Sundaram@Sun.COM 		}
9883147Sxc151355 
9895895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
9903147Sxc151355 	} else {
9915895Syz147064 		*prop_val[0] = '\0';
9923147Sxc151355 	}
9933147Sxc151355 
9943448Sdh155122 	return (DLADM_STATUS_OK);
9953448Sdh155122 }
9963448Sdh155122 
9973448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
9983448Sdh155122 
9993448Sdh155122 static int
10003448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
10013448Sdh155122 {
10023448Sdh155122 	char			root[MAXPATHLEN];
10033448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
10043448Sdh155122 	void			*dlhandle;
10053448Sdh155122 	void			*sym;
10063448Sdh155122 	int			ret;
10073448Sdh155122 
10083448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
10093448Sdh155122 		return (-1);
10103448Sdh155122 
10113448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
10123448Sdh155122 		(void) dlclose(dlhandle);
10133448Sdh155122 		return (-1);
10143448Sdh155122 	}
10153448Sdh155122 
10163448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
10173448Sdh155122 
10183448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
10193448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
10203448Sdh155122 	(void) dlclose(dlhandle);
10213448Sdh155122 	return (ret);
10223448Sdh155122 }
10233448Sdh155122 
10243448Sdh155122 static dladm_status_t
1025*8453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
1026*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
10273448Sdh155122 {
10283448Sdh155122 	char		path[MAXPATHLEN];
10295895Syz147064 	char		name[MAXLINKNAMELEN];
10303448Sdh155122 	di_prof_t	prof = NULL;
10313448Sdh155122 	char		zone_name[ZONENAME_MAX];
10323448Sdh155122 	dladm_status_t	status;
10335895Syz147064 	int		ret;
10343448Sdh155122 
10353448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
10363448Sdh155122 		return (dladm_errno2status(errno));
10373448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
10383448Sdh155122 		return (dladm_errno2status(errno));
10393448Sdh155122 	if (di_prof_init(path, &prof) != 0)
10403448Sdh155122 		return (dladm_errno2status(errno));
10413448Sdh155122 
1042*8453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
10435895Syz147064 	if (status != DLADM_STATUS_OK)
10445895Syz147064 		goto cleanup;
10455895Syz147064 
10465895Syz147064 	if (add)
10475895Syz147064 		ret = di_prof_add_dev(prof, name);
10485895Syz147064 	else
10495895Syz147064 		ret = di_prof_add_exclude(prof, name);
10505895Syz147064 
10515895Syz147064 	if (ret != 0) {
10523448Sdh155122 		status = dladm_errno2status(errno);
10533448Sdh155122 		goto cleanup;
10543448Sdh155122 	}
10553448Sdh155122 
10563448Sdh155122 	if (di_prof_commit(prof) != 0)
10573448Sdh155122 		status = dladm_errno2status(errno);
10583448Sdh155122 cleanup:
10593448Sdh155122 	if (prof)
10603448Sdh155122 		di_prof_fini(prof);
10613448Sdh155122 
10623448Sdh155122 	return (status);
10633448Sdh155122 }
10643448Sdh155122 
10655903Ssowmini /* ARGSUSED */
10663448Sdh155122 static dladm_status_t
1067*8453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1068*8453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
10693448Sdh155122 {
10708275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
10718275SEric Cheng 	zoneid_t		zid_old, zid_new;
10728275SEric Cheng 	char			link[MAXLINKNAMELEN];
10738275SEric Cheng 	char			*cp;
10747342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
10757342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
10763448Sdh155122 
10773448Sdh155122 	if (val_cnt != 1)
10783448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
10793448Sdh155122 
10807342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
10817342SAruna.Ramakrishna@Sun.COM 
1082*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
10838275SEric Cheng 	    &status, NULL);
10848275SEric Cheng 	if (status != DLADM_STATUS_OK)
10858275SEric Cheng 		return (status);
10868275SEric Cheng 
10878275SEric Cheng 	cp = dip->pr_val;
10888275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
10898275SEric Cheng 	free(dip);
10907342SAruna.Ramakrishna@Sun.COM 
10917342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
10927342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
10933448Sdh155122 
10943448Sdh155122 	/* Do nothing if setting to current value */
10953448Sdh155122 	if (zid_new == zid_old)
10965895Syz147064 		return (status);
10975895Syz147064 
10985895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
10995895Syz147064 		/*
11005895Syz147064 		 * If the new zoneid is the global zone, we could destroy
11015895Syz147064 		 * the link (in the case of an implicitly-created VLAN) as a
11027342SAruna.Ramakrishna@Sun.COM 		 * result of setting the zoneid. In that case, we defer the
11037342SAruna.Ramakrishna@Sun.COM 		 * operation to the end of this function to avoid recreating
11047342SAruna.Ramakrishna@Sun.COM 		 * the VLAN and getting a different linkid during the rollback
11057342SAruna.Ramakrishna@Sun.COM 		 * if other operation fails.
11065895Syz147064 		 *
11077342SAruna.Ramakrishna@Sun.COM 		 * Otherwise, this operation will hold a reference to the
11085895Syz147064 		 * link and prevent a link renaming, so we need to do it
11095895Syz147064 		 * before other operations.
11105895Syz147064 		 */
1111*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
1112*8453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
11135895Syz147064 		if (status != DLADM_STATUS_OK)
11145895Syz147064 			return (status);
11155895Syz147064 	}
11165895Syz147064 
11173448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
11185895Syz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
11193448Sdh155122 		    errno != ENXIO) {
11203448Sdh155122 			status = dladm_errno2status(errno);
11213448Sdh155122 			goto rollback1;
11223448Sdh155122 		}
11233448Sdh155122 
11245895Syz147064 		/*
11255895Syz147064 		 * It is okay to fail to update the /dev entry (some
11265895Syz147064 		 * vanity-named links do not have a /dev entry).
11275895Syz147064 		 */
1128*8453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
1129*8453SAnurag.Maskey@Sun.COM 		    B_FALSE);
11305895Syz147064 	}
11315895Syz147064 
11325895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
11335895Syz147064 		if (zone_add_datalink(zid_new, link) != 0) {
11345895Syz147064 			status = dladm_errno2status(errno);
11355895Syz147064 			goto rollback2;
11365895Syz147064 		}
11375895Syz147064 
1138*8453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
11395895Syz147064 	} else {
1140*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
1141*8453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
11423448Sdh155122 		if (status != DLADM_STATUS_OK)
11433448Sdh155122 			goto rollback2;
11443448Sdh155122 	}
11453448Sdh155122 
11463448Sdh155122 	return (DLADM_STATUS_OK);
11473448Sdh155122 
11483448Sdh155122 rollback2:
11493448Sdh155122 	if (zid_old != GLOBAL_ZONEID)
1150*8453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid, B_TRUE);
11515895Syz147064 	if (zid_old != GLOBAL_ZONEID)
11525895Syz147064 		(void) zone_add_datalink(zid_old, link);
11533448Sdh155122 rollback1:
11547342SAruna.Ramakrishna@Sun.COM 	if (zid_new != GLOBAL_ZONEID) {
11557342SAruna.Ramakrishna@Sun.COM 		dzp->diz_zid = zid_old;
1156*8453SAnurag.Maskey@Sun.COM 		(void) i_dladm_set_public_prop(handle, pdp, linkid, vdp,
1157*8453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
11587342SAruna.Ramakrishna@Sun.COM 	}
11597342SAruna.Ramakrishna@Sun.COM 
11603448Sdh155122 	return (status);
11613448Sdh155122 }
11623448Sdh155122 
11633448Sdh155122 /* ARGSUSED */
11643448Sdh155122 static dladm_status_t
1165*8453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1166*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
11673448Sdh155122 {
11687342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
11697342SAruna.Ramakrishna@Sun.COM 	char		linkname[MAXLINKNAMELEN];
11707342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
11717342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
11727342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
11733448Sdh155122 
11743448Sdh155122 	if (val_cnt != 1)
11753448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
11763448Sdh155122 
11777342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
11787342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
11797342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
11803448Sdh155122 
1181*8453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
11828275SEric Cheng 	    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
11838275SEric Cheng 		goto done;
11847342SAruna.Ramakrishna@Sun.COM 	}
11857342SAruna.Ramakrishna@Sun.COM 
11868275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
11877342SAruna.Ramakrishna@Sun.COM 	if (strlen(linkname) > MAXLINKNAMELEN) {
11887342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
11897342SAruna.Ramakrishna@Sun.COM 		goto done;
11907342SAruna.Ramakrishna@Sun.COM 	}
11917342SAruna.Ramakrishna@Sun.COM 
11927342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
11937342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
11947342SAruna.Ramakrishna@Sun.COM 		goto done;
11957342SAruna.Ramakrishna@Sun.COM 	}
11967342SAruna.Ramakrishna@Sun.COM 
11977342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
11983448Sdh155122 		ushort_t	flags;
11993448Sdh155122 
12007342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
12013448Sdh155122 		    sizeof (flags)) < 0) {
12027342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
12037342SAruna.Ramakrishna@Sun.COM 			goto done;
12043448Sdh155122 		}
12053448Sdh155122 
12063448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
12077342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
12087342SAruna.Ramakrishna@Sun.COM 			goto done;
12093448Sdh155122 		}
12103448Sdh155122 	}
12113448Sdh155122 
12127342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
12137342SAruna.Ramakrishna@Sun.COM 
12147342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
12157342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
12167342SAruna.Ramakrishna@Sun.COM 
12177342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
12185895Syz147064 	return (DLADM_STATUS_OK);
12197342SAruna.Ramakrishna@Sun.COM done:
12207342SAruna.Ramakrishna@Sun.COM 	free(dzp);
12217342SAruna.Ramakrishna@Sun.COM 	return (status);
12225895Syz147064 }
12235895Syz147064 
12245903Ssowmini /* ARGSUSED */
12255895Syz147064 static dladm_status_t
1226*8453SAnurag.Maskey@Sun.COM dld_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12278275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12288275SEric Cheng     uint_t flags, uint_t *perm_flags)
12298275SEric Cheng {
12308275SEric Cheng 	dld_ioc_macprop_t	*dip;
12318275SEric Cheng 	mac_resource_props_t	mrp;
12328275SEric Cheng 	dladm_status_t		status;
12338275SEric Cheng 
1234*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
12358275SEric Cheng 	    &status, perm_flags);
12368275SEric Cheng 	if (dip == NULL)
12378275SEric Cheng 		return (status);
12388275SEric Cheng 
12398275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
12408275SEric Cheng 	free(dip);
12418275SEric Cheng 
12428275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
12438275SEric Cheng 		(*prop_val)[0] = '\0';
12448275SEric Cheng 	} else {
12458275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
12468275SEric Cheng 	}
12478275SEric Cheng 	*val_cnt = 1;
12488275SEric Cheng 	return (DLADM_STATUS_OK);
12498275SEric Cheng }
12508275SEric Cheng 
12518275SEric Cheng /* ARGSUSED */
12528275SEric Cheng static dladm_status_t
1253*8453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1254*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
12558275SEric Cheng {
12568275SEric Cheng 	uint64_t	*maxbw;
12578275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
12588275SEric Cheng 
12598275SEric Cheng 	if (val_cnt != 1)
12608275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
12618275SEric Cheng 
12628275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
12638275SEric Cheng 	if (maxbw == NULL)
12648275SEric Cheng 		return (DLADM_STATUS_NOMEM);
12658275SEric Cheng 
12668275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
12678275SEric Cheng 	if (status != DLADM_STATUS_OK) {
12688275SEric Cheng 		free(maxbw);
12698275SEric Cheng 		return (status);
12708275SEric Cheng 	}
12718275SEric Cheng 
12728275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
12738275SEric Cheng 		free(maxbw);
12748275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
12758275SEric Cheng 	}
12768275SEric Cheng 
12778275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
12788275SEric Cheng 	return (DLADM_STATUS_OK);
12798275SEric Cheng }
12808275SEric Cheng 
12818275SEric Cheng /* ARGSUSED */
12828275SEric Cheng dladm_status_t
12838275SEric Cheng do_extract_maxbw(val_desc_t *vdp, void *arg, uint_t cnt)
12848275SEric Cheng {
12858275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
12868275SEric Cheng 
12878275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
12888275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
12898275SEric Cheng 
12908275SEric Cheng 	return (DLADM_STATUS_OK);
12918275SEric Cheng }
12928275SEric Cheng 
12938275SEric Cheng /* ARGSUSED */
12948275SEric Cheng static dladm_status_t
1295*8453SAnurag.Maskey@Sun.COM dld_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12968275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12978275SEric Cheng     uint_t flags, uint_t *perm_flags)
12988275SEric Cheng {
12998275SEric Cheng 	dld_ioc_macprop_t	*dip;
13008275SEric Cheng 	mac_resource_props_t	mrp;
13018275SEric Cheng 	int			i;
13028275SEric Cheng 	uint32_t		ncpus;
13038275SEric Cheng 	uchar_t			*cp;
13048275SEric Cheng 	dladm_status_t		status;
13058275SEric Cheng 
1306*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13078275SEric Cheng 	    &status, perm_flags);
13088275SEric Cheng 	if (dip == NULL)
13098275SEric Cheng 		return (status);
13108275SEric Cheng 
13118275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
13128275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
13138275SEric Cheng 	free(dip);
13148275SEric Cheng 
13158275SEric Cheng 	ncpus = mrp.mrp_ncpus;
13168275SEric Cheng 
13178275SEric Cheng 	if (ncpus > *val_cnt)
13188275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
13198275SEric Cheng 
13208275SEric Cheng 	if (ncpus == 0) {
13218275SEric Cheng 		(*prop_val)[0] = '\0';
13228275SEric Cheng 		*val_cnt = 1;
13238275SEric Cheng 		return (DLADM_STATUS_OK);
13248275SEric Cheng 	}
13258275SEric Cheng 
13268275SEric Cheng 	*val_cnt = ncpus;
13278275SEric Cheng 	for (i = 0; i < ncpus; i++) {
13288275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
13298275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
13308275SEric Cheng 	}
13318275SEric Cheng 	return (DLADM_STATUS_OK);
13328275SEric Cheng }
13338275SEric Cheng 
13348275SEric Cheng /* ARGSUSED */
13358275SEric Cheng static dladm_status_t
1336*8453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1337*8453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13388275SEric Cheng {
13398275SEric Cheng 	mac_resource_props_t	mrp;
13408275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
13418275SEric Cheng 	dld_ioc_macprop_t	*dip;
13428275SEric Cheng 
13438275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
13448275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
13458275SEric Cheng 	    flags, &status);
13468275SEric Cheng 
13478275SEric Cheng 	if (dip == NULL)
13488275SEric Cheng 		return (status);
13498275SEric Cheng 
13508275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
13518275SEric Cheng 		switch (dip->pr_num) {
13528275SEric Cheng 		case MAC_PROP_MAXBW:
13538275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
13548275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
13558275SEric Cheng 			break;
13568275SEric Cheng 		case MAC_PROP_PRIO:
13578275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
13588275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
13598275SEric Cheng 			break;
13608275SEric Cheng 		default:
13618275SEric Cheng 			free(dip);
13628275SEric Cheng 			return (DLADM_STATUS_BADARG);
13638275SEric Cheng 		}
13648275SEric Cheng 	} else {
13658275SEric Cheng 		switch (dip->pr_num) {
13668275SEric Cheng 		case MAC_PROP_MAXBW:
13678275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
13688275SEric Cheng 			    sizeof (uint64_t));
13698275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
13708275SEric Cheng 			break;
13718275SEric Cheng 		case MAC_PROP_PRIO:
13728275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
13738275SEric Cheng 			    sizeof (mac_priority_level_t));
13748275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
13758275SEric Cheng 			break;
13768275SEric Cheng 		default:
13778275SEric Cheng 			free(dip);
13788275SEric Cheng 			return (DLADM_STATUS_BADARG);
13798275SEric Cheng 		}
13808275SEric Cheng 	}
13818275SEric Cheng 
13828275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
1383*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
13848275SEric Cheng 	free(dip);
13858275SEric Cheng 	return (status);
13868275SEric Cheng }
13878275SEric Cheng 
13888275SEric Cheng /* ARGSUSED */
13898275SEric Cheng static dladm_status_t
1390*8453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1391*8453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13928275SEric Cheng {
13938275SEric Cheng 	mac_resource_props_t	mrp;
13948275SEric Cheng 	dladm_status_t		status;
13958275SEric Cheng 	dld_ioc_macprop_t	*dip;
13968275SEric Cheng 	datalink_class_t	class;
13978275SEric Cheng 
13988275SEric Cheng 	/*
13998275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
14008275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
14018275SEric Cheng 	 * the phys_info test only on physical links.
14028275SEric Cheng 	 */
1403*8453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
14048275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
14058275SEric Cheng 		return (status);
14068275SEric Cheng 	}
14078275SEric Cheng 
14088275SEric Cheng 	/*
14098275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
14108275SEric Cheng 	 * if possible when the setup is complete in MAC.
14118275SEric Cheng 	 */
14128275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
14138275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
14148275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
14158275SEric Cheng 		mac_resource_props_t	*vmrp;
14168275SEric Cheng 
14178275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
14188275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
14198275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
14208275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
14218275SEric Cheng 		}
14228275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
14238275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
14248275SEric Cheng 		mrp.mrp_intr_cpu = -1;
14258275SEric Cheng 	}
14268275SEric Cheng 
14278275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
14288275SEric Cheng 	    flags, &status);
14298275SEric Cheng 	if (dip == NULL)
14308275SEric Cheng 		return (status);
14318275SEric Cheng 
14328275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
1433*8453SAnurag.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
1440*8453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1441*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14428275SEric Cheng {
14438275SEric Cheng 	uint32_t		cpuid;
14448275SEric Cheng 	int			i, j, rc;
14458275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
14468275SEric Cheng 	mac_resource_props_t	*mrp;
14478275SEric Cheng 
14488275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
14498275SEric Cheng 	if (mrp == NULL)
14508275SEric Cheng 		return (DLADM_STATUS_NOMEM);
14518275SEric Cheng 
14528275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
14538275SEric Cheng 		errno = 0;
14548275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
14558275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
14568275SEric Cheng 			free(mrp);
14578275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
14588275SEric Cheng 		}
14598275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
14608275SEric Cheng 		if (rc < 1) {
14618275SEric Cheng 			free(mrp);
14628275SEric Cheng 			return (DLADM_STATUS_CPUERR);
14638275SEric Cheng 		}
14648275SEric Cheng 		if (rc != P_ONLINE) {
14658275SEric Cheng 			free(mrp);
14668275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
14678275SEric Cheng 		}
14688275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
14698275SEric Cheng 	}
14708275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
14718275SEric Cheng 
14728275SEric Cheng 	/* Check for duplicates */
14738275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
14748275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
14758275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
14768275SEric Cheng 				free(mrp);
14778275SEric Cheng 				return (DLADM_STATUS_BADARG);
14788275SEric Cheng 			}
14798275SEric Cheng 		}
14808275SEric Cheng 	}
14818275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
14828275SEric Cheng 
14838275SEric Cheng 	return (DLADM_STATUS_OK);
14848275SEric Cheng }
14858275SEric Cheng 
14868275SEric Cheng /* ARGSUSED */
14878275SEric Cheng dladm_status_t
14888275SEric Cheng do_extract_cpus(val_desc_t *vdp, void *arg, uint_t cnt)
14898275SEric Cheng {
14908275SEric Cheng 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
14918275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
14928275SEric Cheng 	int			i;
14938275SEric Cheng 
14948275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
14958275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
14968275SEric Cheng 	}
14978275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
14988275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
14998275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
15008275SEric Cheng 
15018275SEric Cheng 	return (DLADM_STATUS_OK);
15028275SEric Cheng }
15038275SEric Cheng 
15048275SEric Cheng /* ARGSUSED */
15058275SEric Cheng static dladm_status_t
1506*8453SAnurag.Maskey@Sun.COM dld_priority_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15078275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15088275SEric Cheng     uint_t flags, uint_t *perm_flags)
15098275SEric Cheng {
15108275SEric Cheng 	dld_ioc_macprop_t	*dip;
15118275SEric Cheng 	mac_resource_props_t	mrp;
15128275SEric Cheng 	mac_priority_level_t	pri;
15138275SEric Cheng 	dladm_status_t		status;
15148275SEric Cheng 
1515*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15168275SEric Cheng 	    &status, perm_flags);
15178275SEric Cheng 	if (dip == NULL)
15188275SEric Cheng 		return (status);
15198275SEric Cheng 
15208275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
15218275SEric Cheng 	free(dip);
15228275SEric Cheng 
15238275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
15248275SEric Cheng 	    mrp.mrp_priority;
15258275SEric Cheng 
15268275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
15278275SEric Cheng 	*val_cnt = 1;
15288275SEric Cheng 	return (DLADM_STATUS_OK);
15298275SEric Cheng }
15308275SEric Cheng 
15318275SEric Cheng /* ARGSUSED */
15328275SEric Cheng static dladm_status_t
1533*8453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1534*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
15358275SEric Cheng {
15368275SEric Cheng 	mac_priority_level_t	*pri;
15378275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15388275SEric Cheng 
15398275SEric Cheng 	if (val_cnt != 1)
15408275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15418275SEric Cheng 
15428275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
15438275SEric Cheng 	if (pri == NULL)
15448275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15458275SEric Cheng 
15468275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
15478275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15488275SEric Cheng 		free(pri);
15498275SEric Cheng 		return (status);
15508275SEric Cheng 	}
15518275SEric Cheng 
15528275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
15538275SEric Cheng 		free(pri);
15548275SEric Cheng 		return (DLADM_STATUS_BADVAL);
15558275SEric Cheng 	}
15568275SEric Cheng 
15578275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
15588275SEric Cheng 	return (DLADM_STATUS_OK);
15598275SEric Cheng }
15608275SEric Cheng 
15618275SEric Cheng /* ARGSUSED */
15628275SEric Cheng dladm_status_t
15638275SEric Cheng do_extract_priority(val_desc_t *vdp, void *arg, uint_t cnt)
15648275SEric Cheng {
15658275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
15668275SEric Cheng 
15678275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
15688275SEric Cheng 	    sizeof (mac_priority_level_t));
15698275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
15708275SEric Cheng 
15718275SEric Cheng 	return (DLADM_STATUS_OK);
15728275SEric Cheng }
15738275SEric Cheng 
15748275SEric Cheng /* ARGSUSED */
15758275SEric Cheng static dladm_status_t
1576*8453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15778275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15788275SEric Cheng     uint_t flags, uint_t *perm_flags)
15795895Syz147064 {
15807342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
15817342SAruna.Ramakrishna@Sun.COM 	int		i, len;
15827342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
15837342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
15845895Syz147064 
15856789Sam223141 	if (flags & MAC_PROP_DEFAULT)
15867776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
15876512Ssowmini 
15885895Syz147064 	*val_cnt = 1;
1589*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15908275SEric Cheng 	    &status, perm_flags);
15917342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
15925895Syz147064 		(*prop_val)[0] = '\0';
15938275SEric Cheng 		return (DLADM_STATUS_OK);
15945895Syz147064 	}
15957342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
15965895Syz147064 
15977342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
15985895Syz147064 		if (i != 0) {
15995895Syz147064 			(void) snprintf(*prop_val + len,
16005895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
16015895Syz147064 			len += 1;
16025895Syz147064 		}
16035895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
16047342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
16057342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
16067342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
16075895Syz147064 			(void) snprintf(*prop_val + len,
16085895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
16095895Syz147064 			    AP_ANCHOR);
16105895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
16115895Syz147064 		}
16125895Syz147064 	}
16137342SAruna.Ramakrishna@Sun.COM 	free(dip);
16145895Syz147064 done:
16155895Syz147064 	return (DLADM_STATUS_OK);
16165895Syz147064 }
16175895Syz147064 
16185895Syz147064 /*
16195895Syz147064  * Add the specified module to the dlautopush structure; returns a
16205895Syz147064  * DLADM_STATUS_* code.
16215895Syz147064  */
16225895Syz147064 dladm_status_t
16235895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
16245895Syz147064 {
16255895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
16265895Syz147064 		return (DLADM_STATUS_BADVAL);
16275895Syz147064 
16285895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
16295895Syz147064 		/*
16305895Syz147064 		 * We don't allow multiple anchors, and the anchor must
16315895Syz147064 		 * be after at least one module.
16325895Syz147064 		 */
16335895Syz147064 		if (dlap->dap_anchor != 0)
16345895Syz147064 			return (DLADM_STATUS_BADVAL);
16355895Syz147064 		if (dlap->dap_npush == 0)
16365895Syz147064 			return (DLADM_STATUS_BADVAL);
16375895Syz147064 
16385895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
16395895Syz147064 		return (DLADM_STATUS_OK);
16405895Syz147064 	}
16415895Syz147064 	if (dlap->dap_npush > MAXAPUSH)
16425895Syz147064 		return (DLADM_STATUS_BADVALCNT);
16435895Syz147064 
16445895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
16455895Syz147064 	    FMNAMESZ + 1);
16465895Syz147064 
16475895Syz147064 	return (DLADM_STATUS_OK);
16485895Syz147064 }
16495895Syz147064 
16505895Syz147064 /*
16515895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
16525895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
16535895Syz147064  * latter is used in the autopush(1M) file.
16545895Syz147064  */
16555895Syz147064 /* ARGSUSED */
16565895Syz147064 static dladm_status_t
1657*8453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1658*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
16595895Syz147064 {
16605895Syz147064 	char			*module;
16615895Syz147064 	struct dlautopush	*dlap;
16625895Syz147064 	dladm_status_t		status;
16635895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
16645895Syz147064 	char			delimiters[4];
16655895Syz147064 
16665895Syz147064 	if (val_cnt != 1)
16675895Syz147064 		return (DLADM_STATUS_BADVALCNT);
16685895Syz147064 
16697342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
16707342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
16717342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
16727342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
16733448Sdh155122 
16747342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
16757342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
16767342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
16777342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
16787342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
16797342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
16807342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
16817342SAruna.Ramakrishna@Sun.COM 				return (status);
16827342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
16837342SAruna.Ramakrishna@Sun.COM 		}
16847342SAruna.Ramakrishna@Sun.COM 
16857342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
16867342SAruna.Ramakrishna@Sun.COM 	} else {
16877342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
16885895Syz147064 	}
16893448Sdh155122 	return (DLADM_STATUS_OK);
16903448Sdh155122 }
16913448Sdh155122 
16927663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
16937663SSowmini.Varadhan@Sun.COM 
16945903Ssowmini /* ARGSUSED */
16953448Sdh155122 static dladm_status_t
1696*8453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
1697*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
1698*8453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
16993448Sdh155122 {
17005895Syz147064 	wl_rates_t	*wrp;
17015895Syz147064 	uint_t		i;
17025895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
17035895Syz147064 
17047663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
17057663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
17067663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
17075895Syz147064 
1708*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
1709*8453SAnurag.Maskey@Sun.COM 	    B_FALSE);
17105895Syz147064 	if (status != DLADM_STATUS_OK)
17115895Syz147064 		goto done;
17125895Syz147064 
17135895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
17145895Syz147064 		status = DLADM_STATUS_TOOSMALL;
17155895Syz147064 		goto done;
17165895Syz147064 	}
17175895Syz147064 
17185895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
17195895Syz147064 		prop_val[0][0] = '\0';
17205895Syz147064 		*val_cnt = 1;
17215895Syz147064 		goto done;
17225895Syz147064 	}
17235895Syz147064 
17245895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
17255895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
17265895Syz147064 		    wrp->wl_rates_rates[i] % 2,
17275895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
17285895Syz147064 	}
17295895Syz147064 	*val_cnt = wrp->wl_rates_num;
17308275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
17313448Sdh155122 
17325895Syz147064 done:
17337663SSowmini.Varadhan@Sun.COM 	free(wrp);
17345895Syz147064 	return (status);
17355895Syz147064 }
17365895Syz147064 
17375895Syz147064 static dladm_status_t
1738*8453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17398275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
17408275SEric Cheng     uint_t flags, uint_t *perm_flags)
17415895Syz147064 {
17428118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
1743*8453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
17448275SEric Cheng 		    val_cnt, flags, perm_flags));
17458118SVasumathi.Sundaram@Sun.COM 	}
17465960Ssowmini 
1747*8453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
17488275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
17495895Syz147064 }
17505895Syz147064 
17516512Ssowmini /* ARGSUSED */
17525895Syz147064 static dladm_status_t
1753*8453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17548275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
17558275SEric Cheng     uint_t flags, uint_t *perm_flags)
17565895Syz147064 {
17575960Ssowmini 	switch (media) {
17585960Ssowmini 	case DL_ETHER:
17596512Ssowmini 		/*
17606512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
17616512Ssowmini 		 * links can have a speed of 5.5 Gbps.
17626512Ssowmini 		 */
17636512Ssowmini 		return (DLADM_STATUS_NOTSUP);
17645960Ssowmini 
17655960Ssowmini 	case DL_WIFI:
1766*8453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
1767*8453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
17685960Ssowmini 	default:
17695960Ssowmini 		return (DLADM_STATUS_BADARG);
17705960Ssowmini 	}
17715895Syz147064 }
17725895Syz147064 
17735895Syz147064 static dladm_status_t
1774*8453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
1775*8453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
17765895Syz147064 {
17775895Syz147064 	int		i;
17785895Syz147064 	uint_t		len;
17795895Syz147064 	wl_rates_t	*wrp;
17805895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
17815895Syz147064 
17827663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
17837663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
17845895Syz147064 		return (DLADM_STATUS_NOMEM);
17855895Syz147064 
17867663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
17875895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
17885895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
17895895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
17905895Syz147064 
17915895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
17925895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
1793*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
1794*8453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
17955895Syz147064 
17967663SSowmini.Varadhan@Sun.COM 	free(wrp);
17975895Syz147064 	return (status);
17985895Syz147064 }
17993448Sdh155122 
18005903Ssowmini /* ARGSUSED */
18015895Syz147064 static dladm_status_t
1802*8453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18035960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
18045895Syz147064 {
18055895Syz147064 	dladm_wlan_rates_t	rates;
18065895Syz147064 	dladm_status_t		status;
18075895Syz147064 
18085960Ssowmini 	/*
18095960Ssowmini 	 * can currently set rate on WIFI links only.
18105960Ssowmini 	 */
18115960Ssowmini 	if (media != DL_WIFI)
18125960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
18135960Ssowmini 
18145895Syz147064 	if (val_cnt != 1)
18155895Syz147064 		return (DLADM_STATUS_BADVALCNT);
18165895Syz147064 
18175895Syz147064 	rates.wr_cnt = 1;
18185895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
18195895Syz147064 
1820*8453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
18215895Syz147064 
18225895Syz147064 done:
18235895Syz147064 	return (status);
18245895Syz147064 }
18253448Sdh155122 
18265895Syz147064 /* ARGSUSED */
18275895Syz147064 static dladm_status_t
1828*8453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1829*8453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
18305895Syz147064 {
18315895Syz147064 	int		i;
18325895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
18335895Syz147064 	char		*buf, **modval;
18345895Syz147064 	dladm_status_t	status;
18358118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
18365895Syz147064 
18375895Syz147064 	if (val_cnt != 1)
18385895Syz147064 		return (DLADM_STATUS_BADVALCNT);
18395895Syz147064 
18405895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
18415895Syz147064 	    MAX_SUPPORT_RATES);
18425895Syz147064 	if (buf == NULL) {
18435895Syz147064 		status = DLADM_STATUS_NOMEM;
18445895Syz147064 		goto done;
18455895Syz147064 	}
18463448Sdh155122 
18475895Syz147064 	modval = (char **)(void *)buf;
18485895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
18495895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
18505895Syz147064 		    i * DLADM_STRSIZE;
18515895Syz147064 	}
18525895Syz147064 
1853*8453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
1854*8453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
18555895Syz147064 	if (status != DLADM_STATUS_OK)
18565895Syz147064 		goto done;
18575895Syz147064 
18585895Syz147064 	for (i = 0; i < modval_cnt; i++) {
18595895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
18605903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
18615903Ssowmini 			    (atof(*prop_val) * 2);
18625895Syz147064 			status = DLADM_STATUS_OK;
18633448Sdh155122 			break;
18643448Sdh155122 		}
18655895Syz147064 	}
18665895Syz147064 	if (i == modval_cnt)
18675895Syz147064 		status = DLADM_STATUS_BADVAL;
18685895Syz147064 done:
18695895Syz147064 	free(buf);
18705895Syz147064 	return (status);
18715895Syz147064 }
18725895Syz147064 
18735895Syz147064 static dladm_status_t
1874*8453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
1875*8453SAnurag.Maskey@Sun.COM     int buflen)
18765895Syz147064 {
1877*8453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
18787663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
18795895Syz147064 }
18805895Syz147064 
18815903Ssowmini /* ARGSUSED */
18825895Syz147064 static dladm_status_t
1883*8453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
1884*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
1885*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
18865895Syz147064 {
18875895Syz147064 	uint32_t	channel;
18887663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
18895895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
18907663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
18915895Syz147064 
1892*8453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
18937663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
18945895Syz147064 		goto done;
18955895Syz147064 
18967663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
18977663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
18985895Syz147064 		status = DLADM_STATUS_NOTFOUND;
18995895Syz147064 		goto done;
19005895Syz147064 	}
19015895Syz147064 
19025895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
19035895Syz147064 	*val_cnt = 1;
19048275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
19055895Syz147064 done:
19065895Syz147064 	return (status);
19075895Syz147064 }
19085895Syz147064 
19095895Syz147064 static dladm_status_t
1910*8453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
1911*8453SAnurag.Maskey@Sun.COM     int buflen)
19125895Syz147064 {
1913*8453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
19147663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
19155895Syz147064 }
19165895Syz147064 
19175903Ssowmini /* ARGSUSED */
19185895Syz147064 static dladm_status_t
1919*8453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
1920*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
1921*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
19225895Syz147064 {
19237663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
19245895Syz147064 	const char	*s;
19257663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
19265895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
19275895Syz147064 
1928*8453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
19297663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
19305895Syz147064 		goto done;
19315895Syz147064 
19327663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
19337663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
19345895Syz147064 	case WL_PM_AM:
19355895Syz147064 		s = "off";
19365895Syz147064 		break;
19375895Syz147064 	case WL_PM_MPS:
19385895Syz147064 		s = "max";
19395895Syz147064 		break;
19405895Syz147064 	case WL_PM_FAST:
19415895Syz147064 		s = "fast";
19423448Sdh155122 		break;
19433448Sdh155122 	default:
19445895Syz147064 		status = DLADM_STATUS_NOTFOUND;
19455895Syz147064 		goto done;
19465895Syz147064 	}
19475895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
19485895Syz147064 	*val_cnt = 1;
19498275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
19505895Syz147064 done:
19515895Syz147064 	return (status);
19525895Syz147064 }
19535895Syz147064 
19545895Syz147064 static dladm_status_t
1955*8453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
1956*8453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
19575895Syz147064 {
19585895Syz147064 	wl_ps_mode_t    ps_mode;
19595895Syz147064 
19605895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
19615895Syz147064 
19625895Syz147064 	switch (*pm) {
19635895Syz147064 	case DLADM_WLAN_PM_OFF:
19645895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
19653448Sdh155122 		break;
19665895Syz147064 	case DLADM_WLAN_PM_MAX:
19675895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
19685895Syz147064 		break;
19695895Syz147064 	case DLADM_WLAN_PM_FAST:
19705895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
19715895Syz147064 		break;
19725895Syz147064 	default:
19735895Syz147064 		return (DLADM_STATUS_NOTSUP);
19743448Sdh155122 	}
1975*8453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
1976*8453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
19775895Syz147064 }
19785895Syz147064 
19795895Syz147064 /* ARGSUSED */
19805895Syz147064 static dladm_status_t
1981*8453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
1982*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
1983*8453SAnurag.Maskey@Sun.COM     datalink_media_t media)
19845895Syz147064 {
19855895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
19865895Syz147064 	dladm_status_t status;
19875895Syz147064 
19885895Syz147064 	if (val_cnt != 1)
19895895Syz147064 		return (DLADM_STATUS_BADVALCNT);
19905895Syz147064 
1991*8453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
19923448Sdh155122 
19933448Sdh155122 	return (status);
19943448Sdh155122 }
19953448Sdh155122 
19963448Sdh155122 static dladm_status_t
1997*8453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
19983448Sdh155122 {
1999*8453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
2000*8453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
20015895Syz147064 }
20023448Sdh155122 
20035903Ssowmini /* ARGSUSED */
20045895Syz147064 static dladm_status_t
2005*8453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20068275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
20078275SEric Cheng     uint_t flags, uint_t *perm_flags)
20085895Syz147064 {
20095895Syz147064 	wl_radio_t	radio;
20105895Syz147064 	const char	*s;
20117663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
20125895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
20133448Sdh155122 
2014*8453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
20157663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
20165895Syz147064 		goto done;
20173448Sdh155122 
20187663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
20195895Syz147064 	switch (radio) {
20205895Syz147064 	case B_TRUE:
20215895Syz147064 		s = "on";
20225895Syz147064 		break;
20235895Syz147064 	case B_FALSE:
20245895Syz147064 		s = "off";
20255895Syz147064 		break;
20265895Syz147064 	default:
20275895Syz147064 		status = DLADM_STATUS_NOTFOUND;
20285895Syz147064 		goto done;
20295895Syz147064 	}
20305895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
20315895Syz147064 	*val_cnt = 1;
20328275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
20335895Syz147064 done:
20343448Sdh155122 	return (status);
20353448Sdh155122 }
20363448Sdh155122 
20373448Sdh155122 static dladm_status_t
2038*8453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
2039*8453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
20403448Sdh155122 {
20415895Syz147064 	wl_radio_t r;
20423448Sdh155122 
20435895Syz147064 	switch (*radio) {
20445895Syz147064 	case DLADM_WLAN_RADIO_ON:
20455895Syz147064 		r = B_TRUE;
20465895Syz147064 		break;
20475895Syz147064 	case DLADM_WLAN_RADIO_OFF:
20485895Syz147064 		r = B_FALSE;
20495895Syz147064 		break;
20505895Syz147064 	default:
20515895Syz147064 		return (DLADM_STATUS_NOTSUP);
20525895Syz147064 	}
2053*8453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
20547663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
20555895Syz147064 }
20563448Sdh155122 
20575895Syz147064 /* ARGSUSED */
20585895Syz147064 static dladm_status_t
2059*8453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20605960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
20615895Syz147064 {
20625895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
20635895Syz147064 	dladm_status_t status;
20643448Sdh155122 
20655895Syz147064 	if (val_cnt != 1)
20665895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20675895Syz147064 
2068*8453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
20693448Sdh155122 
20703448Sdh155122 	return (status);
20713448Sdh155122 }
20723448Sdh155122 
20735895Syz147064 static dladm_status_t
2074*8453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
2075*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
20763448Sdh155122 {
20775895Syz147064 	char		buf[MAXLINELEN];
20785895Syz147064 	int		i;
20795895Syz147064 	dladm_conf_t	conf;
20805895Syz147064 	dladm_status_t	status;
20813448Sdh155122 
2082*8453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
20835895Syz147064 	if (status != DLADM_STATUS_OK)
20845895Syz147064 		return (status);
20853448Sdh155122 
20865895Syz147064 	/*
20875895Syz147064 	 * reset case.
20885895Syz147064 	 */
20895895Syz147064 	if (val_cnt == 0) {
2090*8453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
20915895Syz147064 		if (status == DLADM_STATUS_OK)
2092*8453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
20935895Syz147064 		goto done;
20945895Syz147064 	}
20953448Sdh155122 
20965895Syz147064 	buf[0] = '\0';
20975895Syz147064 	for (i = 0; i < val_cnt; i++) {
20985895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
20995895Syz147064 		if (i != val_cnt - 1)
21005895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
21013448Sdh155122 	}
21023448Sdh155122 
2103*8453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
2104*8453SAnurag.Maskey@Sun.COM 	    buf);
21055895Syz147064 	if (status == DLADM_STATUS_OK)
2106*8453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
21075895Syz147064 
21085895Syz147064 done:
2109*8453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
21105895Syz147064 	return (status);
21113448Sdh155122 }
21125895Syz147064 
21135895Syz147064 static dladm_status_t
2114*8453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
2115*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
21165895Syz147064 {
21175895Syz147064 	char		buf[MAXLINELEN], *str;
21185895Syz147064 	uint_t		cnt = 0;
21195895Syz147064 	dladm_conf_t	conf;
21205895Syz147064 	dladm_status_t	status;
21215895Syz147064 
2122*8453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
21235895Syz147064 	if (status != DLADM_STATUS_OK)
21245895Syz147064 		return (status);
21255895Syz147064 
2126*8453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
21275895Syz147064 	if (status != DLADM_STATUS_OK)
21285895Syz147064 		goto done;
21295895Syz147064 
21305895Syz147064 	str = strtok(buf, ",");
21315895Syz147064 	while (str != NULL) {
21325895Syz147064 		if (cnt == *val_cntp) {
21335895Syz147064 			status = DLADM_STATUS_TOOSMALL;
21345895Syz147064 			goto done;
21355895Syz147064 		}
21365895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
21375895Syz147064 		str = strtok(NULL, ",");
21385895Syz147064 	}
21395895Syz147064 
21405895Syz147064 	*val_cntp = cnt;
21415895Syz147064 
21425895Syz147064 done:
2143*8453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
21445895Syz147064 	return (status);
21455895Syz147064 }
21465903Ssowmini 
21477663SSowmini.Varadhan@Sun.COM static link_attr_t *
21485903Ssowmini dladm_name2prop(const char *prop_name)
21495903Ssowmini {
21507663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
21515903Ssowmini 
21527663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
21535903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
21545903Ssowmini 			break;
21555903Ssowmini 	}
21565903Ssowmini 	return (p);
21575903Ssowmini }
21585903Ssowmini 
21597663SSowmini.Varadhan@Sun.COM static link_attr_t *
21607663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
21617663SSowmini.Varadhan@Sun.COM {
21627663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
21637663SSowmini.Varadhan@Sun.COM 
21647663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
21657663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
21667663SSowmini.Varadhan@Sun.COM 			break;
21677663SSowmini.Varadhan@Sun.COM 	}
21687663SSowmini.Varadhan@Sun.COM 	return (p);
21697663SSowmini.Varadhan@Sun.COM }
21705903Ssowmini 
21716789Sam223141 static dld_ioc_macprop_t *
21727663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
21737663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
21747663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
21755903Ssowmini {
21765903Ssowmini 	int dsize;
21776789Sam223141 	dld_ioc_macprop_t *dip;
21785903Ssowmini 
21795903Ssowmini 	*status = DLADM_STATUS_OK;
21806789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
21815903Ssowmini 	dip = malloc(dsize);
21825903Ssowmini 	if (dip == NULL) {
21835903Ssowmini 		*status = DLADM_STATUS_NOMEM;
21845903Ssowmini 		return (NULL);
21855903Ssowmini 	}
21865903Ssowmini 	bzero(dip, dsize);
21875903Ssowmini 	dip->pr_valsize = valsize;
21886512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
21896789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
21905960Ssowmini 	dip->pr_linkid = linkid;
21917663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
21926512Ssowmini 	dip->pr_flags = flags;
21935903Ssowmini 	return (dip);
21945903Ssowmini }
21955903Ssowmini 
21967663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
21977663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
21987663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
21997663SSowmini.Varadhan@Sun.COM {
22007663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
22017663SSowmini.Varadhan@Sun.COM 
22027663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
22037663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
22047663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
22057663SSowmini.Varadhan@Sun.COM 	    flags, status));
22067663SSowmini.Varadhan@Sun.COM }
22077663SSowmini.Varadhan@Sun.COM 
22087663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
22097663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
22107663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
22117663SSowmini.Varadhan@Sun.COM {
22127663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
22137663SSowmini.Varadhan@Sun.COM 
22147663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
22157663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
22167663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
22177663SSowmini.Varadhan@Sun.COM 	    flags, status));
22187663SSowmini.Varadhan@Sun.COM }
22197663SSowmini.Varadhan@Sun.COM 
22205903Ssowmini /* ARGSUSED */
22215903Ssowmini static dladm_status_t
2222*8453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
2223*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
2224*8453SAnurag.Maskey@Sun.COM     datalink_media_t media)
22255903Ssowmini {
22266789Sam223141 	dld_ioc_macprop_t	*dip;
22275903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
22285903Ssowmini 	uint8_t		u8;
22295903Ssowmini 	uint16_t	u16;
22305903Ssowmini 	uint32_t	u32;
22315903Ssowmini 	void		*val;
22325903Ssowmini 
22338275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
22345903Ssowmini 	if (dip == NULL)
22355903Ssowmini 		return (status);
22365903Ssowmini 
22378275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
22385903Ssowmini 		val = (void *)vdp->vd_val;
22395903Ssowmini 	else {
22405903Ssowmini 		/*
22415903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
22425903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
22435903Ssowmini 		 */
22445903Ssowmini 		switch (dip->pr_valsize) {
22455903Ssowmini 		case 1:
22465903Ssowmini 			u8 = vdp->vd_val;
22475903Ssowmini 			val = &u8;
22485903Ssowmini 			break;
22495903Ssowmini 		case 2:
22505903Ssowmini 			u16 = vdp->vd_val;
22515903Ssowmini 			val = &u16;
22525903Ssowmini 			break;
22535903Ssowmini 		case 4:
22545903Ssowmini 			u32 = vdp->vd_val;
22555903Ssowmini 			val = &u32;
22565903Ssowmini 			break;
22575903Ssowmini 		default:
22585903Ssowmini 			val = &vdp->vd_val;
22595903Ssowmini 			break;
22605903Ssowmini 		}
22615903Ssowmini 	}
22625903Ssowmini 
22637342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
22647342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
22657342SAruna.Ramakrishna@Sun.COM 	else
22667342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
22677342SAruna.Ramakrishna@Sun.COM 
2268*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
22697663SSowmini.Varadhan@Sun.COM 
22707663SSowmini.Varadhan@Sun.COM done:
22717663SSowmini.Varadhan@Sun.COM 	free(dip);
22727663SSowmini.Varadhan@Sun.COM 	return (status);
22737663SSowmini.Varadhan@Sun.COM }
22747663SSowmini.Varadhan@Sun.COM 
22757663SSowmini.Varadhan@Sun.COM dladm_status_t
2276*8453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
22777663SSowmini.Varadhan@Sun.COM {
22787663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
22797663SSowmini.Varadhan@Sun.COM 
2280*8453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
2281*8453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
22825903Ssowmini 		status = dladm_errno2status(errno);
2283*8453SAnurag.Maskey@Sun.COM 
22845903Ssowmini 	return (status);
22855903Ssowmini }
22865903Ssowmini 
22876789Sam223141 static dld_ioc_macprop_t *
2288*8453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
2289*8453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
22905903Ssowmini {
22916789Sam223141 	dld_ioc_macprop_t *dip = NULL;
22926512Ssowmini 
22937663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
22946512Ssowmini 	if (dip == NULL)
22956512Ssowmini 		return (NULL);
22965903Ssowmini 
2297*8453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
22986512Ssowmini 	if (*status != DLADM_STATUS_OK) {
22996512Ssowmini 		free(dip);
23006512Ssowmini 		return (NULL);
23016512Ssowmini 	}
23028275SEric Cheng 	if (perm_flags != NULL)
23038275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
23048275SEric Cheng 
23056512Ssowmini 	return (dip);
23065903Ssowmini }
23075903Ssowmini 
23085903Ssowmini /* ARGSUSED */
23095903Ssowmini static dladm_status_t
2310*8453SAnurag.Maskey@Sun.COM i_dladm_defmtu_check(dladm_handle_t handle, prop_desc_t *pdp,
2311*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
2312*8453SAnurag.Maskey@Sun.COM     datalink_media_t media)
23135903Ssowmini {
23145903Ssowmini 	if (val_cnt != 1)
23155903Ssowmini 		return (DLADM_STATUS_BADVAL);
23166512Ssowmini 	v->vd_val = atoi(prop_val[0]);
23175903Ssowmini 	return (DLADM_STATUS_OK);
23185903Ssowmini }
23195903Ssowmini 
23205903Ssowmini /* ARGSUSED */
23215903Ssowmini static dladm_status_t
2322*8453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
2323*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2324*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23255903Ssowmini {
23265903Ssowmini 	link_duplex_t   link_duplex;
23275903Ssowmini 	dladm_status_t  status;
23285903Ssowmini 
2329*8453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
23305903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
23315903Ssowmini 		return (status);
23325903Ssowmini 
23335903Ssowmini 	switch (link_duplex) {
23345903Ssowmini 	case LINK_DUPLEX_FULL:
23355903Ssowmini 		(void) strcpy(*prop_val, "full");
23365903Ssowmini 		break;
23375903Ssowmini 	case LINK_DUPLEX_HALF:
23385903Ssowmini 		(void) strcpy(*prop_val, "half");
23395903Ssowmini 		break;
23405903Ssowmini 	default:
23415903Ssowmini 		(void) strcpy(*prop_val, "unknown");
23425903Ssowmini 		break;
23435903Ssowmini 	}
23445903Ssowmini 	*val_cnt = 1;
23455903Ssowmini 	return (DLADM_STATUS_OK);
23465903Ssowmini }
23475903Ssowmini 
23485903Ssowmini /* ARGSUSED */
23495903Ssowmini static dladm_status_t
2350*8453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
23518275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
23525903Ssowmini {
23535903Ssowmini 	uint64_t	ifspeed = 0;
23545903Ssowmini 	dladm_status_t status;
23555903Ssowmini 
2356*8453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
23575903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
23585903Ssowmini 		return (status);
23596512Ssowmini 
23605960Ssowmini 	if ((ifspeed % 1000000) != 0) {
23615960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
23625960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
23635960Ssowmini 	} else {
23645960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
23655960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
23665960Ssowmini 	}
23675903Ssowmini 	*val_cnt = 1;
23688275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
23695903Ssowmini 	return (DLADM_STATUS_OK);
23705903Ssowmini }
23715903Ssowmini 
23725903Ssowmini /* ARGSUSED */
23735903Ssowmini static dladm_status_t
2374*8453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
2375*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2376*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23775903Ssowmini {
23788275SEric Cheng 	link_state_t		link_state;
23798275SEric Cheng 	dladm_status_t		status;
23808306SSowmini.Varadhan@Sun.COM 
2381*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
23826512Ssowmini 	if (status != DLADM_STATUS_OK)
23835903Ssowmini 		return (status);
23848275SEric Cheng 
23855903Ssowmini 	switch (link_state) {
23865903Ssowmini 	case LINK_STATE_UP:
23875903Ssowmini 		(void) strcpy(*prop_val, "up");
23885903Ssowmini 		break;
23895903Ssowmini 	case LINK_STATE_DOWN:
23905903Ssowmini 		(void) strcpy(*prop_val, "down");
23915903Ssowmini 		break;
23925903Ssowmini 	default:
23935903Ssowmini 		(void) strcpy(*prop_val, "unknown");
23945903Ssowmini 		break;
23955903Ssowmini 	}
23965903Ssowmini 	*val_cnt = 1;
23978306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
23985903Ssowmini 	return (DLADM_STATUS_OK);
23995903Ssowmini }
24005903Ssowmini 
24015903Ssowmini /* ARGSUSED */
24025903Ssowmini static dladm_status_t
2403*8453SAnurag.Maskey@Sun.COM i_dladm_binary_get(dladm_handle_t handle, prop_desc_t *pdp,
2404*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2405*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24065903Ssowmini {
24076789Sam223141 	dld_ioc_macprop_t *dip;
24085903Ssowmini 	dladm_status_t status;
24095903Ssowmini 
2410*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
24118275SEric Cheng 	    &status, perm_flags);
24126512Ssowmini 	if (dip == NULL)
24135903Ssowmini 		return (status);
24148275SEric Cheng 
24155903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
24165903Ssowmini 	free(dip);
24175903Ssowmini 	*val_cnt = 1;
24185903Ssowmini 	return (DLADM_STATUS_OK);
24195903Ssowmini }
24205903Ssowmini 
24215960Ssowmini /* ARGSUSED */
24225903Ssowmini static dladm_status_t
2423*8453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
2424*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2425*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24265903Ssowmini {
24276789Sam223141 	dld_ioc_macprop_t *dip;
24288275SEric Cheng 	uint32_t v = 0;
24295903Ssowmini 	uchar_t *cp;
24305903Ssowmini 	dladm_status_t status;
24315903Ssowmini 
2432*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
24338275SEric Cheng 	    &status, perm_flags);
24346512Ssowmini 	if (dip == NULL)
24355903Ssowmini 		return (status);
24368275SEric Cheng 
24375903Ssowmini 	cp = (uchar_t *)dip->pr_val;
24385903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
24396512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
24405903Ssowmini 	free(dip);
24415903Ssowmini 	*val_cnt = 1;
24425903Ssowmini 	return (DLADM_STATUS_OK);
24435903Ssowmini }
24445903Ssowmini 
24455960Ssowmini /* ARGSUSED */
24465903Ssowmini static dladm_status_t
2447*8453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
2448*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2449*8453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
24505903Ssowmini {
24516789Sam223141 	dld_ioc_macprop_t *dip;
24525903Ssowmini 	link_flowctrl_t v;
24535903Ssowmini 	dladm_status_t status;
24545903Ssowmini 	uchar_t *cp;
24555903Ssowmini 
2456*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
24578275SEric Cheng 	    &status, perm_flags);
24586512Ssowmini 	if (dip == NULL)
24595903Ssowmini 		return (status);
24608275SEric Cheng 
24615903Ssowmini 	cp = (uchar_t *)dip->pr_val;
24625903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
24635903Ssowmini 	switch (v) {
24645903Ssowmini 	case LINK_FLOWCTRL_NONE:
24655903Ssowmini 		(void) sprintf(*prop_val, "no");
24665903Ssowmini 		break;
24675903Ssowmini 	case LINK_FLOWCTRL_RX:
24685903Ssowmini 		(void) sprintf(*prop_val, "rx");
24695903Ssowmini 		break;
24705903Ssowmini 	case LINK_FLOWCTRL_TX:
24715903Ssowmini 		(void) sprintf(*prop_val, "tx");
24725903Ssowmini 		break;
24735903Ssowmini 	case LINK_FLOWCTRL_BI:
24745903Ssowmini 		(void) sprintf(*prop_val, "bi");
24755903Ssowmini 		break;
24765903Ssowmini 	}
24775903Ssowmini 	free(dip);
24785903Ssowmini 	*val_cnt = 1;
24795903Ssowmini 	return (DLADM_STATUS_OK);
24805903Ssowmini }
24815903Ssowmini 
24825903Ssowmini 
24835903Ssowmini /* ARGSUSED */
24845903Ssowmini static dladm_status_t
2485*8453SAnurag.Maskey@Sun.COM i_dladm_set_prop(dladm_handle_t handle, datalink_id_t linkid,
2486*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
2487*8453SAnurag.Maskey@Sun.COM 
24885903Ssowmini {
24897663SSowmini.Varadhan@Sun.COM 	int		i, slen;
24907408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
24916789Sam223141 	dld_ioc_macprop_t *dip = NULL;
24925903Ssowmini 	uchar_t 	*dp;
24937663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
24946512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
24955903Ssowmini 
24965903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
24975903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
24985903Ssowmini 		return (DLADM_STATUS_BADARG);
24995903Ssowmini 	p = dladm_name2prop(prop_name);
25006789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
25015903Ssowmini 		return (DLADM_STATUS_BADARG);
25025903Ssowmini 
25035903Ssowmini 	/*
25045903Ssowmini 	 * private properties: all parsing is done in the kernel.
25055903Ssowmini 	 * allocate a enough space for each property + its separator (',').
25065903Ssowmini 	 */
25075903Ssowmini 	for (i = 0; i < val_cnt; i++) {
25085903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
25095903Ssowmini 	}
25106512Ssowmini 
25116512Ssowmini 	if (prop_val == NULL) {
25126512Ssowmini 		/*
25136512Ssowmini 		 * getting default value. so use more buffer space.
25146512Ssowmini 		 */
25157663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
25166512Ssowmini 	}
25176512Ssowmini 
25187663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
25196789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
25205903Ssowmini 	if (dip == NULL)
25215903Ssowmini 		return (status);
25225903Ssowmini 
25235903Ssowmini 	dp = (uchar_t *)dip->pr_val;
25245903Ssowmini 	slen = 0;
25257663SSowmini.Varadhan@Sun.COM 
25266512Ssowmini 	if (prop_val == NULL) {
2527*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
25286512Ssowmini 	} else {
25296512Ssowmini 		for (i = 0; i < val_cnt; i++) {
25306512Ssowmini 			int plen = 0;
25315903Ssowmini 
25326512Ssowmini 			plen = strlen(prop_val[i]);
25336512Ssowmini 			bcopy(prop_val[i], dp, plen);
25346512Ssowmini 			slen += plen;
25356512Ssowmini 			/*
25366512Ssowmini 			 * add a "," separator and update dp.
25376512Ssowmini 			 */
25386512Ssowmini 			if (i != (val_cnt -1))
25396512Ssowmini 				dp[slen++] = ',';
25406512Ssowmini 			dp += (plen + 1);
25416512Ssowmini 		}
2542*8453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
25435903Ssowmini 	}
25446512Ssowmini 
25455903Ssowmini 	free(dip);
25466512Ssowmini 	return (status);
25475903Ssowmini }
25485903Ssowmini 
25495903Ssowmini static dladm_status_t
2550*8453SAnurag.Maskey@Sun.COM i_dladm_get_prop(dladm_handle_t handle, datalink_id_t linkid,
2551*8453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
2552*8453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
25535903Ssowmini {
25547663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
25556789Sam223141 	dld_ioc_macprop_t *dip = NULL;
25567663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
25575903Ssowmini 	char tmp = '\0';
25585903Ssowmini 
25595903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
25605903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
25615903Ssowmini 		return (DLADM_STATUS_BADARG);
25625903Ssowmini 
25635903Ssowmini 	p = dladm_name2prop(prop_name);
25646789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
25655903Ssowmini 		return (DLADM_STATUS_BADARG);
25665903Ssowmini 
25676512Ssowmini 	if (type == DLADM_PROP_VAL_MODIFIABLE) {
25685903Ssowmini 		*prop_val = &tmp;
25695903Ssowmini 		*val_cnt = 1;
25705903Ssowmini 		return (DLADM_STATUS_OK);
25715903Ssowmini 	}
25725903Ssowmini 
25735903Ssowmini 	/*
25745903Ssowmini 	 * private properties: all parsing is done in the kernel.
25755903Ssowmini 	 */
25767663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
25777663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
25785903Ssowmini 	if (dip == NULL)
25795903Ssowmini 		return (status);
25805903Ssowmini 
2581*8453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
2582*8453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
25838118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
25848275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
25858118SVasumathi.Sundaram@Sun.COM 		} else {
25868118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
25878118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
25888118SVasumathi.Sundaram@Sun.COM 		}
25895903Ssowmini 		*val_cnt = 1;
25905903Ssowmini 	}
25916512Ssowmini 	free(dip);
25925903Ssowmini 	return (status);
25935903Ssowmini }
25946512Ssowmini 
25956512Ssowmini 
25966512Ssowmini static dladm_status_t
2597*8453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
2598*8453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
25996512Ssowmini {
26006512Ssowmini 	dladm_status_t status;
26016512Ssowmini 	char **prop_vals = NULL, *buf;
26026512Ssowmini 	size_t bufsize;
26036512Ssowmini 	uint_t cnt;
26046512Ssowmini 	int i;
26058118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
26066512Ssowmini 
26076512Ssowmini 	/*
26086512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
26096512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
26106512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
26116512Ssowmini 	 */
26126512Ssowmini 	bufsize =
26136512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
26146512Ssowmini 	buf = malloc(bufsize);
26156512Ssowmini 	prop_vals = (char **)(void *)buf;
26166512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
26176512Ssowmini 		prop_vals[i] = buf +
26186512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
26196512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
26206512Ssowmini 	}
26216768Sar224390 
26226768Sar224390 	/*
26237342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
26247342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
26257342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
26267342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
26277342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
26287342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
26297342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
26307342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
26316768Sar224390 	 */
2632*8453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
26338118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
26346512Ssowmini 	if (status == DLADM_STATUS_OK) {
26358118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
2636*8453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
2637*8453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
26388118SVasumathi.Sundaram@Sun.COM 		}
26398118SVasumathi.Sundaram@Sun.COM 		else
26408118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
26416512Ssowmini 	}
26426512Ssowmini 	free(buf);
26436512Ssowmini 	return (status);
26446512Ssowmini }
26457663SSowmini.Varadhan@Sun.COM 
26467663SSowmini.Varadhan@Sun.COM int
26477663SSowmini.Varadhan@Sun.COM macprop_to_wifi(mac_prop_id_t wl_prop)
26487663SSowmini.Varadhan@Sun.COM {
26497663SSowmini.Varadhan@Sun.COM 	switch (wl_prop) {
26507663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ESSID:
26517663SSowmini.Varadhan@Sun.COM 		return (WL_ESSID);
26527663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_BSSID:
26537663SSowmini.Varadhan@Sun.COM 		return (WL_BSSID);
26547663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_BSSTYPE:
26557663SSowmini.Varadhan@Sun.COM 		return (WL_BSS_TYPE);
26567663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_LINKSTATUS:
26577663SSowmini.Varadhan@Sun.COM 		return (WL_LINKSTATUS);
26587663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_DESIRED_RATES:
26597663SSowmini.Varadhan@Sun.COM 		return (WL_DESIRED_RATES);
26607663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SUPPORTED_RATES:
26617663SSowmini.Varadhan@Sun.COM 		return (WL_SUPPORTED_RATES);
26627663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_AUTH_MODE:
26637663SSowmini.Varadhan@Sun.COM 		return (WL_AUTH_MODE);
26647663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ENCRYPTION:
26657663SSowmini.Varadhan@Sun.COM 		return (WL_ENCRYPTION);
26667663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_RSSI:
26677663SSowmini.Varadhan@Sun.COM 		return (WL_RSSI);
26687663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_PHY_CONFIG:
26697663SSowmini.Varadhan@Sun.COM 		return (WL_PHY_CONFIG);
26707663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_CAPABILITY:
26717663SSowmini.Varadhan@Sun.COM 		return (WL_CAPABILITY);
26727663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_WPA:
26737663SSowmini.Varadhan@Sun.COM 		return (WL_WPA);
26747663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SCANRESULTS:
26757663SSowmini.Varadhan@Sun.COM 		return (WL_SCANRESULTS);
26767663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_POWER_MODE:
26777663SSowmini.Varadhan@Sun.COM 		return (WL_POWER_MODE);
26787663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_RADIO:
26797663SSowmini.Varadhan@Sun.COM 		return (WL_RADIO);
26807663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_ESS_LIST:
26817663SSowmini.Varadhan@Sun.COM 		return (WL_ESS_LIST);
26827663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_KEY_TAB:
26837663SSowmini.Varadhan@Sun.COM 		return (WL_WEP_KEY_TAB);
26847663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_CREATE_IBSS:
26857663SSowmini.Varadhan@Sun.COM 		return (WL_CREATE_IBSS);
26867663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_SETOPTIE:
26877663SSowmini.Varadhan@Sun.COM 		return (WL_SETOPTIE);
26887663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_DELKEY:
26897663SSowmini.Varadhan@Sun.COM 		return (WL_DELKEY);
26907663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_KEY:
26917663SSowmini.Varadhan@Sun.COM 		return (WL_KEY);
26927663SSowmini.Varadhan@Sun.COM 	case MAC_PROP_WL_MLME:
26937663SSowmini.Varadhan@Sun.COM 		return (WL_MLME);
26947663SSowmini.Varadhan@Sun.COM 	default:
26957663SSowmini.Varadhan@Sun.COM 		return (-1);
26967663SSowmini.Varadhan@Sun.COM 	}
26977663SSowmini.Varadhan@Sun.COM }
26987663SSowmini.Varadhan@Sun.COM 
26997663SSowmini.Varadhan@Sun.COM dladm_status_t
2700*8453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
2701*8453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
27027663SSowmini.Varadhan@Sun.COM {
27037663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
27047663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
27057663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
27067663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
27077663SSowmini.Varadhan@Sun.COM 	void			*dp;
27087663SSowmini.Varadhan@Sun.COM 
2709*8453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
2710*8453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
27117663SSowmini.Varadhan@Sun.COM 		return (status);
27127663SSowmini.Varadhan@Sun.COM 	}
27137663SSowmini.Varadhan@Sun.COM 
27147663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
27157663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
27167663SSowmini.Varadhan@Sun.COM 
27177663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
27187663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
27197663SSowmini.Varadhan@Sun.COM 
27207663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
27217663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
27227663SSowmini.Varadhan@Sun.COM 
27237663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
27247663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
27257663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
27267663SSowmini.Varadhan@Sun.COM 
27277663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
27287663SSowmini.Varadhan@Sun.COM 	if (set)
27297663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
27307663SSowmini.Varadhan@Sun.COM 
2731*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
27327663SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_NOTSUP) {
27337663SSowmini.Varadhan@Sun.COM 		if (set) {
2734*8453SAnurag.Maskey@Sun.COM 			status = i_dladm_wlan_set_legacy_ioctl(handle, linkid,
27357663SSowmini.Varadhan@Sun.COM 			    buf, len, macprop_to_wifi(cmd));
27367663SSowmini.Varadhan@Sun.COM 		} else {
2737*8453SAnurag.Maskey@Sun.COM 			status = i_dladm_wlan_get_legacy_ioctl(handle, linkid,
27387663SSowmini.Varadhan@Sun.COM 			    buf, len, macprop_to_wifi(cmd));
27397663SSowmini.Varadhan@Sun.COM 		}
27407663SSowmini.Varadhan@Sun.COM 	} else if (status == DLADM_STATUS_OK) {
27417663SSowmini.Varadhan@Sun.COM 		if (!set)
27427663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
27437663SSowmini.Varadhan@Sun.COM 	}
27447663SSowmini.Varadhan@Sun.COM 
27457663SSowmini.Varadhan@Sun.COM 	free(dip);
27467663SSowmini.Varadhan@Sun.COM 	return (status);
27477663SSowmini.Varadhan@Sun.COM }
27487663SSowmini.Varadhan@Sun.COM 
27497663SSowmini.Varadhan@Sun.COM static dladm_status_t
2750*8453SAnurag.Maskey@Sun.COM i_dladm_wlan_get_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid,
2751*8453SAnurag.Maskey@Sun.COM     void *buf, uint_t buflen, uint_t id)
27527663SSowmini.Varadhan@Sun.COM {
27537663SSowmini.Varadhan@Sun.COM 	wldp_t *gbuf;
27547663SSowmini.Varadhan@Sun.COM 	dladm_status_t status;
27557663SSowmini.Varadhan@Sun.COM 
27567663SSowmini.Varadhan@Sun.COM 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
27577663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
27587663SSowmini.Varadhan@Sun.COM 
27597663SSowmini.Varadhan@Sun.COM 	(void) memset(gbuf, 0, MAX_BUF_LEN);
2760*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, id,
2761*8453SAnurag.Maskey@Sun.COM 	    MAX_BUF_LEN, WLAN_GET_PARAM, sizeof (wldp_t));
27627663SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK)
27637663SSowmini.Varadhan@Sun.COM 		(void) memcpy(buf, gbuf->wldp_buf, buflen);
27647663SSowmini.Varadhan@Sun.COM 
27657663SSowmini.Varadhan@Sun.COM 	free(gbuf);
27667663SSowmini.Varadhan@Sun.COM 	return (status);
27677663SSowmini.Varadhan@Sun.COM }
27687663SSowmini.Varadhan@Sun.COM 
27697663SSowmini.Varadhan@Sun.COM static dladm_status_t
2770*8453SAnurag.Maskey@Sun.COM i_dladm_wlan_set_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid,
2771*8453SAnurag.Maskey@Sun.COM     void *buf, uint_t buflen, uint_t id)
27727663SSowmini.Varadhan@Sun.COM {
27737663SSowmini.Varadhan@Sun.COM 	wldp_t *gbuf;
27747663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
27757663SSowmini.Varadhan@Sun.COM 
27767663SSowmini.Varadhan@Sun.COM 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
27777663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
27787663SSowmini.Varadhan@Sun.COM 
27797663SSowmini.Varadhan@Sun.COM 	(void) memset(gbuf, 0, MAX_BUF_LEN);
27807663SSowmini.Varadhan@Sun.COM 	(void) memcpy(gbuf->wldp_buf, buf, buflen);
27817663SSowmini.Varadhan@Sun.COM 	buflen += WIFI_BUF_OFFSET;
2782*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, id, buflen,
27837663SSowmini.Varadhan@Sun.COM 	    WLAN_SET_PARAM, buflen);
27847663SSowmini.Varadhan@Sun.COM 
27857663SSowmini.Varadhan@Sun.COM 	free(gbuf);
27867663SSowmini.Varadhan@Sun.COM 	return (status);
27877663SSowmini.Varadhan@Sun.COM }
27888275SEric Cheng 
27898275SEric Cheng static dladm_status_t
27908275SEric Cheng link_proplist_check(dladm_arg_list_t *proplist)
27918275SEric Cheng {
27928275SEric Cheng 	int		i, j;
27938275SEric Cheng 	boolean_t	matched;
27948275SEric Cheng 
27958275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
27968275SEric Cheng 		matched = B_FALSE;
27978275SEric Cheng 		for (j = 0; j < DLADM_MAX_PROPS; j++) {
27988275SEric Cheng 			if (strcmp(proplist->al_info[i].ai_name,
27998275SEric Cheng 			    prop_table[j].pd_name) == 0)
28008275SEric Cheng 				matched = B_TRUE;
28018275SEric Cheng 		}
28028275SEric Cheng 		if (!matched)
28038275SEric Cheng 			return (DLADM_STATUS_BADPROP);
28048275SEric Cheng 	}
28058275SEric Cheng 	return (DLADM_STATUS_OK);
28068275SEric Cheng }
28078275SEric Cheng 
28088275SEric Cheng dladm_status_t
28098275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
28108275SEric Cheng {
28118275SEric Cheng 	dladm_status_t	status;
28128275SEric Cheng 
28138275SEric Cheng 	status = dladm_parse_args(str, listp, novalues);
28148275SEric Cheng 	if (status != DLADM_STATUS_OK)
28158275SEric Cheng 		return (status);
28168275SEric Cheng 
28178275SEric Cheng 	status = link_proplist_check(*listp);
28188275SEric Cheng 	if (status != DLADM_STATUS_OK) {
28198275SEric Cheng 		dladm_free_props(*listp);
28208275SEric Cheng 		return (status);
28218275SEric Cheng 	}
28228275SEric Cheng 
28238275SEric Cheng 	return (DLADM_STATUS_OK);
28248275SEric Cheng }
28258275SEric Cheng 
28268275SEric Cheng /*
28278275SEric Cheng  * Retrieve the one link property from the database
28288275SEric Cheng  */
28298275SEric Cheng /*ARGSUSED*/
28308275SEric Cheng static int
2831*8453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
2832*8453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
28338275SEric Cheng {
28348275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
28358275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
28368275SEric Cheng 
28378275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
28388275SEric Cheng 	/*
28398275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
28408275SEric Cheng 	 * prop_table[n].pd_name.
28418275SEric Cheng 	 */
28428275SEric Cheng 	aip->ai_name = prop_name;
28438275SEric Cheng 
2844*8453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
2845*8453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
28468275SEric Cheng 
28478275SEric Cheng 	if (aip->ai_count != 0)
28488275SEric Cheng 		proplist->al_count++;
28498275SEric Cheng 
28508275SEric Cheng 	return (DLADM_WALK_CONTINUE);
28518275SEric Cheng }
28528275SEric Cheng 
28538275SEric Cheng 
28548275SEric Cheng /*
28558275SEric Cheng  * Retrieve all link properties for a link from the database and
28568275SEric Cheng  * return a property list.
28578275SEric Cheng  */
28588275SEric Cheng dladm_status_t
2859*8453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
2860*8453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
28618275SEric Cheng {
28628275SEric Cheng 	dladm_arg_list_t	*list;
28638275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
28648275SEric Cheng 
28658275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
28668275SEric Cheng 	if (list == NULL)
28678275SEric Cheng 		return (dladm_errno2status(errno));
28688275SEric Cheng 
2869*8453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
2870*8453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
28718275SEric Cheng 
28728275SEric Cheng 	*listp = list;
28738275SEric Cheng 	return (status);
28748275SEric Cheng }
28758275SEric Cheng 
28768275SEric Cheng /*
28778275SEric Cheng  * Retrieve the named property from a proplist, check the value and
28788275SEric Cheng  * convert to a kernel structure.
28798275SEric Cheng  */
28808275SEric Cheng static dladm_status_t
2881*8453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
2882*8453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist, const char *name, void *val)
28838275SEric Cheng {
28848275SEric Cheng 	dladm_status_t		status;
28858275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
28868275SEric Cheng 	int			i, j;
28878275SEric Cheng 
28888275SEric Cheng 	/* Find named property in proplist */
28898275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
28908275SEric Cheng 		aip = &proplist->al_info[i];
28918275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
28928275SEric Cheng 			break;
28938275SEric Cheng 	}
28948275SEric Cheng 
28958275SEric Cheng 	/* Property not in list */
28968275SEric Cheng 	if (i == proplist->al_count)
28978275SEric Cheng 		return (DLADM_STATUS_OK);
28988275SEric Cheng 
28998275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
29008275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
29018275SEric Cheng 		val_desc_t	*vdp;
29028275SEric Cheng 
29038275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
29048275SEric Cheng 		if (vdp == NULL)
29058275SEric Cheng 			return (DLADM_STATUS_NOMEM);
29068275SEric Cheng 
29078275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
29088275SEric Cheng 			continue;
29098275SEric Cheng 
29108275SEric Cheng 		if (aip->ai_val == NULL)
29118275SEric Cheng 			return (DLADM_STATUS_BADARG);
29128275SEric Cheng 
29138275SEric Cheng 		/* Check property value */
29148275SEric Cheng 		if (pdp->pd_check != NULL) {
2915*8453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
29168275SEric Cheng 			    aip->ai_count, vdp, 0);
29178275SEric Cheng 		} else {
29188275SEric Cheng 			status = DLADM_STATUS_BADARG;
29198275SEric Cheng 		}
29208275SEric Cheng 
29218275SEric Cheng 		if (status != DLADM_STATUS_OK)
29228275SEric Cheng 			return (status);
29238275SEric Cheng 
29248275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
29258275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
29268275SEric Cheng 
29278275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
29288275SEric Cheng 				continue;
29298275SEric Cheng 
29308275SEric Cheng 			/* Extract kernel structure */
29318275SEric Cheng 			if (rpp->rp_extract != NULL) {
29328275SEric Cheng 				status = rpp->rp_extract(vdp, val,
29338275SEric Cheng 				    aip->ai_count);
29348275SEric Cheng 			} else {
29358275SEric Cheng 				status = DLADM_STATUS_BADARG;
29368275SEric Cheng 			}
29378275SEric Cheng 			break;
29388275SEric Cheng 		}
29398275SEric Cheng 
29408275SEric Cheng 		if (status != DLADM_STATUS_OK)
29418275SEric Cheng 			return (status);
29428275SEric Cheng 
29438275SEric Cheng 		break;
29448275SEric Cheng 	}
29458275SEric Cheng 	return (status);
29468275SEric Cheng }
29478275SEric Cheng 
29488275SEric Cheng /*
29498275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
29508275SEric Cheng  */
29518275SEric Cheng dladm_status_t
2952*8453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
29538275SEric Cheng     mac_resource_props_t *mrp)
29548275SEric Cheng {
29558275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
29568275SEric Cheng 
2957*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "maxbw",
2958*8453SAnurag.Maskey@Sun.COM 	    mrp);
29598275SEric Cheng 	if (status != DLADM_STATUS_OK)
29608275SEric Cheng 		return (status);
2961*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "priority",
2962*8453SAnurag.Maskey@Sun.COM 	    mrp);
29638275SEric Cheng 	if (status != DLADM_STATUS_OK)
29648275SEric Cheng 		return (status);
2965*8453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "cpus",
2966*8453SAnurag.Maskey@Sun.COM 	    mrp);
29678275SEric Cheng 	if (status != DLADM_STATUS_OK)
29688275SEric Cheng 		return (status);
29698275SEric Cheng 	return (status);
29708275SEric Cheng }
29718275SEric Cheng 
29728275SEric Cheng static const char *
29738275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
29748275SEric Cheng {
29758275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
29768275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
29778275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
29788275SEric Cheng 	return (buf);
29798275SEric Cheng }
29808306SSowmini.Varadhan@Sun.COM 
29818306SSowmini.Varadhan@Sun.COM dladm_status_t
2982*8453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
2983*8453SAnurag.Maskey@Sun.COM     link_state_t *state)
29848306SSowmini.Varadhan@Sun.COM {
29858306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
29868306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
29878306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
29888306SSowmini.Varadhan@Sun.COM 
2989*8453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
2990*8453SAnurag.Maskey@Sun.COM 	    &perms);
29918306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
29928306SSowmini.Varadhan@Sun.COM 		return (status);
29938306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
29948306SSowmini.Varadhan@Sun.COM 	free(dip);
29958306SSowmini.Varadhan@Sun.COM 	return (status);
29968306SSowmini.Varadhan@Sun.COM }
2997