13147Sxc151355 /*
23147Sxc151355  * CDDL HEADER START
33147Sxc151355  *
43147Sxc151355  * The contents of this file are subject to the terms of the
53147Sxc151355  * Common Development and Distribution License (the "License").
63147Sxc151355  * You may not use this file except in compliance with the License.
73147Sxc151355  *
83147Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93147Sxc151355  * or http://www.opensolaris.org/os/licensing.
103147Sxc151355  * See the License for the specific language governing permissions
113147Sxc151355  * and limitations under the License.
123147Sxc151355  *
133147Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
143147Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153147Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
163147Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
173147Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
183147Sxc151355  *
193147Sxc151355  * CDDL HEADER END
203147Sxc151355  */
213147Sxc151355 /*
228874SSebastien.Roy@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233147Sxc151355  * Use is subject to license terms.
243147Sxc151355  */
253147Sxc151355 
263147Sxc151355 #include <stdlib.h>
273147Sxc151355 #include <strings.h>
283147Sxc151355 #include <errno.h>
293147Sxc151355 #include <ctype.h>
305895Syz147064 #include <stddef.h>
313448Sdh155122 #include <sys/types.h>
323147Sxc151355 #include <sys/stat.h>
333448Sdh155122 #include <sys/dld.h>
343448Sdh155122 #include <sys/zone.h>
353448Sdh155122 #include <fcntl.h>
363448Sdh155122 #include <unistd.h>
373448Sdh155122 #include <libdevinfo.h>
383448Sdh155122 #include <zone.h>
393871Syz147064 #include <libdllink.h>
403147Sxc151355 #include <libdladm_impl.h>
415895Syz147064 #include <libdlwlan_impl.h>
423871Syz147064 #include <libdlwlan.h>
435895Syz147064 #include <libdlvlan.h>
448275SEric Cheng #include <libdlvnic.h>
458275SEric Cheng #include <libintl.h>
463448Sdh155122 #include <dlfcn.h>
473448Sdh155122 #include <link.h>
485895Syz147064 #include <inet/wifi_ioctl.h>
495903Ssowmini #include <libdladm.h>
508275SEric Cheng #include <libdlstat.h>
515903Ssowmini #include <sys/param.h>
528275SEric Cheng #include <sys/debug.h>
538275SEric Cheng #include <sys/dld.h>
548275SEric Cheng #include <sys/mac_flow.h>
555903Ssowmini #include <inttypes.h>
565903Ssowmini #include <sys/ethernet.h>
577663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
587663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
59*10491SRishi.Srivatsavai@Sun.COM #include <sys/vlan.h>
60*10491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
61*10491SRishi.Srivatsavai@Sun.COM #include <stp_in.h>
623448Sdh155122 
635895Syz147064 /*
645895Syz147064  * The linkprop get() callback.
658275SEric Cheng  * - pd: 	pointer to the prop_desc_t
665895Syz147064  * - propstrp:	a property string array to keep the returned property.
675895Syz147064  *		Caller allocated.
685895Syz147064  * - cntp:	number of returned properties.
695895Syz147064  *		Caller also uses it to indicate how many it expects.
705895Syz147064  */
715903Ssowmini struct prop_desc;
728275SEric Cheng typedef struct prop_desc prop_desc_t;
738275SEric Cheng 
748453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
755960Ssowmini 			datalink_id_t, char **propstp, uint_t *cntp,
768118SVasumathi.Sundaram@Sun.COM 			datalink_media_t, uint_t, uint_t *);
775895Syz147064 
785895Syz147064 /*
795895Syz147064  * The linkprop set() callback.
805895Syz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
815895Syz147064  * - cnt:	number of properties to be set.
825903Ssowmini  * - flags: 	additional flags passed down the system call.
835903Ssowmini  *
845903Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
855903Ssowmini  * a format suitable for kernel consumption. This may require allocation
865903Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
875903Ssowmini  * by all other pd_sets) which invokes the ioctl.
885895Syz147064  */
898453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
908275SEric Cheng 			    val_desc_t *propval, uint_t cnt, uint_t flags,
918275SEric Cheng 			    datalink_media_t);
923448Sdh155122 
935895Syz147064 /*
945895Syz147064  * The linkprop check() callback.
955895Syz147064  * - propstrp:	property string array which keeps the property to be checked.
965895Syz147064  * - cnt:	number of properties.
975895Syz147064  * - propval:	return value; the property values of the given property strings.
985903Ssowmini  *
995903Ssowmini  * pd_check checks that the input values are valid. It does so by
1005903Ssowmini  * iteraring through the pd_modval list for the property. If
1015903Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
1025903Ssowmini  * specific to this property can be used. If the input values are
1035903Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
1045903Ssowmini  * with either a val_desc_t found on the pd_modval list or something
1055903Ssowmini  * generated on the fly.
1065895Syz147064  */
1078453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
1088453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **propstrp, uint_t cnt,
1098453SAnurag.Maskey@Sun.COM 			    val_desc_t *propval, datalink_media_t);
1103448Sdh155122 
1117663SSowmini.Varadhan@Sun.COM typedef struct link_attr_s {
1126789Sam223141 	mac_prop_id_t	pp_id;
1135903Ssowmini 	size_t		pp_valsize;
1145903Ssowmini 	char		*pp_name;
1157663SSowmini.Varadhan@Sun.COM } link_attr_t;
1165903Ssowmini 
1177663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
1188275SEric Cheng 			    const char *, uint_t, dladm_status_t *);
1197663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
1208275SEric Cheng 			    mac_prop_id_t, uint_t, dladm_status_t *);
1218453SAnurag.Maskey@Sun.COM static dld_ioc_macprop_t *i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
1228453SAnurag.Maskey@Sun.COM 			    char *, uint_t, dladm_status_t *, uint_t *);
1238453SAnurag.Maskey@Sun.COM 
1249692SRishi.Srivatsavai@Sun.COM static dladm_status_t i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
1258453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
1268460SArtem.Kachitchkin@Sun.COM static dladm_status_t i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
1278453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *, dladm_prop_type_t,
1288453SAnurag.Maskey@Sun.COM 			    uint_t);
1297663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_name2prop(const char *);
1307663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_id2prop(mac_prop_id_t);
1318275SEric Cheng 
1325895Syz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
1335895Syz147064 			do_get_rate_prop, do_get_channel_prop,
1345903Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
1357342SAruna.Ramakrishna@Sun.COM 			i_dladm_duplex_get, i_dladm_status_get,
1367342SAruna.Ramakrishna@Sun.COM 			i_dladm_binary_get, i_dladm_uint32_get,
1378460SArtem.Kachitchkin@Sun.COM 			i_dladm_flowctl_get, i_dladm_maxbw_get,
1388874SSebastien.Roy@Sun.COM 			i_dladm_cpus_get, i_dladm_priority_get,
139*10491SRishi.Srivatsavai@Sun.COM 			i_dladm_tagmode_get, i_dladm_range_get,
140*10491SRishi.Srivatsavai@Sun.COM 			get_stp_prop, get_bridge_forward,
141*10491SRishi.Srivatsavai@Sun.COM 			get_bridge_pvid;
1428275SEric Cheng 
1437342SAruna.Ramakrishna@Sun.COM static pd_setf_t	do_set_zone, do_set_rate_prop,
1445903Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
145*10491SRishi.Srivatsavai@Sun.COM 			i_dladm_set_public_prop, do_set_res, do_set_cpus,
146*10491SRishi.Srivatsavai@Sun.COM 			set_stp_prop, set_bridge_forward, set_bridge_pvid;
1478275SEric Cheng 
1485903Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
149*10491SRishi.Srivatsavai@Sun.COM 			i_dladm_uint32_check, do_check_maxbw, do_check_cpus,
150*10491SRishi.Srivatsavai@Sun.COM 			do_check_priority, check_stp_prop, check_bridge_pvid;
1518275SEric Cheng 
1528453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_speed_get(dladm_handle_t, prop_desc_t *,
1538453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **, uint_t *, uint_t, uint_t *);
1548453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1558275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1568275SEric Cheng 
1578275SEric Cheng struct prop_desc {
1585895Syz147064 	/*
1595895Syz147064 	 * link property name
1605895Syz147064 	 */
1615895Syz147064 	char			*pd_name;
1625895Syz147064 
1635895Syz147064 	/*
1645895Syz147064 	 * default property value, can be set to { "", NULL }
1655895Syz147064 	 */
1665895Syz147064 	val_desc_t		pd_defval;
1675895Syz147064 
1685895Syz147064 	/*
1695895Syz147064 	 * list of optional property values, can be NULL.
1705895Syz147064 	 *
1715895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1725895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1735895Syz147064 	 */
1745895Syz147064 	val_desc_t		*pd_optval;
1755895Syz147064 
1765895Syz147064 	/*
1775895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1785895Syz147064 	 */
1795895Syz147064 	uint_t			pd_noptval;
1805895Syz147064 
1815895Syz147064 	/*
182*10491SRishi.Srivatsavai@Sun.COM 	 * callback to set link property; set to NULL if this property is
183*10491SRishi.Srivatsavai@Sun.COM 	 * read-only and may be called before or after permanent update; see
184*10491SRishi.Srivatsavai@Sun.COM 	 * flags.
1855895Syz147064 	 */
1865895Syz147064 	pd_setf_t		*pd_set;
1875895Syz147064 
1885895Syz147064 	/*
1895895Syz147064 	 * callback to get modifiable link property
1905895Syz147064 	 */
1915895Syz147064 	pd_getf_t		*pd_getmod;
1925895Syz147064 
1935895Syz147064 	/*
1945895Syz147064 	 * callback to get current link property
1955895Syz147064 	 */
1965895Syz147064 	pd_getf_t		*pd_get;
1975895Syz147064 
1985895Syz147064 	/*
1995895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
2005895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
2015895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
2025895Syz147064 	 * valid.
2035895Syz147064 	 */
2045895Syz147064 	pd_checkf_t		*pd_check;
2055895Syz147064 
2065895Syz147064 	uint_t			pd_flags;
2075903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2085903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
209*10491SRishi.Srivatsavai@Sun.COM #define	PD_AFTER_PERM	0x4	/* pd_set after db update; no temporary */
2105895Syz147064 	/*
2115895Syz147064 	 * indicate link classes this property applies to.
2125895Syz147064 	 */
2135895Syz147064 	datalink_class_t	pd_class;
2145895Syz147064 
2155895Syz147064 	/*
2165895Syz147064 	 * indicate link media type this property applies to.
2175895Syz147064 	 */
2185895Syz147064 	datalink_media_t	pd_dmedia;
2198275SEric Cheng };
2203448Sdh155122 
2216789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2225903Ssowmini 
2237663SSowmini.Varadhan@Sun.COM /*
2247663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2257663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2267663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2277663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2287663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2297663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2307663SSowmini.Varadhan@Sun.COM  */
2317663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2327663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2335903Ssowmini 
2347663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2357663SSowmini.Varadhan@Sun.COM 
2367663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2377663SSowmini.Varadhan@Sun.COM 
2387663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2395903Ssowmini 
2407663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2415903Ssowmini 
2427663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2437663SSowmini.Varadhan@Sun.COM 
2447663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2455903Ssowmini 
2467663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2477663SSowmini.Varadhan@Sun.COM 
2489449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),	"adv_10gfdx_cap"},
2499449Sxiuyan.wang@Sun.COM 
2509449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),	"en_10gfdx_cap"},
2519449Sxiuyan.wang@Sun.COM 
2527663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2537663SSowmini.Varadhan@Sun.COM 
2547663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2555903Ssowmini 
2567663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2575903Ssowmini 
2587663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2597663SSowmini.Varadhan@Sun.COM 
2607663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2617342SAruna.Ramakrishna@Sun.COM 
2627663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2637663SSowmini.Varadhan@Sun.COM 
2647663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2657663SSowmini.Varadhan@Sun.COM 
2667663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2677342SAruna.Ramakrishna@Sun.COM 
2687663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2697663SSowmini.Varadhan@Sun.COM 
2707663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2715903Ssowmini 
2727663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2737663SSowmini.Varadhan@Sun.COM 
2747663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2755903Ssowmini 
2767663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2777663SSowmini.Varadhan@Sun.COM 
2787663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2795903Ssowmini 
2807663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2817663SSowmini.Varadhan@Sun.COM 
2827663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2837663SSowmini.Varadhan@Sun.COM 
2847663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2857663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2865903Ssowmini 
2877663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2887663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2897663SSowmini.Varadhan@Sun.COM 
2907663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2915903Ssowmini 
2927663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
2937663SSowmini.Varadhan@Sun.COM 
2947663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
2955903Ssowmini 
2967663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
2977663SSowmini.Varadhan@Sun.COM 
2987663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
2995903Ssowmini 
3007663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
3017663SSowmini.Varadhan@Sun.COM 
3027663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
3037663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
3045903Ssowmini 
3057663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
3067663SSowmini.Varadhan@Sun.COM 
3077663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
3085903Ssowmini 
3097663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3107663SSowmini.Varadhan@Sun.COM 
3117663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3125903Ssowmini 
3137663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3147663SSowmini.Varadhan@Sun.COM 
3157663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3167663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3175903Ssowmini 
3187663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3197663SSowmini.Varadhan@Sun.COM 
3207663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3215903Ssowmini 
3227663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3237663SSowmini.Varadhan@Sun.COM 
3248275SEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
3258275SEric Cheng 
3268275SEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
3278275SEric Cheng 
3288275SEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
3298275SEric Cheng 
3308874SSebastien.Roy@Sun.COM 	{ MAC_PROP_TAGMODE,	sizeof (link_tagmode_t),	"tagmode"},
3318874SSebastien.Roy@Sun.COM 
332*10491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_PVID,	sizeof (uint16_t),	"default_tag"},
333*10491SRishi.Srivatsavai@Sun.COM 
334*10491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LLIMIT,	sizeof (uint32_t),	"learn_limit"},
335*10491SRishi.Srivatsavai@Sun.COM 
336*10491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LDECAY,	sizeof (uint32_t),	"learn_decay"},
337*10491SRishi.Srivatsavai@Sun.COM 
3387663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3398275SEric Cheng 
3405903Ssowmini };
3415903Ssowmini 
342*10491SRishi.Srivatsavai@Sun.COM typedef struct bridge_public_prop_s {
343*10491SRishi.Srivatsavai@Sun.COM 	const char	*bpp_name;
344*10491SRishi.Srivatsavai@Sun.COM 	int		bpp_code;
345*10491SRishi.Srivatsavai@Sun.COM } bridge_public_prop_t;
346*10491SRishi.Srivatsavai@Sun.COM 
347*10491SRishi.Srivatsavai@Sun.COM static const bridge_public_prop_t bridge_prop[] = {
348*10491SRishi.Srivatsavai@Sun.COM 	{ "stp", PT_CFG_NON_STP },
349*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", PT_CFG_PRIO },
350*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", PT_CFG_COST },
351*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", PT_CFG_EDGE },
352*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", PT_CFG_P2P },
353*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", PT_CFG_MCHECK },
354*10491SRishi.Srivatsavai@Sun.COM 	{ NULL, 0 }
355*10491SRishi.Srivatsavai@Sun.COM };
356*10491SRishi.Srivatsavai@Sun.COM 
3575903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3585903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3595903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3605903Ssowmini };
3615903Ssowmini static  val_desc_t	link_status_vals[] = {
3625903Ssowmini 	{ "up",		LINK_STATE_UP		},
3635903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3645903Ssowmini };
3655903Ssowmini static  val_desc_t	link_01_vals[] = {
3665903Ssowmini 	{ "1",		1			},
3675903Ssowmini 	{ "0",		0			}
3685903Ssowmini };
3695903Ssowmini static  val_desc_t	link_flow_vals[] = {
3705903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3715903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3725903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3735903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3745903Ssowmini };
3758275SEric Cheng static  val_desc_t	link_priority_vals[] = {
3768275SEric Cheng 	{ "low",	MPL_LOW	},
3778275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
3788275SEric Cheng 	{ "high",	MPL_HIGH	}
3798275SEric Cheng };
3805903Ssowmini 
3818874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
3828874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
3838874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
3848874SSebastien.Roy@Sun.COM };
3858874SSebastien.Roy@Sun.COM 
3865895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
3875895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
3885895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
3895895Syz147064 };
3905895Syz147064 
3915895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
3925895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
3935895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
3945895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
3955895Syz147064 };
3965895Syz147064 
397*10491SRishi.Srivatsavai@Sun.COM static  val_desc_t	stp_p2p_vals[] = {
398*10491SRishi.Srivatsavai@Sun.COM 	{ "true",	P2P_FORCE_TRUE		},
399*10491SRishi.Srivatsavai@Sun.COM 	{ "false",	P2P_FORCE_FALSE		},
400*10491SRishi.Srivatsavai@Sun.COM 	{ "auto",	P2P_AUTO		}
401*10491SRishi.Srivatsavai@Sun.COM };
402*10491SRishi.Srivatsavai@Sun.COM 
4038275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
4048275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
4058275SEric Cheng 
4063448Sdh155122 static prop_desc_t	prop_table[] = {
4075903Ssowmini 	{ "channel",	{ NULL, 0 },
4085903Ssowmini 	    NULL, 0, NULL, NULL,
4095895Syz147064 	    do_get_channel_prop, NULL, 0,
4105903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4115895Syz147064 
4125895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
4135895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
4145895Syz147064 	    do_set_powermode_prop, NULL,
4155895Syz147064 	    do_get_powermode_prop, NULL, 0,
4165903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4175895Syz147064 
4185895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
4195895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
4205895Syz147064 	    do_set_radio_prop, NULL,
4215895Syz147064 	    do_get_radio_prop, NULL, 0,
4225903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4235895Syz147064 
4245895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
4255895Syz147064 	    do_set_rate_prop, do_get_rate_mod,
4265895Syz147064 	    do_get_rate_prop, do_check_rate, 0,
4275960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
4285895Syz147064 
4296512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
4307342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL,
4317342SAruna.Ramakrishna@Sun.COM 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
4325903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4335895Syz147064 
4346512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
4353448Sdh155122 	    do_set_zone, NULL,
4367342SAruna.Ramakrishna@Sun.COM 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4375903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4385903Ssowmini 
4398275SEric Cheng 	{ "duplex",	{ "", 0 },
4405903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
4417342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_duplex_get, NULL,
4425903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4435903Ssowmini 
4448275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4455903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4467342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_status_get, NULL,
4476512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4485903Ssowmini 
44910191SSowmini.Varadhan@Sun.COM 	{ "adv_autoneg_cap", { "", 0 },
4505903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4517342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4525903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4535903Ssowmini 
4546512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4559514SGirish.Moodalbail@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get,
456*10491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_get, i_dladm_uint32_check, 0, DATALINK_CLASS_ALL,
4577342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4585903Ssowmini 
4596512Ssowmini 	{ "flowctrl", { "", 0 },
4605903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4617342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
4625903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4635903Ssowmini 
4649449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
4659449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4669449Sxiuyan.wang@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4679449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4689449Sxiuyan.wang@Sun.COM 
4699449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
4709449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4719449Sxiuyan.wang@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4729449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4739449Sxiuyan.wang@Sun.COM 
4746512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4756512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4767342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4775903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4785903Ssowmini 
4796512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
4805903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4817342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4825903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4835903Ssowmini 
4846512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
4855903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4867342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4875903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4885903Ssowmini 
4896512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
4905903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4917342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4925903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4935903Ssowmini 
4946512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
4955903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4967342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4975903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4985903Ssowmini 
4996512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
5005903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5017342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5025903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5035903Ssowmini 
5046512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
5055903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5067342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5075903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5085903Ssowmini 
5096512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
5105903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5117342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5125903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5135903Ssowmini 
5146512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
5155903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5167342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5175903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5185903Ssowmini 
5196512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
5205903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5217342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5225903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5235903Ssowmini 
5246512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
5255903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5267342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5275903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5285903Ssowmini 
5296512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
5305903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5317342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5328275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5338275SEric Cheng 
5348275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
5358275SEric Cheng 	    do_set_res, NULL,
5368460SArtem.Kachitchkin@Sun.COM 	    i_dladm_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
5378275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5388275SEric Cheng 
5398275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
5408275SEric Cheng 	    do_set_cpus, NULL,
5418460SArtem.Kachitchkin@Sun.COM 	    i_dladm_cpus_get, do_check_cpus, 0,
5428275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5438275SEric Cheng 
5448275SEric Cheng 	{ "priority", { "high", RESET_VAL },
5458275SEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
5468460SArtem.Kachitchkin@Sun.COM 	    i_dladm_priority_get, do_check_priority, PD_CHECK_ALLOC,
5478275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5488874SSebastien.Roy@Sun.COM 
5498874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
5508874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
5518874SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_tagmode_get,
5528874SSebastien.Roy@Sun.COM 	    NULL, 0,
5538874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
554*10491SRishi.Srivatsavai@Sun.COM 	    DL_ETHER },
555*10491SRishi.Srivatsavai@Sun.COM 
556*10491SRishi.Srivatsavai@Sun.COM 	{ "forward", { "1", 1 },
557*10491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
558*10491SRishi.Srivatsavai@Sun.COM 	    set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
559*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
560*10491SRishi.Srivatsavai@Sun.COM 
561*10491SRishi.Srivatsavai@Sun.COM 	{ "default_tag", { "1", 1 }, NULL, 0,
562*10491SRishi.Srivatsavai@Sun.COM 	    set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
563*10491SRishi.Srivatsavai@Sun.COM 	    0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
564*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
565*10491SRishi.Srivatsavai@Sun.COM 
566*10491SRishi.Srivatsavai@Sun.COM 	{ "learn_limit", { "1000", 1000 }, NULL, 0,
567*10491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
568*10491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
569*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
570*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
571*10491SRishi.Srivatsavai@Sun.COM 
572*10491SRishi.Srivatsavai@Sun.COM 	{ "learn_decay", { "200", 200 }, NULL, 0,
573*10491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
574*10491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
575*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
576*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
577*10491SRishi.Srivatsavai@Sun.COM 
578*10491SRishi.Srivatsavai@Sun.COM 	{ "stp", { "1", 1 },
579*10491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
580*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
581*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
582*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
583*10491SRishi.Srivatsavai@Sun.COM 
584*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", { "128", 128 }, NULL, 0,
585*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
586*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
587*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
588*10491SRishi.Srivatsavai@Sun.COM 
589*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", { "auto", 0 }, NULL, 0,
590*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
591*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
592*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
593*10491SRishi.Srivatsavai@Sun.COM 
594*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", { "1", 1 },
595*10491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
596*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
597*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
598*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
599*10491SRishi.Srivatsavai@Sun.COM 
600*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", { "auto", P2P_AUTO },
601*10491SRishi.Srivatsavai@Sun.COM 	    stp_p2p_vals, VALCNT(stp_p2p_vals),
602*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
603*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
604*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
605*10491SRishi.Srivatsavai@Sun.COM 
606*10491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", { "0", 0 },
607*10491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
608*10491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
609*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
610*10491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
6113448Sdh155122 };
6123448Sdh155122 
6135895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
6145895Syz147064 
6158275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
6168275SEric Cheng 	{"maxbw",	do_extract_maxbw},
6178275SEric Cheng 	{"priority",	do_extract_priority},
6188275SEric Cheng 	{"cpus",	do_extract_cpus}
6198275SEric Cheng };
6208275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
6218275SEric Cheng 	sizeof (resource_prop_t))
6228275SEric Cheng 
6237663SSowmini.Varadhan@Sun.COM /*
6247663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
6257663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
6267663SSowmini.Varadhan@Sun.COM  */
6277663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
6287663SSowmini.Varadhan@Sun.COM 
6298453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
6308453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
6318453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
6328453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
6338460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
6348460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
6358460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
6368453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
6378453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
6388453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
6398453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
6408453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
6418453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
6428453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
6438275SEric Cheng 
6445895Syz147064 /*
6455895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
6465895Syz147064  * rates to be retrieved. However, we cannot increase it at this
6475895Syz147064  * time because it will break binary compatibility with unbundled
6485895Syz147064  * WiFi drivers and utilities. So for now we define an additional
6495895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
6505895Syz147064  */
6515895Syz147064 #define	MAX_SUPPORT_RATES	64
6525895Syz147064 
6535895Syz147064 #define	AP_ANCHOR	"[anchor]"
6545895Syz147064 #define	AP_DELIMITER	'.'
6555895Syz147064 
6565895Syz147064 static dladm_status_t
6575895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
6585895Syz147064     val_desc_t *vdp)
6595895Syz147064 {
6605895Syz147064 	int		i, j;
6615895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6623147Sxc151355 
6635895Syz147064 	for (j = 0; j < val_cnt; j++) {
6645895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
6655895Syz147064 			if (strcasecmp(*prop_val,
6665895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
6675895Syz147064 				break;
6685895Syz147064 			}
6695895Syz147064 		}
6705895Syz147064 		if (i == pdp->pd_noptval) {
6715895Syz147064 			status = DLADM_STATUS_BADVAL;
6725895Syz147064 			goto done;
6735895Syz147064 		}
6745895Syz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
6755895Syz147064 	}
6765895Syz147064 
6775895Syz147064 done:
6785895Syz147064 	return (status);
6795895Syz147064 }
6805895Syz147064 
6815895Syz147064 static dladm_status_t
6828453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
6838453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
6848453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
6853147Sxc151355 {
6865895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6875895Syz147064 	val_desc_t	*vdp = NULL;
6885895Syz147064 	boolean_t	needfree = B_FALSE;
6895895Syz147064 	uint_t		cnt, i;
6903147Sxc151355 
6915895Syz147064 	if (!(pdp->pd_class & class))
6925895Syz147064 		return (DLADM_STATUS_BADARG);
6935895Syz147064 
6945895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
6953147Sxc151355 		return (DLADM_STATUS_BADARG);
6963147Sxc151355 
6975895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
6985895Syz147064 		return (DLADM_STATUS_TEMPONLY);
6995895Syz147064 
7005895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
7015895Syz147064 		return (DLADM_STATUS_OK);
7025895Syz147064 
7035895Syz147064 	if (pdp->pd_set == NULL)
7045895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
7053448Sdh155122 
7065895Syz147064 	if (prop_val != NULL) {
7075895Syz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
7085895Syz147064 		if (vdp == NULL)
7095895Syz147064 			return (DLADM_STATUS_NOMEM);
7105895Syz147064 
7115895Syz147064 		if (pdp->pd_check != NULL) {
7128275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
7138453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
7148453SAnurag.Maskey@Sun.COM 			    val_cnt, vdp, media);
7155895Syz147064 		} else if (pdp->pd_optval != NULL) {
7165895Syz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
7175895Syz147064 		} else {
7183448Sdh155122 			status = DLADM_STATUS_BADARG;
7193147Sxc151355 		}
7205895Syz147064 
7213147Sxc151355 		if (status != DLADM_STATUS_OK)
7225895Syz147064 			goto done;
7235895Syz147064 
7245895Syz147064 		cnt = val_cnt;
7255895Syz147064 	} else {
7268275SEric Cheng 		boolean_t	defval = B_FALSE;
7278275SEric Cheng 
7285895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
7295895Syz147064 			return (DLADM_STATUS_NOTSUP);
7305895Syz147064 
7317342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
7328275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
7338275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
7346512Ssowmini 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
7356512Ssowmini 				return (DLADM_STATUS_NOMEM);
7367342SAruna.Ramakrishna@Sun.COM 
7378275SEric Cheng 			if (defval) {
7388275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
7398275SEric Cheng 				    sizeof (val_desc_t));
7408275SEric Cheng 			} else if (pdp->pd_check != NULL) {
7418453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
7428453SAnurag.Maskey@Sun.COM 				    prop_val, cnt, vdp, media);
7437342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
7447342SAruna.Ramakrishna@Sun.COM 					goto done;
7457342SAruna.Ramakrishna@Sun.COM 			}
7466512Ssowmini 		} else {
7478453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
7486512Ssowmini 			    media, flags);
7496512Ssowmini 			return (status);
7506512Ssowmini 		}
7515895Syz147064 	}
752*10491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_AFTER_PERM)
753*10491SRishi.Srivatsavai@Sun.COM 		status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
754*10491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_PERMONLY;
755*10491SRishi.Srivatsavai@Sun.COM 	else
756*10491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
757*10491SRishi.Srivatsavai@Sun.COM 		    media);
7585895Syz147064 	if (needfree) {
7595895Syz147064 		for (i = 0; i < cnt; i++)
7605903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
7613147Sxc151355 	}
7625895Syz147064 done:
7635895Syz147064 	free(vdp);
7645895Syz147064 	return (status);
7655895Syz147064 }
7665895Syz147064 
7675895Syz147064 static dladm_status_t
7688453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
7698453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
7705895Syz147064 {
7715895Syz147064 	int			i;
7725895Syz147064 	boolean_t		found = B_FALSE;
7735895Syz147064 	datalink_class_t	class;
7745895Syz147064 	uint32_t		media;
7755895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
7765895Syz147064 
7778453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
7788453SAnurag.Maskey@Sun.COM 	    NULL, 0);
7795895Syz147064 	if (status != DLADM_STATUS_OK)
7805895Syz147064 		return (status);
7815895Syz147064 
7825895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
7835895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
7845895Syz147064 		dladm_status_t	s;
7855895Syz147064 
7865895Syz147064 		if (prop_name != NULL &&
7875895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
7885895Syz147064 			continue;
7895895Syz147064 		found = B_TRUE;
7908453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
7918453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
7923448Sdh155122 
7935895Syz147064 		if (prop_name != NULL) {
7945895Syz147064 			status = s;
7955895Syz147064 			break;
7965895Syz147064 		} else {
7975895Syz147064 			if (s != DLADM_STATUS_OK &&
7985895Syz147064 			    s != DLADM_STATUS_NOTSUP)
7995895Syz147064 				status = s;
8005895Syz147064 		}
8015895Syz147064 	}
8025903Ssowmini 	if (!found) {
8035903Ssowmini 		if (prop_name[0] == '_') {
8045903Ssowmini 			/* other private properties */
8059692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
8069692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
8075903Ssowmini 		} else  {
8085903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
8095903Ssowmini 		}
8105903Ssowmini 	}
8115895Syz147064 
8125895Syz147064 	return (status);
8135895Syz147064 }
8145895Syz147064 
8155895Syz147064 /*
8165895Syz147064  * Set/reset link property for specific link
8175895Syz147064  */
8185895Syz147064 dladm_status_t
8198453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8208453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8215895Syz147064 {
8225895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
8235895Syz147064 
8245895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
8255895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
8265895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
8275895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
8285895Syz147064 		return (DLADM_STATUS_BADARG);
8295895Syz147064 	}
8305895Syz147064 
8319692SRishi.Srivatsavai@Sun.COM 	/*
8329692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
8339692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
8349692SRishi.Srivatsavai@Sun.COM 	 */
8358453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
8365895Syz147064 	    val_cnt, flags);
8375895Syz147064 	if (status != DLADM_STATUS_OK)
8385895Syz147064 		return (status);
8395895Syz147064 
8405895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
8418453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
8423147Sxc151355 		    prop_val, val_cnt);
843*10491SRishi.Srivatsavai@Sun.COM 
844*10491SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
845*10491SRishi.Srivatsavai@Sun.COM 			prop_desc_t *pdp = prop_table;
846*10491SRishi.Srivatsavai@Sun.COM 			int i;
847*10491SRishi.Srivatsavai@Sun.COM 
848*10491SRishi.Srivatsavai@Sun.COM 			for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
849*10491SRishi.Srivatsavai@Sun.COM 				if (!(pdp->pd_flags & PD_AFTER_PERM))
850*10491SRishi.Srivatsavai@Sun.COM 					continue;
851*10491SRishi.Srivatsavai@Sun.COM 				if (prop_name != NULL &&
852*10491SRishi.Srivatsavai@Sun.COM 				    strcasecmp(prop_name, pdp->pd_name) != 0)
853*10491SRishi.Srivatsavai@Sun.COM 					continue;
854*10491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_set(handle, pdp, linkid, NULL,
855*10491SRishi.Srivatsavai@Sun.COM 				    0, flags, 0);
856*10491SRishi.Srivatsavai@Sun.COM 			}
857*10491SRishi.Srivatsavai@Sun.COM 		}
8583147Sxc151355 	}
8593147Sxc151355 	return (status);
8603147Sxc151355 }
8613147Sxc151355 
8625895Syz147064 /*
8638460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
8648460SArtem.Kachitchkin@Sun.COM  *
8658460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
8668460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
8678460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
8688460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
8695895Syz147064  */
8703147Sxc151355 dladm_status_t
8718453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
8728453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
8733147Sxc151355 {
8745895Syz147064 	dladm_status_t		status;
8755895Syz147064 	datalink_class_t	class;
8765895Syz147064 	uint_t			media;
8775895Syz147064 	int			i;
8785895Syz147064 
8795895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
8805895Syz147064 		return (DLADM_STATUS_BADARG);
8815895Syz147064 
8828453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
8838453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8845895Syz147064 	if (status != DLADM_STATUS_OK)
8855895Syz147064 		return (status);
8865895Syz147064 
8878460SArtem.Kachitchkin@Sun.COM 	/* public */
8885895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
8895895Syz147064 		if (!(prop_table[i].pd_class & class))
8905895Syz147064 			continue;
8915895Syz147064 
8925895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
8935895Syz147064 			continue;
8945895Syz147064 
8958453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
8965895Syz147064 		    DLADM_WALK_TERMINATE) {
8975895Syz147064 			break;
8985895Syz147064 		}
8995895Syz147064 	}
9005895Syz147064 
9018460SArtem.Kachitchkin@Sun.COM 	/* private */
9028460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
9038460SArtem.Kachitchkin@Sun.COM 
9048460SArtem.Kachitchkin@Sun.COM 	return (status);
9055895Syz147064 }
9063448Sdh155122 
9075895Syz147064 /*
9085895Syz147064  * Get linkprop of the given specific link.
9095895Syz147064  */
9105895Syz147064 dladm_status_t
9118453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9128453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
9138453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
9145895Syz147064 {
9155895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
9165895Syz147064 	datalink_class_t	class;
9175895Syz147064 	uint_t			media;
9185895Syz147064 	prop_desc_t		*pdp;
9196512Ssowmini 	uint_t			cnt, dld_flags = 0;
9205895Syz147064 	int			i;
9218118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
9225895Syz147064 
9236512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
9249514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_DEFAULT;
9259514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
9269514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_POSSIBLE;
9276512Ssowmini 
9285895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
9295895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
9305895Syz147064 		return (DLADM_STATUS_BADARG);
9315895Syz147064 
9325895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
9335895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
9345895Syz147064 			break;
9355895Syz147064 
9365903Ssowmini 	if (i == DLADM_MAX_PROPS) {
9375903Ssowmini 		if (prop_name[0] == '_') {
9385903Ssowmini 			/*
9395903Ssowmini 			 * private property.
9405903Ssowmini 			 */
9418460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
9428460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
9438460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
9448460SArtem.Kachitchkin@Sun.COM 			else
9458460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
9468460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
9478460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
9485903Ssowmini 		} else {
9495903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
9505903Ssowmini 		}
9515903Ssowmini 	}
9525895Syz147064 
9535895Syz147064 	pdp = &prop_table[i];
9545895Syz147064 
9558453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9568453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9575895Syz147064 	if (status != DLADM_STATUS_OK)
9585895Syz147064 		return (status);
9595895Syz147064 
9605895Syz147064 	if (!(pdp->pd_class & class))
9615895Syz147064 		return (DLADM_STATUS_BADARG);
9625895Syz147064 
9635895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
9643147Sxc151355 		return (DLADM_STATUS_BADARG);
9653147Sxc151355 
9665895Syz147064 	switch (type) {
9675895Syz147064 	case DLADM_PROP_VAL_CURRENT:
9688453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
9698453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
9708118SVasumathi.Sundaram@Sun.COM 		break;
9718118SVasumathi.Sundaram@Sun.COM 
9728118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
9738118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
9748118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
9758118SVasumathi.Sundaram@Sun.COM 		} else {
9768453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
9778453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
9788118SVasumathi.Sundaram@Sun.COM 		}
9798118SVasumathi.Sundaram@Sun.COM 
9808118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
9819055SMichael.Lim@Sun.COM 		*val_cntp = 1;
9828275SEric Cheng 		if (status == DLADM_STATUS_OK)
9838275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
9845895Syz147064 		break;
9855895Syz147064 
9865895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
9876768Sar224390 		/*
9886768Sar224390 		 * If defaults are not defined for the property,
9896768Sar224390 		 * pd_defval.vd_name should be null. If the driver
9906768Sar224390 		 * has to be contacted for the value, vd_name should
9916768Sar224390 		 * be the empty string (""). Otherwise, dladm will
9926768Sar224390 		 * just print whatever is in the table.
9936768Sar224390 		 */
9945895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
9955895Syz147064 			status = DLADM_STATUS_NOTSUP;
9965895Syz147064 			break;
9975895Syz147064 		}
9986512Ssowmini 
9996512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
10008453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
10018453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10026512Ssowmini 		} else {
10036512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
10046512Ssowmini 		}
10055895Syz147064 		*val_cntp = 1;
10065895Syz147064 		break;
10073448Sdh155122 
10085895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
10095895Syz147064 		if (pdp->pd_getmod != NULL) {
10108453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
10118118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10125895Syz147064 			break;
10135895Syz147064 		}
10145895Syz147064 		cnt = pdp->pd_noptval;
10155895Syz147064 		if (cnt == 0) {
10165895Syz147064 			status = DLADM_STATUS_NOTSUP;
10175895Syz147064 		} else if (cnt > *val_cntp) {
10185895Syz147064 			status = DLADM_STATUS_TOOSMALL;
10195895Syz147064 		} else {
10205895Syz147064 			for (i = 0; i < cnt; i++) {
10215895Syz147064 				(void) strcpy(prop_val[i],
10225895Syz147064 				    pdp->pd_optval[i].vd_name);
10235895Syz147064 			}
10245895Syz147064 			*val_cntp = cnt;
10255895Syz147064 		}
10265895Syz147064 		break;
10275895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
10285895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
10295895Syz147064 			return (DLADM_STATUS_TEMPONLY);
10308453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
10315895Syz147064 		    prop_val, val_cntp);
10325895Syz147064 		break;
10335895Syz147064 	default:
10345895Syz147064 		status = DLADM_STATUS_BADARG;
10355895Syz147064 		break;
10363147Sxc151355 	}
10373448Sdh155122 
10385895Syz147064 	return (status);
10395895Syz147064 }
10405895Syz147064 
1041*10491SRishi.Srivatsavai@Sun.COM /*
1042*10491SRishi.Srivatsavai@Sun.COM  * Get linkprop of the given specific link and run any possible conversion
1043*10491SRishi.Srivatsavai@Sun.COM  * of the values using the check function for the property. Fails if the
1044*10491SRishi.Srivatsavai@Sun.COM  * check function doesn't succeed for the property value.
1045*10491SRishi.Srivatsavai@Sun.COM  */
1046*10491SRishi.Srivatsavai@Sun.COM dladm_status_t
1047*10491SRishi.Srivatsavai@Sun.COM dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
1048*10491SRishi.Srivatsavai@Sun.COM     dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
1049*10491SRishi.Srivatsavai@Sun.COM     uint_t *val_cntp)
1050*10491SRishi.Srivatsavai@Sun.COM {
1051*10491SRishi.Srivatsavai@Sun.COM 	dladm_status_t		status;
1052*10491SRishi.Srivatsavai@Sun.COM 	datalink_class_t	class;
1053*10491SRishi.Srivatsavai@Sun.COM 	uint_t			media;
1054*10491SRishi.Srivatsavai@Sun.COM 	prop_desc_t		*pdp;
1055*10491SRishi.Srivatsavai@Sun.COM 	uint_t			dld_flags;
1056*10491SRishi.Srivatsavai@Sun.COM 	int			valc, i;
1057*10491SRishi.Srivatsavai@Sun.COM 	char			**prop_val;
1058*10491SRishi.Srivatsavai@Sun.COM 	uint_t			perm_flags;
1059*10491SRishi.Srivatsavai@Sun.COM 
1060*10491SRishi.Srivatsavai@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
1061*10491SRishi.Srivatsavai@Sun.COM 	    ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
1062*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
1063*10491SRishi.Srivatsavai@Sun.COM 
1064*10491SRishi.Srivatsavai@Sun.COM 	for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
1065*10491SRishi.Srivatsavai@Sun.COM 		if (strcasecmp(prop_name, pdp->pd_name) == 0)
1066*10491SRishi.Srivatsavai@Sun.COM 			break;
1067*10491SRishi.Srivatsavai@Sun.COM 
1068*10491SRishi.Srivatsavai@Sun.COM 	if (pdp == prop_table + DLADM_MAX_PROPS)
1069*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
1070*10491SRishi.Srivatsavai@Sun.COM 
1071*10491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_CHECK_ALLOC)
1072*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
1073*10491SRishi.Srivatsavai@Sun.COM 
1074*10491SRishi.Srivatsavai@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
1075*10491SRishi.Srivatsavai@Sun.COM 	    NULL, 0);
1076*10491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
1077*10491SRishi.Srivatsavai@Sun.COM 		return (status);
1078*10491SRishi.Srivatsavai@Sun.COM 
1079*10491SRishi.Srivatsavai@Sun.COM 	if (!(pdp->pd_class & class))
1080*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
1081*10491SRishi.Srivatsavai@Sun.COM 
1082*10491SRishi.Srivatsavai@Sun.COM 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
1083*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
1084*10491SRishi.Srivatsavai@Sun.COM 
1085*10491SRishi.Srivatsavai@Sun.COM 	prop_val = malloc(*val_cntp * sizeof (*prop_val) +
1086*10491SRishi.Srivatsavai@Sun.COM 	    *val_cntp * DLADM_PROP_VAL_MAX);
1087*10491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL)
1088*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOMEM);
1089*10491SRishi.Srivatsavai@Sun.COM 	for (valc = 0; valc < *val_cntp; valc++)
1090*10491SRishi.Srivatsavai@Sun.COM 		prop_val[valc] = (char *)(prop_val + *val_cntp) +
1091*10491SRishi.Srivatsavai@Sun.COM 		    valc * DLADM_PROP_VAL_MAX;
1092*10491SRishi.Srivatsavai@Sun.COM 
1093*10491SRishi.Srivatsavai@Sun.COM 	dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? MAC_PROP_DEFAULT : 0;
1094*10491SRishi.Srivatsavai@Sun.COM 
1095*10491SRishi.Srivatsavai@Sun.COM 	switch (type) {
1096*10491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_CURRENT:
1097*10491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1098*10491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
1099*10491SRishi.Srivatsavai@Sun.COM 		break;
1100*10491SRishi.Srivatsavai@Sun.COM 
1101*10491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_DEFAULT:
1102*10491SRishi.Srivatsavai@Sun.COM 		/*
1103*10491SRishi.Srivatsavai@Sun.COM 		 * If defaults are not defined for the property,
1104*10491SRishi.Srivatsavai@Sun.COM 		 * pd_defval.vd_name should be null. If the driver
1105*10491SRishi.Srivatsavai@Sun.COM 		 * has to be contacted for the value, vd_name should
1106*10491SRishi.Srivatsavai@Sun.COM 		 * be the empty string (""). Otherwise, dladm will
1107*10491SRishi.Srivatsavai@Sun.COM 		 * just print whatever is in the table.
1108*10491SRishi.Srivatsavai@Sun.COM 		 */
1109*10491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name == NULL) {
1110*10491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_NOTSUP;
1111*10491SRishi.Srivatsavai@Sun.COM 			break;
1112*10491SRishi.Srivatsavai@Sun.COM 		}
1113*10491SRishi.Srivatsavai@Sun.COM 
1114*10491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name[0] != '\0') {
1115*10491SRishi.Srivatsavai@Sun.COM 			*val_cntp = 1;
1116*10491SRishi.Srivatsavai@Sun.COM 			*ret_val = pdp->pd_defval.vd_val;
1117*10491SRishi.Srivatsavai@Sun.COM 			free(prop_val);
1118*10491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
1119*10491SRishi.Srivatsavai@Sun.COM 		}
1120*10491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
1121*10491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
1122*10491SRishi.Srivatsavai@Sun.COM 		break;
1123*10491SRishi.Srivatsavai@Sun.COM 
1124*10491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_PERSISTENT:
1125*10491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_flags & PD_TEMPONLY)
1126*10491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_TEMPONLY;
1127*10491SRishi.Srivatsavai@Sun.COM 		else
1128*10491SRishi.Srivatsavai@Sun.COM 			status = i_dladm_get_linkprop_db(handle, linkid,
1129*10491SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cntp);
1130*10491SRishi.Srivatsavai@Sun.COM 		break;
1131*10491SRishi.Srivatsavai@Sun.COM 
1132*10491SRishi.Srivatsavai@Sun.COM 	default:
1133*10491SRishi.Srivatsavai@Sun.COM 		status = DLADM_STATUS_BADARG;
1134*10491SRishi.Srivatsavai@Sun.COM 		break;
1135*10491SRishi.Srivatsavai@Sun.COM 	}
1136*10491SRishi.Srivatsavai@Sun.COM 
1137*10491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
1138*10491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_check != NULL) {
1139*10491SRishi.Srivatsavai@Sun.COM 			val_desc_t *vdp;
1140*10491SRishi.Srivatsavai@Sun.COM 
1141*10491SRishi.Srivatsavai@Sun.COM 			vdp = malloc(sizeof (val_desc_t) * *val_cntp);
1142*10491SRishi.Srivatsavai@Sun.COM 			if (vdp == NULL)
1143*10491SRishi.Srivatsavai@Sun.COM 				status = DLADM_STATUS_NOMEM;
1144*10491SRishi.Srivatsavai@Sun.COM 			else
1145*10491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
1146*10491SRishi.Srivatsavai@Sun.COM 				    prop_val, *val_cntp, vdp, media);
1147*10491SRishi.Srivatsavai@Sun.COM 			if (status == DLADM_STATUS_OK) {
1148*10491SRishi.Srivatsavai@Sun.COM 				for (valc = 0; valc < *val_cntp; valc++)
1149*10491SRishi.Srivatsavai@Sun.COM 					ret_val[valc] = vdp[valc].vd_val;
1150*10491SRishi.Srivatsavai@Sun.COM 			}
1151*10491SRishi.Srivatsavai@Sun.COM 			free(vdp);
1152*10491SRishi.Srivatsavai@Sun.COM 		} else {
1153*10491SRishi.Srivatsavai@Sun.COM 			for (valc = 0; valc < *val_cntp; valc++) {
1154*10491SRishi.Srivatsavai@Sun.COM 				for (i = 0; i < pdp->pd_noptval; i++) {
1155*10491SRishi.Srivatsavai@Sun.COM 					if (strcmp(pdp->pd_optval[i].vd_name,
1156*10491SRishi.Srivatsavai@Sun.COM 					    prop_val[valc]) == 0) {
1157*10491SRishi.Srivatsavai@Sun.COM 						ret_val[valc] =
1158*10491SRishi.Srivatsavai@Sun.COM 						    pdp->pd_optval[i].vd_val;
1159*10491SRishi.Srivatsavai@Sun.COM 						break;
1160*10491SRishi.Srivatsavai@Sun.COM 					}
1161*10491SRishi.Srivatsavai@Sun.COM 				}
1162*10491SRishi.Srivatsavai@Sun.COM 				if (i == pdp->pd_noptval) {
1163*10491SRishi.Srivatsavai@Sun.COM 					status = DLADM_STATUS_FAILED;
1164*10491SRishi.Srivatsavai@Sun.COM 					break;
1165*10491SRishi.Srivatsavai@Sun.COM 				}
1166*10491SRishi.Srivatsavai@Sun.COM 			}
1167*10491SRishi.Srivatsavai@Sun.COM 		}
1168*10491SRishi.Srivatsavai@Sun.COM 	}
1169*10491SRishi.Srivatsavai@Sun.COM 
1170*10491SRishi.Srivatsavai@Sun.COM 	free(prop_val);
1171*10491SRishi.Srivatsavai@Sun.COM 
1172*10491SRishi.Srivatsavai@Sun.COM 	return (status);
1173*10491SRishi.Srivatsavai@Sun.COM }
1174*10491SRishi.Srivatsavai@Sun.COM 
11755895Syz147064 /*ARGSUSED*/
11765895Syz147064 static int
11778453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
11788453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
11795895Syz147064 {
11805895Syz147064 	char	*buf, **propvals;
11815895Syz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
11825895Syz147064 
11835895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
11845895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
11855895Syz147064 		return (DLADM_WALK_CONTINUE);
11865895Syz147064 	}
11875895Syz147064 
11885895Syz147064 	propvals = (char **)(void *)buf;
11895895Syz147064 	for (i = 0; i < valcnt; i++) {
11905895Syz147064 		propvals[i] = buf +
11915895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
11925895Syz147064 		    i * DLADM_PROP_VAL_MAX;
11935895Syz147064 	}
11945895Syz147064 
11958453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
11968453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
11975895Syz147064 		goto done;
11985895Syz147064 	}
11995895Syz147064 
12008453SAnurag.Maskey@Sun.COM 	(void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
12015895Syz147064 	    DLADM_OPT_ACTIVE);
12025895Syz147064 
12035895Syz147064 done:
12045895Syz147064 	if (buf != NULL)
12055895Syz147064 		free(buf);
12065895Syz147064 
12075895Syz147064 	return (DLADM_WALK_CONTINUE);
12085895Syz147064 }
12095895Syz147064 
12105895Syz147064 /*ARGSUSED*/
12115895Syz147064 static int
12128453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
12135895Syz147064 {
12148275SEric Cheng 	datalink_class_t	class;
12158275SEric Cheng 	dladm_status_t		status;
12168275SEric Cheng 
12178453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
12188453SAnurag.Maskey@Sun.COM 	    NULL, 0);
12198275SEric Cheng 	if (status != DLADM_STATUS_OK)
12208275SEric Cheng 		return (DLADM_WALK_TERMINATE);
12218275SEric Cheng 
12228275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
12238453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
12248275SEric Cheng 
12255895Syz147064 	return (DLADM_WALK_CONTINUE);
12265895Syz147064 }
12275895Syz147064 
12285895Syz147064 dladm_status_t
12298453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
12308453SAnurag.Maskey@Sun.COM     boolean_t any_media)
12315895Syz147064 {
12326916Sartem 	datalink_media_t	dmedia;
12336916Sartem 	uint32_t		media;
12346916Sartem 
12356916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
12366916Sartem 
12375895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
12388453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
12398453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
12408453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
12418453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
12428453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
12436916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
12448453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, NULL,
12458453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
12463448Sdh155122 	}
12473448Sdh155122 	return (DLADM_STATUS_OK);
12483147Sxc151355 }
12493147Sxc151355 
12505903Ssowmini /* ARGSUSED */
12515895Syz147064 static dladm_status_t
12528453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12538275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12548275SEric Cheng     uint_t flags, uint_t *perm_flags)
12553147Sxc151355 {
12568275SEric Cheng 	char			zone_name[ZONENAME_MAX];
12578275SEric Cheng 	zoneid_t		zid;
12588275SEric Cheng 	dladm_status_t		status;
12598275SEric Cheng 	char			*cp;
12607342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
12613147Sxc151355 
12626512Ssowmini 	if (flags != 0)
12636512Ssowmini 		return (DLADM_STATUS_NOTSUP);
12646512Ssowmini 
12658453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
12668275SEric Cheng 	    &status, perm_flags);
12675895Syz147064 	if (status != DLADM_STATUS_OK)
12683448Sdh155122 		return (status);
12693448Sdh155122 
12707342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
12717342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
12727342SAruna.Ramakrishna@Sun.COM 	free(dip);
12737342SAruna.Ramakrishna@Sun.COM 
12745895Syz147064 	*val_cnt = 1;
12755895Syz147064 	if (zid != GLOBAL_ZONEID) {
12768118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
12775895Syz147064 			return (dladm_errno2status(errno));
12788118SVasumathi.Sundaram@Sun.COM 		}
12793147Sxc151355 
12805895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
12813147Sxc151355 	} else {
12825895Syz147064 		*prop_val[0] = '\0';
12833147Sxc151355 	}
12843147Sxc151355 
12853448Sdh155122 	return (DLADM_STATUS_OK);
12863448Sdh155122 }
12873448Sdh155122 
12883448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
12893448Sdh155122 
12903448Sdh155122 static int
12913448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
12923448Sdh155122 {
12933448Sdh155122 	char			root[MAXPATHLEN];
12943448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
12953448Sdh155122 	void			*dlhandle;
12963448Sdh155122 	void			*sym;
12973448Sdh155122 	int			ret;
12983448Sdh155122 
12993448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
13003448Sdh155122 		return (-1);
13013448Sdh155122 
13023448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
13033448Sdh155122 		(void) dlclose(dlhandle);
13043448Sdh155122 		return (-1);
13053448Sdh155122 	}
13063448Sdh155122 
13073448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
13083448Sdh155122 
13093448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
13103448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
13113448Sdh155122 	(void) dlclose(dlhandle);
13123448Sdh155122 	return (ret);
13133448Sdh155122 }
13143448Sdh155122 
13153448Sdh155122 static dladm_status_t
13168453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
13178453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
13183448Sdh155122 {
13193448Sdh155122 	char		path[MAXPATHLEN];
13205895Syz147064 	char		name[MAXLINKNAMELEN];
13213448Sdh155122 	di_prof_t	prof = NULL;
13223448Sdh155122 	char		zone_name[ZONENAME_MAX];
13233448Sdh155122 	dladm_status_t	status;
13245895Syz147064 	int		ret;
13253448Sdh155122 
13263448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
13273448Sdh155122 		return (dladm_errno2status(errno));
13283448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
13293448Sdh155122 		return (dladm_errno2status(errno));
13303448Sdh155122 	if (di_prof_init(path, &prof) != 0)
13313448Sdh155122 		return (dladm_errno2status(errno));
13323448Sdh155122 
13338453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
13345895Syz147064 	if (status != DLADM_STATUS_OK)
13355895Syz147064 		goto cleanup;
13365895Syz147064 
13375895Syz147064 	if (add)
13385895Syz147064 		ret = di_prof_add_dev(prof, name);
13395895Syz147064 	else
13405895Syz147064 		ret = di_prof_add_exclude(prof, name);
13415895Syz147064 
13425895Syz147064 	if (ret != 0) {
13433448Sdh155122 		status = dladm_errno2status(errno);
13443448Sdh155122 		goto cleanup;
13453448Sdh155122 	}
13463448Sdh155122 
13473448Sdh155122 	if (di_prof_commit(prof) != 0)
13483448Sdh155122 		status = dladm_errno2status(errno);
13493448Sdh155122 cleanup:
13503448Sdh155122 	if (prof)
13513448Sdh155122 		di_prof_fini(prof);
13523448Sdh155122 
13533448Sdh155122 	return (status);
13543448Sdh155122 }
13553448Sdh155122 
13565903Ssowmini /* ARGSUSED */
13573448Sdh155122 static dladm_status_t
13588453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13598453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13603448Sdh155122 {
13618275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
13628275SEric Cheng 	zoneid_t		zid_old, zid_new;
13638275SEric Cheng 	char			link[MAXLINKNAMELEN];
13648275SEric Cheng 	char			*cp;
13657342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
13667342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
13673448Sdh155122 
13683448Sdh155122 	if (val_cnt != 1)
13693448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
13703448Sdh155122 
13717342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
13727342SAruna.Ramakrishna@Sun.COM 
13738453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13748275SEric Cheng 	    &status, NULL);
13758275SEric Cheng 	if (status != DLADM_STATUS_OK)
13768275SEric Cheng 		return (status);
13778275SEric Cheng 
13788275SEric Cheng 	cp = dip->pr_val;
13798275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
13808275SEric Cheng 	free(dip);
13817342SAruna.Ramakrishna@Sun.COM 
13827342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
13837342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
13843448Sdh155122 
13853448Sdh155122 	/* Do nothing if setting to current value */
13863448Sdh155122 	if (zid_new == zid_old)
13875895Syz147064 		return (status);
13885895Syz147064 
13895895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
13905895Syz147064 		/*
13915895Syz147064 		 * If the new zoneid is the global zone, we could destroy
13925895Syz147064 		 * the link (in the case of an implicitly-created VLAN) as a
13937342SAruna.Ramakrishna@Sun.COM 		 * result of setting the zoneid. In that case, we defer the
13947342SAruna.Ramakrishna@Sun.COM 		 * operation to the end of this function to avoid recreating
13957342SAruna.Ramakrishna@Sun.COM 		 * the VLAN and getting a different linkid during the rollback
13967342SAruna.Ramakrishna@Sun.COM 		 * if other operation fails.
13975895Syz147064 		 *
13987342SAruna.Ramakrishna@Sun.COM 		 * Otherwise, this operation will hold a reference to the
13995895Syz147064 		 * link and prevent a link renaming, so we need to do it
14005895Syz147064 		 * before other operations.
14015895Syz147064 		 */
14028453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
14038453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
14045895Syz147064 		if (status != DLADM_STATUS_OK)
14055895Syz147064 			return (status);
14065895Syz147064 	}
14075895Syz147064 
14083448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
14095895Syz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
14103448Sdh155122 		    errno != ENXIO) {
14113448Sdh155122 			status = dladm_errno2status(errno);
14123448Sdh155122 			goto rollback1;
14133448Sdh155122 		}
14143448Sdh155122 
14155895Syz147064 		/*
14165895Syz147064 		 * It is okay to fail to update the /dev entry (some
14175895Syz147064 		 * vanity-named links do not have a /dev entry).
14185895Syz147064 		 */
14198453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
14208453SAnurag.Maskey@Sun.COM 		    B_FALSE);
14215895Syz147064 	}
14225895Syz147064 
14235895Syz147064 	if (zid_new != GLOBAL_ZONEID) {
14245895Syz147064 		if (zone_add_datalink(zid_new, link) != 0) {
14255895Syz147064 			status = dladm_errno2status(errno);
14265895Syz147064 			goto rollback2;
14275895Syz147064 		}
14285895Syz147064 
14298453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
14305895Syz147064 	} else {
14318453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_public_prop(handle, pdp, linkid, vdp,
14328453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
14333448Sdh155122 		if (status != DLADM_STATUS_OK)
14343448Sdh155122 			goto rollback2;
14353448Sdh155122 	}
14363448Sdh155122 
14373448Sdh155122 	return (DLADM_STATUS_OK);
14383448Sdh155122 
14393448Sdh155122 rollback2:
14403448Sdh155122 	if (zid_old != GLOBAL_ZONEID)
14418453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid, B_TRUE);
14425895Syz147064 	if (zid_old != GLOBAL_ZONEID)
14435895Syz147064 		(void) zone_add_datalink(zid_old, link);
14443448Sdh155122 rollback1:
14457342SAruna.Ramakrishna@Sun.COM 	if (zid_new != GLOBAL_ZONEID) {
14467342SAruna.Ramakrishna@Sun.COM 		dzp->diz_zid = zid_old;
14478453SAnurag.Maskey@Sun.COM 		(void) i_dladm_set_public_prop(handle, pdp, linkid, vdp,
14488453SAnurag.Maskey@Sun.COM 		    val_cnt, flags, media);
14497342SAruna.Ramakrishna@Sun.COM 	}
14507342SAruna.Ramakrishna@Sun.COM 
14513448Sdh155122 	return (status);
14523448Sdh155122 }
14533448Sdh155122 
14543448Sdh155122 /* ARGSUSED */
14553448Sdh155122 static dladm_status_t
14568453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14578453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14583448Sdh155122 {
14597342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
14607342SAruna.Ramakrishna@Sun.COM 	char		linkname[MAXLINKNAMELEN];
14617342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
14627342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
14637342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
14643448Sdh155122 
14653448Sdh155122 	if (val_cnt != 1)
14663448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14673448Sdh155122 
14687342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
14697342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
14707342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
14713448Sdh155122 
14728453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
14738275SEric Cheng 	    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
14748275SEric Cheng 		goto done;
14757342SAruna.Ramakrishna@Sun.COM 	}
14767342SAruna.Ramakrishna@Sun.COM 
14778275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
14787342SAruna.Ramakrishna@Sun.COM 	if (strlen(linkname) > MAXLINKNAMELEN) {
14797342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
14807342SAruna.Ramakrishna@Sun.COM 		goto done;
14817342SAruna.Ramakrishna@Sun.COM 	}
14827342SAruna.Ramakrishna@Sun.COM 
14837342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
14847342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
14857342SAruna.Ramakrishna@Sun.COM 		goto done;
14867342SAruna.Ramakrishna@Sun.COM 	}
14877342SAruna.Ramakrishna@Sun.COM 
14887342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
14893448Sdh155122 		ushort_t	flags;
14903448Sdh155122 
14917342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
14923448Sdh155122 		    sizeof (flags)) < 0) {
14937342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
14947342SAruna.Ramakrishna@Sun.COM 			goto done;
14953448Sdh155122 		}
14963448Sdh155122 
14973448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
14987342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
14997342SAruna.Ramakrishna@Sun.COM 			goto done;
15003448Sdh155122 		}
15013448Sdh155122 	}
15023448Sdh155122 
15037342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
15047342SAruna.Ramakrishna@Sun.COM 
15057342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
15067342SAruna.Ramakrishna@Sun.COM 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
15077342SAruna.Ramakrishna@Sun.COM 
15087342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
15095895Syz147064 	return (DLADM_STATUS_OK);
15107342SAruna.Ramakrishna@Sun.COM done:
15117342SAruna.Ramakrishna@Sun.COM 	free(dzp);
15127342SAruna.Ramakrishna@Sun.COM 	return (status);
15135895Syz147064 }
15145895Syz147064 
15155903Ssowmini /* ARGSUSED */
15165895Syz147064 static dladm_status_t
15178460SArtem.Kachitchkin@Sun.COM i_dladm_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15188275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15198275SEric Cheng     uint_t flags, uint_t *perm_flags)
15208275SEric Cheng {
15218275SEric Cheng 	dld_ioc_macprop_t	*dip;
15228275SEric Cheng 	mac_resource_props_t	mrp;
15238275SEric Cheng 	dladm_status_t		status;
15248275SEric Cheng 
15258453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15268275SEric Cheng 	    &status, perm_flags);
15278275SEric Cheng 	if (dip == NULL)
15288275SEric Cheng 		return (status);
15298275SEric Cheng 
15308275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
15318275SEric Cheng 	free(dip);
15328275SEric Cheng 
15338275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
15348275SEric Cheng 		(*prop_val)[0] = '\0';
15358275SEric Cheng 	} else {
15368275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
15378275SEric Cheng 	}
15388275SEric Cheng 	*val_cnt = 1;
15398275SEric Cheng 	return (DLADM_STATUS_OK);
15408275SEric Cheng }
15418275SEric Cheng 
15428275SEric Cheng /* ARGSUSED */
15438275SEric Cheng static dladm_status_t
15448453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15458453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
15468275SEric Cheng {
15478275SEric Cheng 	uint64_t	*maxbw;
15488275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15498275SEric Cheng 
15508275SEric Cheng 	if (val_cnt != 1)
15518275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15528275SEric Cheng 
15538275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
15548275SEric Cheng 	if (maxbw == NULL)
15558275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15568275SEric Cheng 
15578275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
15588275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15598275SEric Cheng 		free(maxbw);
15608275SEric Cheng 		return (status);
15618275SEric Cheng 	}
15628275SEric Cheng 
15638275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
15648275SEric Cheng 		free(maxbw);
15658275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
15668275SEric Cheng 	}
15678275SEric Cheng 
15688275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
15698275SEric Cheng 	return (DLADM_STATUS_OK);
15708275SEric Cheng }
15718275SEric Cheng 
15728275SEric Cheng /* ARGSUSED */
15738275SEric Cheng dladm_status_t
15748275SEric Cheng do_extract_maxbw(val_desc_t *vdp, void *arg, uint_t cnt)
15758275SEric Cheng {
15768275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
15778275SEric Cheng 
15788275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
15798275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
15808275SEric Cheng 
15818275SEric Cheng 	return (DLADM_STATUS_OK);
15828275SEric Cheng }
15838275SEric Cheng 
15848275SEric Cheng /* ARGSUSED */
15858275SEric Cheng static dladm_status_t
15868460SArtem.Kachitchkin@Sun.COM i_dladm_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15878275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15888275SEric Cheng     uint_t flags, uint_t *perm_flags)
15898275SEric Cheng {
15908275SEric Cheng 	dld_ioc_macprop_t	*dip;
15918275SEric Cheng 	mac_resource_props_t	mrp;
15928275SEric Cheng 	int			i;
15938275SEric Cheng 	uint32_t		ncpus;
15948275SEric Cheng 	uchar_t			*cp;
15958275SEric Cheng 	dladm_status_t		status;
15968275SEric Cheng 
15978453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15988275SEric Cheng 	    &status, perm_flags);
15998275SEric Cheng 	if (dip == NULL)
16008275SEric Cheng 		return (status);
16018275SEric Cheng 
16028275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
16038275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
16048275SEric Cheng 	free(dip);
16058275SEric Cheng 
16068275SEric Cheng 	ncpus = mrp.mrp_ncpus;
16078275SEric Cheng 
16088275SEric Cheng 	if (ncpus > *val_cnt)
16098275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
16108275SEric Cheng 
16118275SEric Cheng 	if (ncpus == 0) {
16128275SEric Cheng 		(*prop_val)[0] = '\0';
16138275SEric Cheng 		*val_cnt = 1;
16148275SEric Cheng 		return (DLADM_STATUS_OK);
16158275SEric Cheng 	}
16168275SEric Cheng 
16178275SEric Cheng 	*val_cnt = ncpus;
16188275SEric Cheng 	for (i = 0; i < ncpus; i++) {
16198275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
16208275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
16218275SEric Cheng 	}
16228275SEric Cheng 	return (DLADM_STATUS_OK);
16238275SEric Cheng }
16248275SEric Cheng 
16258275SEric Cheng /* ARGSUSED */
16268275SEric Cheng static dladm_status_t
16278453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16288453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16298275SEric Cheng {
16308275SEric Cheng 	mac_resource_props_t	mrp;
16318275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
16328275SEric Cheng 	dld_ioc_macprop_t	*dip;
16338275SEric Cheng 
16348275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16358275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16368275SEric Cheng 	    flags, &status);
16378275SEric Cheng 
16388275SEric Cheng 	if (dip == NULL)
16398275SEric Cheng 		return (status);
16408275SEric Cheng 
16418275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
16428275SEric Cheng 		switch (dip->pr_num) {
16438275SEric Cheng 		case MAC_PROP_MAXBW:
16448275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
16458275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16468275SEric Cheng 			break;
16478275SEric Cheng 		case MAC_PROP_PRIO:
16488275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
16498275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16508275SEric Cheng 			break;
16518275SEric Cheng 		default:
16528275SEric Cheng 			free(dip);
16538275SEric Cheng 			return (DLADM_STATUS_BADARG);
16548275SEric Cheng 		}
16558275SEric Cheng 	} else {
16568275SEric Cheng 		switch (dip->pr_num) {
16578275SEric Cheng 		case MAC_PROP_MAXBW:
16588275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
16598275SEric Cheng 			    sizeof (uint64_t));
16608275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16618275SEric Cheng 			break;
16628275SEric Cheng 		case MAC_PROP_PRIO:
16638275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
16648275SEric Cheng 			    sizeof (mac_priority_level_t));
16658275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16668275SEric Cheng 			break;
16678275SEric Cheng 		default:
16688275SEric Cheng 			free(dip);
16698275SEric Cheng 			return (DLADM_STATUS_BADARG);
16708275SEric Cheng 		}
16718275SEric Cheng 	}
16728275SEric Cheng 
16738275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16748453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16758275SEric Cheng 	free(dip);
16768275SEric Cheng 	return (status);
16778275SEric Cheng }
16788275SEric Cheng 
16798275SEric Cheng /* ARGSUSED */
16808275SEric Cheng static dladm_status_t
16818453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16828453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16838275SEric Cheng {
16848275SEric Cheng 	mac_resource_props_t	mrp;
16858275SEric Cheng 	dladm_status_t		status;
16868275SEric Cheng 	dld_ioc_macprop_t	*dip;
16878275SEric Cheng 	datalink_class_t	class;
16888275SEric Cheng 
16898275SEric Cheng 	/*
16908275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
16918275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
16928275SEric Cheng 	 * the phys_info test only on physical links.
16938275SEric Cheng 	 */
16948453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
16958275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
16968275SEric Cheng 		return (status);
16978275SEric Cheng 	}
16988275SEric Cheng 
16998275SEric Cheng 	/*
17008275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
17018275SEric Cheng 	 * if possible when the setup is complete in MAC.
17028275SEric Cheng 	 */
17038275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
17048275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
17058275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
17068275SEric Cheng 		mac_resource_props_t	*vmrp;
17078275SEric Cheng 
17088275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
17098275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
17108275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
17118275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
17128275SEric Cheng 		}
17138275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
17148275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
17158275SEric Cheng 		mrp.mrp_intr_cpu = -1;
17168275SEric Cheng 	}
17178275SEric Cheng 
17188275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
17198275SEric Cheng 	    flags, &status);
17208275SEric Cheng 	if (dip == NULL)
17218275SEric Cheng 		return (status);
17228275SEric Cheng 
17238275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
17248453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
17258275SEric Cheng 	free(dip);
17268275SEric Cheng 	return (status);
17278275SEric Cheng }
17288275SEric Cheng 
17298275SEric Cheng /* ARGSUSED */
17308275SEric Cheng static dladm_status_t
17318453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17328453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17338275SEric Cheng {
17348275SEric Cheng 	uint32_t		cpuid;
17358275SEric Cheng 	int			i, j, rc;
17368275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
17378275SEric Cheng 	mac_resource_props_t	*mrp;
17388275SEric Cheng 
17398275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
17408275SEric Cheng 	if (mrp == NULL)
17418275SEric Cheng 		return (DLADM_STATUS_NOMEM);
17428275SEric Cheng 
17438275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17448275SEric Cheng 		errno = 0;
17458275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
17468275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
17478275SEric Cheng 			free(mrp);
17488275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
17498275SEric Cheng 		}
17508275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
17518275SEric Cheng 		if (rc < 1) {
17528275SEric Cheng 			free(mrp);
17538275SEric Cheng 			return (DLADM_STATUS_CPUERR);
17548275SEric Cheng 		}
17558275SEric Cheng 		if (rc != P_ONLINE) {
17568275SEric Cheng 			free(mrp);
17578275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
17588275SEric Cheng 		}
17598275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
17608275SEric Cheng 	}
17618275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
17628275SEric Cheng 
17638275SEric Cheng 	/* Check for duplicates */
17648275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17658275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
17668275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
17678275SEric Cheng 				free(mrp);
17688275SEric Cheng 				return (DLADM_STATUS_BADARG);
17698275SEric Cheng 			}
17708275SEric Cheng 		}
17718275SEric Cheng 	}
17728275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
17738275SEric Cheng 
17748275SEric Cheng 	return (DLADM_STATUS_OK);
17758275SEric Cheng }
17768275SEric Cheng 
17778275SEric Cheng /* ARGSUSED */
17788275SEric Cheng dladm_status_t
17798275SEric Cheng do_extract_cpus(val_desc_t *vdp, void *arg, uint_t cnt)
17808275SEric Cheng {
17818275SEric Cheng 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
17828275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
17838275SEric Cheng 	int			i;
17848275SEric Cheng 
17858275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
17868275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
17878275SEric Cheng 	}
17888275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
17898275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
17908275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
17919055SMichael.Lim@Sun.COM 	mrp->mrp_intr_cpu = -1;
17928275SEric Cheng 
17938275SEric Cheng 	return (DLADM_STATUS_OK);
17948275SEric Cheng }
17958275SEric Cheng 
17968275SEric Cheng /* ARGSUSED */
17978275SEric Cheng static dladm_status_t
17988460SArtem.Kachitchkin@Sun.COM i_dladm_priority_get(dladm_handle_t handle, prop_desc_t *pdp,
17998460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
18008460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
18018275SEric Cheng {
18028275SEric Cheng 	dld_ioc_macprop_t	*dip;
18038275SEric Cheng 	mac_resource_props_t	mrp;
18048275SEric Cheng 	mac_priority_level_t	pri;
18058275SEric Cheng 	dladm_status_t		status;
18068275SEric Cheng 
18078453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
18088275SEric Cheng 	    &status, perm_flags);
18098275SEric Cheng 	if (dip == NULL)
18108275SEric Cheng 		return (status);
18118275SEric Cheng 
18128275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
18138275SEric Cheng 	free(dip);
18148275SEric Cheng 
18158275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
18168275SEric Cheng 	    mrp.mrp_priority;
18178275SEric Cheng 
18188275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
18198275SEric Cheng 	*val_cnt = 1;
18208275SEric Cheng 	return (DLADM_STATUS_OK);
18218275SEric Cheng }
18228275SEric Cheng 
18238275SEric Cheng /* ARGSUSED */
18248275SEric Cheng static dladm_status_t
18258453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18268453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
18278275SEric Cheng {
18288275SEric Cheng 	mac_priority_level_t	*pri;
18298275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
18308275SEric Cheng 
18318275SEric Cheng 	if (val_cnt != 1)
18328275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
18338275SEric Cheng 
18348275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
18358275SEric Cheng 	if (pri == NULL)
18368275SEric Cheng 		return (DLADM_STATUS_NOMEM);
18378275SEric Cheng 
18388275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
18398275SEric Cheng 	if (status != DLADM_STATUS_OK) {
18408275SEric Cheng 		free(pri);
18418275SEric Cheng 		return (status);
18428275SEric Cheng 	}
18438275SEric Cheng 
18448275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
18458275SEric Cheng 		free(pri);
18468275SEric Cheng 		return (DLADM_STATUS_BADVAL);
18478275SEric Cheng 	}
18488275SEric Cheng 
18498275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
18508275SEric Cheng 	return (DLADM_STATUS_OK);
18518275SEric Cheng }
18528275SEric Cheng 
18538275SEric Cheng /* ARGSUSED */
18548275SEric Cheng dladm_status_t
18558275SEric Cheng do_extract_priority(val_desc_t *vdp, void *arg, uint_t cnt)
18568275SEric Cheng {
18578275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
18588275SEric Cheng 
18598275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
18608275SEric Cheng 	    sizeof (mac_priority_level_t));
18618275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
18628275SEric Cheng 
18638275SEric Cheng 	return (DLADM_STATUS_OK);
18648275SEric Cheng }
18658275SEric Cheng 
18668275SEric Cheng /* ARGSUSED */
18678275SEric Cheng static dladm_status_t
18688453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18698275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
18708275SEric Cheng     uint_t flags, uint_t *perm_flags)
18715895Syz147064 {
18727342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
18737342SAruna.Ramakrishna@Sun.COM 	int		i, len;
18747342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
18757342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
18765895Syz147064 
18776789Sam223141 	if (flags & MAC_PROP_DEFAULT)
18787776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
18796512Ssowmini 
18805895Syz147064 	*val_cnt = 1;
18818453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
18828275SEric Cheng 	    &status, perm_flags);
18837342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
18845895Syz147064 		(*prop_val)[0] = '\0';
18858275SEric Cheng 		return (DLADM_STATUS_OK);
18865895Syz147064 	}
18877342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
18885895Syz147064 
18897342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
18905895Syz147064 		if (i != 0) {
18915895Syz147064 			(void) snprintf(*prop_val + len,
18925895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
18935895Syz147064 			len += 1;
18945895Syz147064 		}
18955895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
18967342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
18977342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
18987342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
18995895Syz147064 			(void) snprintf(*prop_val + len,
19005895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
19015895Syz147064 			    AP_ANCHOR);
19025895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
19035895Syz147064 		}
19045895Syz147064 	}
19057342SAruna.Ramakrishna@Sun.COM 	free(dip);
19065895Syz147064 done:
19075895Syz147064 	return (DLADM_STATUS_OK);
19085895Syz147064 }
19095895Syz147064 
19105895Syz147064 /*
19115895Syz147064  * Add the specified module to the dlautopush structure; returns a
19125895Syz147064  * DLADM_STATUS_* code.
19135895Syz147064  */
19145895Syz147064 dladm_status_t
19155895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
19165895Syz147064 {
19175895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
19185895Syz147064 		return (DLADM_STATUS_BADVAL);
19195895Syz147064 
19205895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
19215895Syz147064 		/*
19225895Syz147064 		 * We don't allow multiple anchors, and the anchor must
19235895Syz147064 		 * be after at least one module.
19245895Syz147064 		 */
19255895Syz147064 		if (dlap->dap_anchor != 0)
19265895Syz147064 			return (DLADM_STATUS_BADVAL);
19275895Syz147064 		if (dlap->dap_npush == 0)
19285895Syz147064 			return (DLADM_STATUS_BADVAL);
19295895Syz147064 
19305895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
19315895Syz147064 		return (DLADM_STATUS_OK);
19325895Syz147064 	}
19338957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
19345895Syz147064 		return (DLADM_STATUS_BADVALCNT);
19355895Syz147064 
19365895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
19375895Syz147064 	    FMNAMESZ + 1);
19385895Syz147064 
19395895Syz147064 	return (DLADM_STATUS_OK);
19405895Syz147064 }
19415895Syz147064 
19425895Syz147064 /*
19435895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
19445895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
19455895Syz147064  * latter is used in the autopush(1M) file.
19465895Syz147064  */
19475895Syz147064 /* ARGSUSED */
19485895Syz147064 static dladm_status_t
19498453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19508453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
19515895Syz147064 {
19525895Syz147064 	char			*module;
19535895Syz147064 	struct dlautopush	*dlap;
19545895Syz147064 	dladm_status_t		status;
19555895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
19565895Syz147064 	char			delimiters[4];
19575895Syz147064 
19585895Syz147064 	if (val_cnt != 1)
19595895Syz147064 		return (DLADM_STATUS_BADVALCNT);
19605895Syz147064 
19617342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
19627342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
19637342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
19647342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
19653448Sdh155122 
19667342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
19677342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
19687342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
19697342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
19707342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
19717342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
19727342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
19737342SAruna.Ramakrishna@Sun.COM 				return (status);
19747342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
19757342SAruna.Ramakrishna@Sun.COM 		}
19767342SAruna.Ramakrishna@Sun.COM 
19777342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
19787342SAruna.Ramakrishna@Sun.COM 	} else {
19797342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
19805895Syz147064 	}
19813448Sdh155122 	return (DLADM_STATUS_OK);
19823448Sdh155122 }
19833448Sdh155122 
19847663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
19857663SSowmini.Varadhan@Sun.COM 
19865903Ssowmini /* ARGSUSED */
19873448Sdh155122 static dladm_status_t
19888453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
19898453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
19908453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
19913448Sdh155122 {
19925895Syz147064 	wl_rates_t	*wrp;
19935895Syz147064 	uint_t		i;
19945895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
19955895Syz147064 
19967663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
19977663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
19987663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
19995895Syz147064 
20008453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
20018453SAnurag.Maskey@Sun.COM 	    B_FALSE);
20025895Syz147064 	if (status != DLADM_STATUS_OK)
20035895Syz147064 		goto done;
20045895Syz147064 
20055895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
20065895Syz147064 		status = DLADM_STATUS_TOOSMALL;
20075895Syz147064 		goto done;
20085895Syz147064 	}
20095895Syz147064 
20105895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
20115895Syz147064 		prop_val[0][0] = '\0';
20125895Syz147064 		*val_cnt = 1;
20135895Syz147064 		goto done;
20145895Syz147064 	}
20155895Syz147064 
20165895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
20175895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
20185895Syz147064 		    wrp->wl_rates_rates[i] % 2,
20195895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
20205895Syz147064 	}
20215895Syz147064 	*val_cnt = wrp->wl_rates_num;
20228275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
20233448Sdh155122 
20245895Syz147064 done:
20257663SSowmini.Varadhan@Sun.COM 	free(wrp);
20265895Syz147064 	return (status);
20275895Syz147064 }
20285895Syz147064 
20295895Syz147064 static dladm_status_t
20308453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20318275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
20328275SEric Cheng     uint_t flags, uint_t *perm_flags)
20335895Syz147064 {
20348118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
20358453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
20368275SEric Cheng 		    val_cnt, flags, perm_flags));
20378118SVasumathi.Sundaram@Sun.COM 	}
20385960Ssowmini 
20398453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
20408275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
20415895Syz147064 }
20425895Syz147064 
20436512Ssowmini /* ARGSUSED */
20445895Syz147064 static dladm_status_t
20458453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20468275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
20478275SEric Cheng     uint_t flags, uint_t *perm_flags)
20485895Syz147064 {
20495960Ssowmini 	switch (media) {
20505960Ssowmini 	case DL_ETHER:
20516512Ssowmini 		/*
20526512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
20536512Ssowmini 		 * links can have a speed of 5.5 Gbps.
20546512Ssowmini 		 */
20556512Ssowmini 		return (DLADM_STATUS_NOTSUP);
20565960Ssowmini 
20575960Ssowmini 	case DL_WIFI:
20588453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
20598453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
20605960Ssowmini 	default:
20615960Ssowmini 		return (DLADM_STATUS_BADARG);
20625960Ssowmini 	}
20635895Syz147064 }
20645895Syz147064 
20655895Syz147064 static dladm_status_t
20668453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
20678453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
20685895Syz147064 {
20695895Syz147064 	int		i;
20705895Syz147064 	uint_t		len;
20715895Syz147064 	wl_rates_t	*wrp;
20725895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
20735895Syz147064 
20747663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
20757663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
20765895Syz147064 		return (DLADM_STATUS_NOMEM);
20775895Syz147064 
20787663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
20795895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
20805895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
20815895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
20825895Syz147064 
20835895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
20845895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
20858453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
20868453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
20875895Syz147064 
20887663SSowmini.Varadhan@Sun.COM 	free(wrp);
20895895Syz147064 	return (status);
20905895Syz147064 }
20913448Sdh155122 
20925903Ssowmini /* ARGSUSED */
20935895Syz147064 static dladm_status_t
20948453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20955960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
20965895Syz147064 {
20975895Syz147064 	dladm_wlan_rates_t	rates;
20985895Syz147064 	dladm_status_t		status;
20995895Syz147064 
21005960Ssowmini 	/*
21015960Ssowmini 	 * can currently set rate on WIFI links only.
21025960Ssowmini 	 */
21035960Ssowmini 	if (media != DL_WIFI)
21045960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
21055960Ssowmini 
21065895Syz147064 	if (val_cnt != 1)
21075895Syz147064 		return (DLADM_STATUS_BADVALCNT);
21085895Syz147064 
21095895Syz147064 	rates.wr_cnt = 1;
21105895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
21115895Syz147064 
21128453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
21135895Syz147064 
21145895Syz147064 done:
21155895Syz147064 	return (status);
21165895Syz147064 }
21173448Sdh155122 
21185895Syz147064 /* ARGSUSED */
21195895Syz147064 static dladm_status_t
21208453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21218453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
21225895Syz147064 {
21235895Syz147064 	int		i;
21245895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
21255895Syz147064 	char		*buf, **modval;
21265895Syz147064 	dladm_status_t	status;
21278118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
21285895Syz147064 
21295895Syz147064 	if (val_cnt != 1)
21305895Syz147064 		return (DLADM_STATUS_BADVALCNT);
21315895Syz147064 
21325895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
21335895Syz147064 	    MAX_SUPPORT_RATES);
21345895Syz147064 	if (buf == NULL) {
21355895Syz147064 		status = DLADM_STATUS_NOMEM;
21365895Syz147064 		goto done;
21375895Syz147064 	}
21383448Sdh155122 
21395895Syz147064 	modval = (char **)(void *)buf;
21405895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
21415895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
21425895Syz147064 		    i * DLADM_STRSIZE;
21435895Syz147064 	}
21445895Syz147064 
21458453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
21468453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
21475895Syz147064 	if (status != DLADM_STATUS_OK)
21485895Syz147064 		goto done;
21495895Syz147064 
21505895Syz147064 	for (i = 0; i < modval_cnt; i++) {
21515895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
21525903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
21535903Ssowmini 			    (atof(*prop_val) * 2);
21545895Syz147064 			status = DLADM_STATUS_OK;
21553448Sdh155122 			break;
21563448Sdh155122 		}
21575895Syz147064 	}
21585895Syz147064 	if (i == modval_cnt)
21595895Syz147064 		status = DLADM_STATUS_BADVAL;
21605895Syz147064 done:
21615895Syz147064 	free(buf);
21625895Syz147064 	return (status);
21635895Syz147064 }
21645895Syz147064 
21655895Syz147064 static dladm_status_t
21668453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
21678453SAnurag.Maskey@Sun.COM     int buflen)
21685895Syz147064 {
21698453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
21707663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
21715895Syz147064 }
21725895Syz147064 
21735903Ssowmini /* ARGSUSED */
21745895Syz147064 static dladm_status_t
21758453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
21768453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
21778453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
21785895Syz147064 {
21795895Syz147064 	uint32_t	channel;
21807663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
21815895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21827663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
21835895Syz147064 
21848453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
21857663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
21865895Syz147064 		goto done;
21875895Syz147064 
21887663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
21897663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
21905895Syz147064 		status = DLADM_STATUS_NOTFOUND;
21915895Syz147064 		goto done;
21925895Syz147064 	}
21935895Syz147064 
21945895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
21955895Syz147064 	*val_cnt = 1;
21968275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
21975895Syz147064 done:
21985895Syz147064 	return (status);
21995895Syz147064 }
22005895Syz147064 
22015895Syz147064 static dladm_status_t
22028453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
22038453SAnurag.Maskey@Sun.COM     int buflen)
22045895Syz147064 {
22058453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
22067663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
22075895Syz147064 }
22085895Syz147064 
22095903Ssowmini /* ARGSUSED */
22105895Syz147064 static dladm_status_t
22118453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
22128453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
22138453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
22145895Syz147064 {
22157663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
22165895Syz147064 	const char	*s;
22177663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
22185895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
22195895Syz147064 
22208453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
22217663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
22225895Syz147064 		goto done;
22235895Syz147064 
22247663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
22257663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
22265895Syz147064 	case WL_PM_AM:
22275895Syz147064 		s = "off";
22285895Syz147064 		break;
22295895Syz147064 	case WL_PM_MPS:
22305895Syz147064 		s = "max";
22315895Syz147064 		break;
22325895Syz147064 	case WL_PM_FAST:
22335895Syz147064 		s = "fast";
22343448Sdh155122 		break;
22353448Sdh155122 	default:
22365895Syz147064 		status = DLADM_STATUS_NOTFOUND;
22375895Syz147064 		goto done;
22385895Syz147064 	}
22395895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
22405895Syz147064 	*val_cnt = 1;
22418275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
22425895Syz147064 done:
22435895Syz147064 	return (status);
22445895Syz147064 }
22455895Syz147064 
22465895Syz147064 static dladm_status_t
22478453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
22488453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
22495895Syz147064 {
22505895Syz147064 	wl_ps_mode_t    ps_mode;
22515895Syz147064 
22525895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
22535895Syz147064 
22545895Syz147064 	switch (*pm) {
22555895Syz147064 	case DLADM_WLAN_PM_OFF:
22565895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
22573448Sdh155122 		break;
22585895Syz147064 	case DLADM_WLAN_PM_MAX:
22595895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
22605895Syz147064 		break;
22615895Syz147064 	case DLADM_WLAN_PM_FAST:
22625895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
22635895Syz147064 		break;
22645895Syz147064 	default:
22655895Syz147064 		return (DLADM_STATUS_NOTSUP);
22663448Sdh155122 	}
22678453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
22688453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
22695895Syz147064 }
22705895Syz147064 
22715895Syz147064 /* ARGSUSED */
22725895Syz147064 static dladm_status_t
22738453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
22748453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
22758453SAnurag.Maskey@Sun.COM     datalink_media_t media)
22765895Syz147064 {
22775895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
22785895Syz147064 	dladm_status_t status;
22795895Syz147064 
22805895Syz147064 	if (val_cnt != 1)
22815895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22825895Syz147064 
22838453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
22843448Sdh155122 
22853448Sdh155122 	return (status);
22863448Sdh155122 }
22873448Sdh155122 
22883448Sdh155122 static dladm_status_t
22898453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
22903448Sdh155122 {
22918453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
22928453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
22935895Syz147064 }
22943448Sdh155122 
22955903Ssowmini /* ARGSUSED */
22965895Syz147064 static dladm_status_t
22978453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22988275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
22998275SEric Cheng     uint_t flags, uint_t *perm_flags)
23005895Syz147064 {
23015895Syz147064 	wl_radio_t	radio;
23025895Syz147064 	const char	*s;
23037663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
23045895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
23053448Sdh155122 
23068453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
23077663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
23085895Syz147064 		goto done;
23093448Sdh155122 
23107663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
23115895Syz147064 	switch (radio) {
23125895Syz147064 	case B_TRUE:
23135895Syz147064 		s = "on";
23145895Syz147064 		break;
23155895Syz147064 	case B_FALSE:
23165895Syz147064 		s = "off";
23175895Syz147064 		break;
23185895Syz147064 	default:
23195895Syz147064 		status = DLADM_STATUS_NOTFOUND;
23205895Syz147064 		goto done;
23215895Syz147064 	}
23225895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
23235895Syz147064 	*val_cnt = 1;
23248275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
23255895Syz147064 done:
23263448Sdh155122 	return (status);
23273448Sdh155122 }
23283448Sdh155122 
23293448Sdh155122 static dladm_status_t
23308453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
23318453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
23323448Sdh155122 {
23335895Syz147064 	wl_radio_t r;
23343448Sdh155122 
23355895Syz147064 	switch (*radio) {
23365895Syz147064 	case DLADM_WLAN_RADIO_ON:
23375895Syz147064 		r = B_TRUE;
23385895Syz147064 		break;
23395895Syz147064 	case DLADM_WLAN_RADIO_OFF:
23405895Syz147064 		r = B_FALSE;
23415895Syz147064 		break;
23425895Syz147064 	default:
23435895Syz147064 		return (DLADM_STATUS_NOTSUP);
23445895Syz147064 	}
23458453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
23467663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
23475895Syz147064 }
23483448Sdh155122 
23495895Syz147064 /* ARGSUSED */
23505895Syz147064 static dladm_status_t
23518453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
23525960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
23535895Syz147064 {
23545895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
23555895Syz147064 	dladm_status_t status;
23563448Sdh155122 
23575895Syz147064 	if (val_cnt != 1)
23585895Syz147064 		return (DLADM_STATUS_BADVALCNT);
23595895Syz147064 
23608453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
23613448Sdh155122 
23623448Sdh155122 	return (status);
23633448Sdh155122 }
23643448Sdh155122 
23655895Syz147064 static dladm_status_t
23668453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
23678453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
23683448Sdh155122 {
23695895Syz147064 	char		buf[MAXLINELEN];
23705895Syz147064 	int		i;
23715895Syz147064 	dladm_conf_t	conf;
23725895Syz147064 	dladm_status_t	status;
23733448Sdh155122 
23748453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
23755895Syz147064 	if (status != DLADM_STATUS_OK)
23765895Syz147064 		return (status);
23773448Sdh155122 
23785895Syz147064 	/*
23795895Syz147064 	 * reset case.
23805895Syz147064 	 */
23815895Syz147064 	if (val_cnt == 0) {
23828453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
23835895Syz147064 		if (status == DLADM_STATUS_OK)
23848453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
23855895Syz147064 		goto done;
23865895Syz147064 	}
23873448Sdh155122 
23885895Syz147064 	buf[0] = '\0';
23895895Syz147064 	for (i = 0; i < val_cnt; i++) {
23905895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
23915895Syz147064 		if (i != val_cnt - 1)
23925895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
23933448Sdh155122 	}
23943448Sdh155122 
23958453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
23968453SAnurag.Maskey@Sun.COM 	    buf);
23975895Syz147064 	if (status == DLADM_STATUS_OK)
23988453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
23995895Syz147064 
24005895Syz147064 done:
24018453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
24025895Syz147064 	return (status);
24033448Sdh155122 }
24045895Syz147064 
24055895Syz147064 static dladm_status_t
24068453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
24078453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
24085895Syz147064 {
24095895Syz147064 	char		buf[MAXLINELEN], *str;
24105895Syz147064 	uint_t		cnt = 0;
24115895Syz147064 	dladm_conf_t	conf;
24125895Syz147064 	dladm_status_t	status;
24135895Syz147064 
24148453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
24155895Syz147064 	if (status != DLADM_STATUS_OK)
24165895Syz147064 		return (status);
24175895Syz147064 
24188453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
24195895Syz147064 	if (status != DLADM_STATUS_OK)
24205895Syz147064 		goto done;
24215895Syz147064 
24225895Syz147064 	str = strtok(buf, ",");
24235895Syz147064 	while (str != NULL) {
24245895Syz147064 		if (cnt == *val_cntp) {
24255895Syz147064 			status = DLADM_STATUS_TOOSMALL;
24265895Syz147064 			goto done;
24275895Syz147064 		}
24285895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
24295895Syz147064 		str = strtok(NULL, ",");
24305895Syz147064 	}
24315895Syz147064 
24325895Syz147064 	*val_cntp = cnt;
24335895Syz147064 
24345895Syz147064 done:
24358453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
24365895Syz147064 	return (status);
24375895Syz147064 }
24385903Ssowmini 
24398460SArtem.Kachitchkin@Sun.COM /*
24408460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
24418460SArtem.Kachitchkin@Sun.COM  */
24428460SArtem.Kachitchkin@Sun.COM static dladm_status_t
24438460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
24448460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
24458460SArtem.Kachitchkin@Sun.COM {
24468460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
24478460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
24488460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
24498460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
24508460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
24518460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
24528460SArtem.Kachitchkin@Sun.COM 
24538460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
24548460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
24558460SArtem.Kachitchkin@Sun.COM 
24568460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
24578460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
24588460SArtem.Kachitchkin@Sun.COM 		return (status);
24598460SArtem.Kachitchkin@Sun.COM 
24608460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
24618460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
24628460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
24638460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
24648460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
24658460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
24668460SArtem.Kachitchkin@Sun.COM 				break;
24678460SArtem.Kachitchkin@Sun.COM 		}
24688460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
24698460SArtem.Kachitchkin@Sun.COM 	}
24708460SArtem.Kachitchkin@Sun.COM 
24718460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
24728460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
24738460SArtem.Kachitchkin@Sun.COM }
24748460SArtem.Kachitchkin@Sun.COM 
24757663SSowmini.Varadhan@Sun.COM static link_attr_t *
24765903Ssowmini dladm_name2prop(const char *prop_name)
24775903Ssowmini {
24787663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
24795903Ssowmini 
24807663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
24815903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
24825903Ssowmini 			break;
24835903Ssowmini 	}
24845903Ssowmini 	return (p);
24855903Ssowmini }
24865903Ssowmini 
24877663SSowmini.Varadhan@Sun.COM static link_attr_t *
24887663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
24897663SSowmini.Varadhan@Sun.COM {
24907663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
24917663SSowmini.Varadhan@Sun.COM 
24927663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
24937663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
24947663SSowmini.Varadhan@Sun.COM 			break;
24957663SSowmini.Varadhan@Sun.COM 	}
24967663SSowmini.Varadhan@Sun.COM 	return (p);
24977663SSowmini.Varadhan@Sun.COM }
24985903Ssowmini 
24996789Sam223141 static dld_ioc_macprop_t *
25007663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
25017663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
25027663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
25035903Ssowmini {
25045903Ssowmini 	int dsize;
25056789Sam223141 	dld_ioc_macprop_t *dip;
25065903Ssowmini 
25075903Ssowmini 	*status = DLADM_STATUS_OK;
25086789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
25095903Ssowmini 	dip = malloc(dsize);
25105903Ssowmini 	if (dip == NULL) {
25115903Ssowmini 		*status = DLADM_STATUS_NOMEM;
25125903Ssowmini 		return (NULL);
25135903Ssowmini 	}
25145903Ssowmini 	bzero(dip, dsize);
25155903Ssowmini 	dip->pr_valsize = valsize;
25166512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
25176789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
25185960Ssowmini 	dip->pr_linkid = linkid;
25197663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
25206512Ssowmini 	dip->pr_flags = flags;
25215903Ssowmini 	return (dip);
25225903Ssowmini }
25235903Ssowmini 
25247663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
25257663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
25267663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
25277663SSowmini.Varadhan@Sun.COM {
25287663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
25297663SSowmini.Varadhan@Sun.COM 
25307663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
25317663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
25327663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
25337663SSowmini.Varadhan@Sun.COM 	    flags, status));
25347663SSowmini.Varadhan@Sun.COM }
25357663SSowmini.Varadhan@Sun.COM 
25367663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
25377663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
25387663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
25397663SSowmini.Varadhan@Sun.COM {
25407663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
25417663SSowmini.Varadhan@Sun.COM 
25427663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
25437663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
25447663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
25457663SSowmini.Varadhan@Sun.COM 	    flags, status));
25467663SSowmini.Varadhan@Sun.COM }
25477663SSowmini.Varadhan@Sun.COM 
25485903Ssowmini /* ARGSUSED */
25495903Ssowmini static dladm_status_t
25508453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
25518453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
25528453SAnurag.Maskey@Sun.COM     datalink_media_t media)
25535903Ssowmini {
25546789Sam223141 	dld_ioc_macprop_t	*dip;
25555903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
25565903Ssowmini 	uint8_t		u8;
25575903Ssowmini 	uint16_t	u16;
25585903Ssowmini 	uint32_t	u32;
25595903Ssowmini 	void		*val;
25605903Ssowmini 
25618275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
25625903Ssowmini 	if (dip == NULL)
25635903Ssowmini 		return (status);
25645903Ssowmini 
25658275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
25665903Ssowmini 		val = (void *)vdp->vd_val;
25675903Ssowmini 	else {
25685903Ssowmini 		/*
25695903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
25705903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
25715903Ssowmini 		 */
25725903Ssowmini 		switch (dip->pr_valsize) {
25735903Ssowmini 		case 1:
25745903Ssowmini 			u8 = vdp->vd_val;
25755903Ssowmini 			val = &u8;
25765903Ssowmini 			break;
25775903Ssowmini 		case 2:
25785903Ssowmini 			u16 = vdp->vd_val;
25795903Ssowmini 			val = &u16;
25805903Ssowmini 			break;
25815903Ssowmini 		case 4:
25825903Ssowmini 			u32 = vdp->vd_val;
25835903Ssowmini 			val = &u32;
25845903Ssowmini 			break;
25855903Ssowmini 		default:
25865903Ssowmini 			val = &vdp->vd_val;
25875903Ssowmini 			break;
25885903Ssowmini 		}
25895903Ssowmini 	}
25905903Ssowmini 
25917342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
25927342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
25937342SAruna.Ramakrishna@Sun.COM 	else
25947342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
25957342SAruna.Ramakrishna@Sun.COM 
25968453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
25977663SSowmini.Varadhan@Sun.COM 
25987663SSowmini.Varadhan@Sun.COM done:
25997663SSowmini.Varadhan@Sun.COM 	free(dip);
26007663SSowmini.Varadhan@Sun.COM 	return (status);
26017663SSowmini.Varadhan@Sun.COM }
26027663SSowmini.Varadhan@Sun.COM 
26037663SSowmini.Varadhan@Sun.COM dladm_status_t
26048453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
26057663SSowmini.Varadhan@Sun.COM {
26067663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
26077663SSowmini.Varadhan@Sun.COM 
26088453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
26098453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
26105903Ssowmini 		status = dladm_errno2status(errno);
26118453SAnurag.Maskey@Sun.COM 
26125903Ssowmini 	return (status);
26135903Ssowmini }
26145903Ssowmini 
26156789Sam223141 static dld_ioc_macprop_t *
26168453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
26178453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
26185903Ssowmini {
26196789Sam223141 	dld_ioc_macprop_t *dip = NULL;
26206512Ssowmini 
26217663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
26226512Ssowmini 	if (dip == NULL)
26236512Ssowmini 		return (NULL);
26245903Ssowmini 
26258453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
26266512Ssowmini 	if (*status != DLADM_STATUS_OK) {
26276512Ssowmini 		free(dip);
26286512Ssowmini 		return (NULL);
26296512Ssowmini 	}
26308275SEric Cheng 	if (perm_flags != NULL)
26318275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
26328275SEric Cheng 
26336512Ssowmini 	return (dip);
26345903Ssowmini }
26355903Ssowmini 
26365903Ssowmini /* ARGSUSED */
26375903Ssowmini static dladm_status_t
2638*10491SRishi.Srivatsavai@Sun.COM i_dladm_uint32_check(dladm_handle_t handle, prop_desc_t *pdp,
26398453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
26408453SAnurag.Maskey@Sun.COM     datalink_media_t media)
26415903Ssowmini {
26425903Ssowmini 	if (val_cnt != 1)
26435903Ssowmini 		return (DLADM_STATUS_BADVAL);
2644*10491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
26455903Ssowmini 	return (DLADM_STATUS_OK);
26465903Ssowmini }
26475903Ssowmini 
26485903Ssowmini /* ARGSUSED */
26495903Ssowmini static dladm_status_t
26508453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
26518453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
26528453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
26535903Ssowmini {
26545903Ssowmini 	link_duplex_t   link_duplex;
26555903Ssowmini 	dladm_status_t  status;
26565903Ssowmini 
26578453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
26585903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
26595903Ssowmini 		return (status);
26605903Ssowmini 
26615903Ssowmini 	switch (link_duplex) {
26625903Ssowmini 	case LINK_DUPLEX_FULL:
26635903Ssowmini 		(void) strcpy(*prop_val, "full");
26645903Ssowmini 		break;
26655903Ssowmini 	case LINK_DUPLEX_HALF:
26665903Ssowmini 		(void) strcpy(*prop_val, "half");
26675903Ssowmini 		break;
26685903Ssowmini 	default:
26695903Ssowmini 		(void) strcpy(*prop_val, "unknown");
26705903Ssowmini 		break;
26715903Ssowmini 	}
26725903Ssowmini 	*val_cnt = 1;
26735903Ssowmini 	return (DLADM_STATUS_OK);
26745903Ssowmini }
26755903Ssowmini 
26765903Ssowmini /* ARGSUSED */
26775903Ssowmini static dladm_status_t
26788453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
26798275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
26805903Ssowmini {
26815903Ssowmini 	uint64_t	ifspeed = 0;
26825903Ssowmini 	dladm_status_t status;
26835903Ssowmini 
26848453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
26855903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
26865903Ssowmini 		return (status);
26876512Ssowmini 
26885960Ssowmini 	if ((ifspeed % 1000000) != 0) {
26895960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
26905960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
26915960Ssowmini 	} else {
26925960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
26935960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
26945960Ssowmini 	}
26955903Ssowmini 	*val_cnt = 1;
26968275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
26975903Ssowmini 	return (DLADM_STATUS_OK);
26985903Ssowmini }
26995903Ssowmini 
27005903Ssowmini /* ARGSUSED */
27015903Ssowmini static dladm_status_t
27028453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
27038453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27048453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27055903Ssowmini {
27068275SEric Cheng 	link_state_t		link_state;
27078275SEric Cheng 	dladm_status_t		status;
27088306SSowmini.Varadhan@Sun.COM 
27098453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
27106512Ssowmini 	if (status != DLADM_STATUS_OK)
27115903Ssowmini 		return (status);
27128275SEric Cheng 
27135903Ssowmini 	switch (link_state) {
27145903Ssowmini 	case LINK_STATE_UP:
27155903Ssowmini 		(void) strcpy(*prop_val, "up");
27165903Ssowmini 		break;
27175903Ssowmini 	case LINK_STATE_DOWN:
27185903Ssowmini 		(void) strcpy(*prop_val, "down");
27195903Ssowmini 		break;
27205903Ssowmini 	default:
27215903Ssowmini 		(void) strcpy(*prop_val, "unknown");
27225903Ssowmini 		break;
27235903Ssowmini 	}
27245903Ssowmini 	*val_cnt = 1;
27258306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
27265903Ssowmini 	return (DLADM_STATUS_OK);
27275903Ssowmini }
27285903Ssowmini 
27295903Ssowmini /* ARGSUSED */
27305903Ssowmini static dladm_status_t
27318453SAnurag.Maskey@Sun.COM i_dladm_binary_get(dladm_handle_t handle, prop_desc_t *pdp,
27328453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27338453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27345903Ssowmini {
27356789Sam223141 	dld_ioc_macprop_t *dip;
27365903Ssowmini 	dladm_status_t status;
27375903Ssowmini 
27388453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
27398275SEric Cheng 	    &status, perm_flags);
27406512Ssowmini 	if (dip == NULL)
27415903Ssowmini 		return (status);
27428275SEric Cheng 
27435903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
27445903Ssowmini 	free(dip);
27455903Ssowmini 	*val_cnt = 1;
27465903Ssowmini 	return (DLADM_STATUS_OK);
27475903Ssowmini }
27485903Ssowmini 
27495960Ssowmini /* ARGSUSED */
27505903Ssowmini static dladm_status_t
27518453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
27528453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27538453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27545903Ssowmini {
27556789Sam223141 	dld_ioc_macprop_t *dip;
27568275SEric Cheng 	uint32_t v = 0;
27575903Ssowmini 	uchar_t *cp;
27585903Ssowmini 	dladm_status_t status;
27595903Ssowmini 
27608453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
27618275SEric Cheng 	    &status, perm_flags);
27626512Ssowmini 	if (dip == NULL)
27635903Ssowmini 		return (status);
27648275SEric Cheng 
27655903Ssowmini 	cp = (uchar_t *)dip->pr_val;
27665903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
27676512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
27685903Ssowmini 	free(dip);
27695903Ssowmini 	*val_cnt = 1;
27705903Ssowmini 	return (DLADM_STATUS_OK);
27715903Ssowmini }
27725903Ssowmini 
27739514SGirish.Moodalbail@Sun.COM /*
27749514SGirish.Moodalbail@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
27759514SGirish.Moodalbail@Sun.COM  * for retrieving the property range values.
27769514SGirish.Moodalbail@Sun.COM  */
27779514SGirish.Moodalbail@Sun.COM static int
27789514SGirish.Moodalbail@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
27799514SGirish.Moodalbail@Sun.COM {
27809514SGirish.Moodalbail@Sun.COM 	uint_t count = r->mpr_count;
27819514SGirish.Moodalbail@Sun.COM 
27829514SGirish.Moodalbail@Sun.COM 	*sz = sizeof (mac_propval_range_t);
27839514SGirish.Moodalbail@Sun.COM 	--count;
27849514SGirish.Moodalbail@Sun.COM 
27859514SGirish.Moodalbail@Sun.COM 	switch (r->mpr_type) {
27869514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32:
27879514SGirish.Moodalbail@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
27889514SGirish.Moodalbail@Sun.COM 		return (0);
27899514SGirish.Moodalbail@Sun.COM 	default:
27909514SGirish.Moodalbail@Sun.COM 		break;
27919514SGirish.Moodalbail@Sun.COM 	}
27929514SGirish.Moodalbail@Sun.COM 	*sz = 0;
27939514SGirish.Moodalbail@Sun.COM 	return (EINVAL);
27949514SGirish.Moodalbail@Sun.COM }
27959514SGirish.Moodalbail@Sun.COM 
27969514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
27979514SGirish.Moodalbail@Sun.COM static dladm_status_t
27989514SGirish.Moodalbail@Sun.COM i_dladm_range_get(dladm_handle_t handle, prop_desc_t *pdp,
27999514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28009514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28019514SGirish.Moodalbail@Sun.COM {
28029514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
28039514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
28049514SGirish.Moodalbail@Sun.COM 	size_t	sz;
28059514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
28069514SGirish.Moodalbail@Sun.COM 
28079514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
28089514SGirish.Moodalbail@Sun.COM 
28099514SGirish.Moodalbail@Sun.COM 	/*
28109514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
28119514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
28129514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
28139514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
28149514SGirish.Moodalbail@Sun.COM 	 */
28159514SGirish.Moodalbail@Sun.COM retry:
28169514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
28179514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
28189514SGirish.Moodalbail@Sun.COM 		return (status);
28199514SGirish.Moodalbail@Sun.COM 
28209514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
28219514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
28229514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
28239514SGirish.Moodalbail@Sun.COM 			int err;
28249514SGirish.Moodalbail@Sun.COM 
28259514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
28269514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
28279514SGirish.Moodalbail@Sun.COM 				free(dip);
28289514SGirish.Moodalbail@Sun.COM 				goto retry;
28299514SGirish.Moodalbail@Sun.COM 			} else {
28309514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
28319514SGirish.Moodalbail@Sun.COM 			}
28329514SGirish.Moodalbail@Sun.COM 		}
28339514SGirish.Moodalbail@Sun.COM 		free(dip);
28349514SGirish.Moodalbail@Sun.COM 		return (status);
28359514SGirish.Moodalbail@Sun.COM 	}
28369514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
28379514SGirish.Moodalbail@Sun.COM 
28389514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
28399514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
28409514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
28419514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
28429514SGirish.Moodalbail@Sun.COM 
28439514SGirish.Moodalbail@Sun.COM 		ur = &rangep->range_uint32[0];
28449514SGirish.Moodalbail@Sun.COM 
28459514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
28469514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
28479514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
28489514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
28499514SGirish.Moodalbail@Sun.COM 			} else {
28509514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
28519514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
28529514SGirish.Moodalbail@Sun.COM 			}
28539514SGirish.Moodalbail@Sun.COM 		}
28549514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
28559514SGirish.Moodalbail@Sun.COM 		break;
28569514SGirish.Moodalbail@Sun.COM 	}
28579514SGirish.Moodalbail@Sun.COM 	default:
28589514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
28599514SGirish.Moodalbail@Sun.COM 		break;
28609514SGirish.Moodalbail@Sun.COM 	}
28619514SGirish.Moodalbail@Sun.COM 	free(dip);
28629514SGirish.Moodalbail@Sun.COM 	return (status);
28639514SGirish.Moodalbail@Sun.COM }
28649514SGirish.Moodalbail@Sun.COM 
28655960Ssowmini /* ARGSUSED */
28665903Ssowmini static dladm_status_t
28678874SSebastien.Roy@Sun.COM i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
28688874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28698874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28708874SSebastien.Roy@Sun.COM {
28718874SSebastien.Roy@Sun.COM 	dld_ioc_macprop_t	*dip;
28728874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
28738874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
28748874SSebastien.Roy@Sun.COM 
28758874SSebastien.Roy@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
28768874SSebastien.Roy@Sun.COM 	    &status, perm_flags);
28778874SSebastien.Roy@Sun.COM 	if (dip == NULL)
28788874SSebastien.Roy@Sun.COM 		return (status);
28798874SSebastien.Roy@Sun.COM 	(void) memcpy(&mode, dip->pr_val, sizeof (mode));
28808874SSebastien.Roy@Sun.COM 	free(dip);
28818874SSebastien.Roy@Sun.COM 
28828874SSebastien.Roy@Sun.COM 	switch (mode) {
28838874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
28848874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
28858874SSebastien.Roy@Sun.COM 		break;
28868874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
28878874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
28888874SSebastien.Roy@Sun.COM 		break;
28898874SSebastien.Roy@Sun.COM 	default:
28908874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
28918874SSebastien.Roy@Sun.COM 	}
28928874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
28938874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
28948874SSebastien.Roy@Sun.COM }
28958874SSebastien.Roy@Sun.COM 
28968874SSebastien.Roy@Sun.COM /* ARGSUSED */
28978874SSebastien.Roy@Sun.COM static dladm_status_t
28988453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
28998453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29008453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29015903Ssowmini {
29026789Sam223141 	dld_ioc_macprop_t *dip;
29035903Ssowmini 	link_flowctrl_t v;
29045903Ssowmini 	dladm_status_t status;
29055903Ssowmini 	uchar_t *cp;
29065903Ssowmini 
29078453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29088275SEric Cheng 	    &status, perm_flags);
29096512Ssowmini 	if (dip == NULL)
29105903Ssowmini 		return (status);
29118275SEric Cheng 
29125903Ssowmini 	cp = (uchar_t *)dip->pr_val;
29135903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
29145903Ssowmini 	switch (v) {
29155903Ssowmini 	case LINK_FLOWCTRL_NONE:
29165903Ssowmini 		(void) sprintf(*prop_val, "no");
29175903Ssowmini 		break;
29185903Ssowmini 	case LINK_FLOWCTRL_RX:
29195903Ssowmini 		(void) sprintf(*prop_val, "rx");
29205903Ssowmini 		break;
29215903Ssowmini 	case LINK_FLOWCTRL_TX:
29225903Ssowmini 		(void) sprintf(*prop_val, "tx");
29235903Ssowmini 		break;
29245903Ssowmini 	case LINK_FLOWCTRL_BI:
29255903Ssowmini 		(void) sprintf(*prop_val, "bi");
29265903Ssowmini 		break;
29275903Ssowmini 	}
29285903Ssowmini 	free(dip);
29295903Ssowmini 	*val_cnt = 1;
29305903Ssowmini 	return (DLADM_STATUS_OK);
29315903Ssowmini }
29325903Ssowmini 
29335903Ssowmini 
29345903Ssowmini /* ARGSUSED */
29355903Ssowmini static dladm_status_t
29369692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
29378453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
29388453SAnurag.Maskey@Sun.COM 
29395903Ssowmini {
29407663SSowmini.Varadhan@Sun.COM 	int		i, slen;
29417408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
29426789Sam223141 	dld_ioc_macprop_t *dip = NULL;
29435903Ssowmini 	uchar_t 	*dp;
29447663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
29456512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
29465903Ssowmini 
29475903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
29485903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
29495903Ssowmini 		return (DLADM_STATUS_BADARG);
29505903Ssowmini 	p = dladm_name2prop(prop_name);
29516789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
29525903Ssowmini 		return (DLADM_STATUS_BADARG);
29535903Ssowmini 
29549692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
29559692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
29569692SRishi.Srivatsavai@Sun.COM 
29575903Ssowmini 	/*
29585903Ssowmini 	 * private properties: all parsing is done in the kernel.
29595903Ssowmini 	 * allocate a enough space for each property + its separator (',').
29605903Ssowmini 	 */
29615903Ssowmini 	for (i = 0; i < val_cnt; i++) {
29625903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
29635903Ssowmini 	}
29646512Ssowmini 
29656512Ssowmini 	if (prop_val == NULL) {
29666512Ssowmini 		/*
29676512Ssowmini 		 * getting default value. so use more buffer space.
29686512Ssowmini 		 */
29697663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
29706512Ssowmini 	}
29716512Ssowmini 
29727663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
29736789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
29745903Ssowmini 	if (dip == NULL)
29755903Ssowmini 		return (status);
29765903Ssowmini 
29775903Ssowmini 	dp = (uchar_t *)dip->pr_val;
29785903Ssowmini 	slen = 0;
29797663SSowmini.Varadhan@Sun.COM 
29806512Ssowmini 	if (prop_val == NULL) {
29818453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
29828460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
29836512Ssowmini 	} else {
29846512Ssowmini 		for (i = 0; i < val_cnt; i++) {
29856512Ssowmini 			int plen = 0;
29865903Ssowmini 
29876512Ssowmini 			plen = strlen(prop_val[i]);
29886512Ssowmini 			bcopy(prop_val[i], dp, plen);
29896512Ssowmini 			slen += plen;
29906512Ssowmini 			/*
29916512Ssowmini 			 * add a "," separator and update dp.
29926512Ssowmini 			 */
29936512Ssowmini 			if (i != (val_cnt -1))
29946512Ssowmini 				dp[slen++] = ',';
29956512Ssowmini 			dp += (plen + 1);
29966512Ssowmini 		}
29978460SArtem.Kachitchkin@Sun.COM 	}
29988460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
29998453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
30006512Ssowmini 
30015903Ssowmini 	free(dip);
30026512Ssowmini 	return (status);
30035903Ssowmini }
30045903Ssowmini 
30055903Ssowmini static dladm_status_t
30068460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
30078453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
30088453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
30095903Ssowmini {
30107663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
30116789Sam223141 	dld_ioc_macprop_t *dip = NULL;
30127663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
30135903Ssowmini 
30145903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
30155903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
30165903Ssowmini 		return (DLADM_STATUS_BADARG);
30175903Ssowmini 
30185903Ssowmini 	p = dladm_name2prop(prop_name);
30196789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
30205903Ssowmini 		return (DLADM_STATUS_BADARG);
30215903Ssowmini 
30225903Ssowmini 	/*
30235903Ssowmini 	 * private properties: all parsing is done in the kernel.
30245903Ssowmini 	 */
30257663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
30267663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
30275903Ssowmini 	if (dip == NULL)
30285903Ssowmini 		return (status);
30295903Ssowmini 
30308453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
30318453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
30328118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
30338275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
30348460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
30358460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
30368118SVasumathi.Sundaram@Sun.COM 		} else {
30378118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
30388118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
30398118SVasumathi.Sundaram@Sun.COM 		}
30405903Ssowmini 		*val_cnt = 1;
30418460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
30428460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
30438460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
30445903Ssowmini 	}
30456512Ssowmini 	free(dip);
30465903Ssowmini 	return (status);
30475903Ssowmini }
30486512Ssowmini 
30496512Ssowmini 
30506512Ssowmini static dladm_status_t
30518453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
30528453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
30536512Ssowmini {
30546512Ssowmini 	dladm_status_t status;
30556512Ssowmini 	char **prop_vals = NULL, *buf;
30566512Ssowmini 	size_t bufsize;
30576512Ssowmini 	uint_t cnt;
30586512Ssowmini 	int i;
30598118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
30606512Ssowmini 
30616512Ssowmini 	/*
30626512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
30636512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
30646512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
30656512Ssowmini 	 */
30666512Ssowmini 	bufsize =
30676512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
30686512Ssowmini 	buf = malloc(bufsize);
30696512Ssowmini 	prop_vals = (char **)(void *)buf;
30706512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
30716512Ssowmini 		prop_vals[i] = buf +
30726512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
30736512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
30746512Ssowmini 	}
30756768Sar224390 
30766768Sar224390 	/*
30777342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
30787342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
30797342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
30807342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
30817342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
30827342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
30837342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
30847342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
30856768Sar224390 	 */
30868453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
30878118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
30886512Ssowmini 	if (status == DLADM_STATUS_OK) {
30898118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
30908453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
30918453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
30928118SVasumathi.Sundaram@Sun.COM 		}
30938118SVasumathi.Sundaram@Sun.COM 		else
30948118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
30956512Ssowmini 	}
30966512Ssowmini 	free(buf);
30976512Ssowmini 	return (status);
30986512Ssowmini }
30997663SSowmini.Varadhan@Sun.COM 
3100*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3101*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3102*10491SRishi.Srivatsavai@Sun.COM get_stp_prop(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
3103*10491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
3104*10491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
3105*10491SRishi.Srivatsavai@Sun.COM {
3106*10491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
3107*10491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
3108*10491SRishi.Srivatsavai@Sun.COM 	int val, i;
3109*10491SRishi.Srivatsavai@Sun.COM 
3110*10491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
3111*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
3112*10491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
3113*10491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
3114*10491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
3115*10491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
3116*10491SRishi.Srivatsavai@Sun.COM 			break;
3117*10491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
3118*10491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
3119*10491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
3120*10491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
3121*10491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
3122*10491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
3123*10491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
3124*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
3125*10491SRishi.Srivatsavai@Sun.COM 	}
3126*10491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
3127*10491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
3128*10491SRishi.Srivatsavai@Sun.COM 		return (retv);
3129*10491SRishi.Srivatsavai@Sun.COM 	}
3130*10491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
3131*10491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
3132*10491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
3133*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
3134*10491SRishi.Srivatsavai@Sun.COM 	}
3135*10491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
3136*10491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
3137*10491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
3138*10491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
3139*10491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
3140*10491SRishi.Srivatsavai@Sun.COM 		}
3141*10491SRishi.Srivatsavai@Sun.COM 	}
3142*10491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
3143*10491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
3144*10491SRishi.Srivatsavai@Sun.COM }
3145*10491SRishi.Srivatsavai@Sun.COM 
3146*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
3147*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3148*10491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
3149*10491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3150*10491SRishi.Srivatsavai@Sun.COM {
3151*10491SRishi.Srivatsavai@Sun.COM 	/*
3152*10491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
3153*10491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
3154*10491SRishi.Srivatsavai@Sun.COM 	 */
3155*10491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
3156*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
3157*10491SRishi.Srivatsavai@Sun.COM 
3158*10491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
3159*10491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
3160*10491SRishi.Srivatsavai@Sun.COM }
3161*10491SRishi.Srivatsavai@Sun.COM 
3162*10491SRishi.Srivatsavai@Sun.COM /*
3163*10491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
3164*10491SRishi.Srivatsavai@Sun.COM  */
3165*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3166*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3167*10491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
3168*10491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
3169*10491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
3170*10491SRishi.Srivatsavai@Sun.COM {
3171*10491SRishi.Srivatsavai@Sun.COM 	char *cp;
3172*10491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
3173*10491SRishi.Srivatsavai@Sun.COM 
3174*10491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
3175*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
3176*10491SRishi.Srivatsavai@Sun.COM 
3177*10491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
3178*10491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
3179*10491SRishi.Srivatsavai@Sun.COM 	} else {
3180*10491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
3181*10491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
3182*10491SRishi.Srivatsavai@Sun.COM 
3183*10491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
3184*10491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
3185*10491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
3186*10491SRishi.Srivatsavai@Sun.COM 		} else {
3187*10491SRishi.Srivatsavai@Sun.COM 			errno = 0;
3188*10491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
3189*10491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
3190*10491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
3191*10491SRishi.Srivatsavai@Sun.COM 		}
3192*10491SRishi.Srivatsavai@Sun.COM 	}
3193*10491SRishi.Srivatsavai@Sun.COM 
3194*10491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
3195*10491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
3196*10491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
3197*10491SRishi.Srivatsavai@Sun.COM 	} else {
3198*10491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
3199*10491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
3200*10491SRishi.Srivatsavai@Sun.COM 		/*
3201*10491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
3202*10491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
3203*10491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
3204*10491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
3205*10491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
3206*10491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
3207*10491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
3208*10491SRishi.Srivatsavai@Sun.COM 		 */
3209*10491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
3210*10491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
3211*10491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
3212*10491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
3213*10491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
3214*10491SRishi.Srivatsavai@Sun.COM 
3215*10491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
3216*10491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
3217*10491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
3218*10491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
3219*10491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
3220*10491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
3221*10491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
3222*10491SRishi.Srivatsavai@Sun.COM 		}
3223*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
3224*10491SRishi.Srivatsavai@Sun.COM 	}
3225*10491SRishi.Srivatsavai@Sun.COM }
3226*10491SRishi.Srivatsavai@Sun.COM 
3227*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3228*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3229*10491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
3230*10491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3231*10491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
3232*10491SRishi.Srivatsavai@Sun.COM {
3233*10491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
3234*10491SRishi.Srivatsavai@Sun.COM 	uint_t val;
3235*10491SRishi.Srivatsavai@Sun.COM 
3236*10491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
3237*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
3238*10491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
3239*10491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
3240*10491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
3241*10491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
3242*10491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
3243*10491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
3244*10491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
3245*10491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
3246*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
3247*10491SRishi.Srivatsavai@Sun.COM 	}
3248*10491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
3249*10491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
3250*10491SRishi.Srivatsavai@Sun.COM 	else
3251*10491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
3252*10491SRishi.Srivatsavai@Sun.COM 	return (retv);
3253*10491SRishi.Srivatsavai@Sun.COM }
3254*10491SRishi.Srivatsavai@Sun.COM 
3255*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3256*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3257*10491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
3258*10491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3259*10491SRishi.Srivatsavai@Sun.COM {
3260*10491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
3261*10491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
3262*10491SRishi.Srivatsavai@Sun.COM }
3263*10491SRishi.Srivatsavai@Sun.COM 
3264*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3265*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3266*10491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
3267*10491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
3268*10491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
3269*10491SRishi.Srivatsavai@Sun.COM {
3270*10491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
3271*10491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
3272*10491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
3273*10491SRishi.Srivatsavai@Sun.COM 
3274*10491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
3275*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
3276*10491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
3277*10491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
3278*10491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
3279*10491SRishi.Srivatsavai@Sun.COM 	    0, &status);
3280*10491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
3281*10491SRishi.Srivatsavai@Sun.COM 		return (status);
3282*10491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
3283*10491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
3284*10491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
3285*10491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
3286*10491SRishi.Srivatsavai@Sun.COM 	} else {
3287*10491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
3288*10491SRishi.Srivatsavai@Sun.COM 	}
3289*10491SRishi.Srivatsavai@Sun.COM 	free(dip);
3290*10491SRishi.Srivatsavai@Sun.COM 	return (status);
3291*10491SRishi.Srivatsavai@Sun.COM }
3292*10491SRishi.Srivatsavai@Sun.COM 
3293*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3294*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3295*10491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
3296*10491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
3297*10491SRishi.Srivatsavai@Sun.COM {
3298*10491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
3299*10491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
3300*10491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
3301*10491SRishi.Srivatsavai@Sun.COM 
3302*10491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
3303*10491SRishi.Srivatsavai@Sun.COM 	    0, &status);
3304*10491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
3305*10491SRishi.Srivatsavai@Sun.COM 		return (status);
3306*10491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
3307*10491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
3308*10491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
3309*10491SRishi.Srivatsavai@Sun.COM 	free(dip);
3310*10491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
3311*10491SRishi.Srivatsavai@Sun.COM 		return (status);
3312*10491SRishi.Srivatsavai@Sun.COM 
3313*10491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
3314*10491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
3315*10491SRishi.Srivatsavai@Sun.COM }
3316*10491SRishi.Srivatsavai@Sun.COM 
3317*10491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
3318*10491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3319*10491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
3320*10491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
3321*10491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
3322*10491SRishi.Srivatsavai@Sun.COM {
3323*10491SRishi.Srivatsavai@Sun.COM 	char *cp;
3324*10491SRishi.Srivatsavai@Sun.COM 
3325*10491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
3326*10491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
3327*10491SRishi.Srivatsavai@Sun.COM 
3328*10491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
3329*10491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
3330*10491SRishi.Srivatsavai@Sun.COM 	} else {
3331*10491SRishi.Srivatsavai@Sun.COM 		errno = 0;
3332*10491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
3333*10491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
3334*10491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
3335*10491SRishi.Srivatsavai@Sun.COM 	}
3336*10491SRishi.Srivatsavai@Sun.COM 
3337*10491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
3338*10491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
3339*10491SRishi.Srivatsavai@Sun.COM }
3340*10491SRishi.Srivatsavai@Sun.COM 
33417663SSowmini.Varadhan@Sun.COM dladm_status_t
33428453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
33438453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
33447663SSowmini.Varadhan@Sun.COM {
33457663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
33467663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
33477663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
33487663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
33497663SSowmini.Varadhan@Sun.COM 	void			*dp;
33507663SSowmini.Varadhan@Sun.COM 
33518453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
33528453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
33537663SSowmini.Varadhan@Sun.COM 		return (status);
33547663SSowmini.Varadhan@Sun.COM 	}
33557663SSowmini.Varadhan@Sun.COM 
33567663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
33577663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
33587663SSowmini.Varadhan@Sun.COM 
33597663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
33607663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
33617663SSowmini.Varadhan@Sun.COM 
33627663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
33637663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
33647663SSowmini.Varadhan@Sun.COM 
33657663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
33667663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
33677663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
33687663SSowmini.Varadhan@Sun.COM 
33697663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
33707663SSowmini.Varadhan@Sun.COM 	if (set)
33717663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
33727663SSowmini.Varadhan@Sun.COM 
33738453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
337410191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
33757663SSowmini.Varadhan@Sun.COM 		if (!set)
33767663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
33777663SSowmini.Varadhan@Sun.COM 	}
33787663SSowmini.Varadhan@Sun.COM 
33797663SSowmini.Varadhan@Sun.COM 	free(dip);
33807663SSowmini.Varadhan@Sun.COM 	return (status);
33817663SSowmini.Varadhan@Sun.COM }
33827663SSowmini.Varadhan@Sun.COM 
33838275SEric Cheng dladm_status_t
33848275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
33858275SEric Cheng {
33868460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
33878275SEric Cheng }
33888275SEric Cheng 
33898275SEric Cheng /*
33908275SEric Cheng  * Retrieve the one link property from the database
33918275SEric Cheng  */
33928275SEric Cheng /*ARGSUSED*/
33938275SEric Cheng static int
33948453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
33958453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
33968275SEric Cheng {
33978275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
33988275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
33998275SEric Cheng 
34008275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
34018275SEric Cheng 	/*
34028275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
34038275SEric Cheng 	 * prop_table[n].pd_name.
34048275SEric Cheng 	 */
34058275SEric Cheng 	aip->ai_name = prop_name;
34068275SEric Cheng 
34078453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
34088453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
34098275SEric Cheng 
34108275SEric Cheng 	if (aip->ai_count != 0)
34118275SEric Cheng 		proplist->al_count++;
34128275SEric Cheng 
34138275SEric Cheng 	return (DLADM_WALK_CONTINUE);
34148275SEric Cheng }
34158275SEric Cheng 
34168275SEric Cheng 
34178275SEric Cheng /*
34188275SEric Cheng  * Retrieve all link properties for a link from the database and
34198275SEric Cheng  * return a property list.
34208275SEric Cheng  */
34218275SEric Cheng dladm_status_t
34228453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
34238453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
34248275SEric Cheng {
34258275SEric Cheng 	dladm_arg_list_t	*list;
34268275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
34278275SEric Cheng 
34288275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
34298275SEric Cheng 	if (list == NULL)
34308275SEric Cheng 		return (dladm_errno2status(errno));
34318275SEric Cheng 
34328453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
34338453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
34348275SEric Cheng 
34358275SEric Cheng 	*listp = list;
34368275SEric Cheng 	return (status);
34378275SEric Cheng }
34388275SEric Cheng 
34398275SEric Cheng /*
34408275SEric Cheng  * Retrieve the named property from a proplist, check the value and
34418275SEric Cheng  * convert to a kernel structure.
34428275SEric Cheng  */
34438275SEric Cheng static dladm_status_t
34448453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
34458453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist, const char *name, void *val)
34468275SEric Cheng {
34478275SEric Cheng 	dladm_status_t		status;
34488275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
34498275SEric Cheng 	int			i, j;
34508275SEric Cheng 
34518275SEric Cheng 	/* Find named property in proplist */
34528275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
34538275SEric Cheng 		aip = &proplist->al_info[i];
34548275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
34558275SEric Cheng 			break;
34568275SEric Cheng 	}
34578275SEric Cheng 
34588275SEric Cheng 	/* Property not in list */
34598275SEric Cheng 	if (i == proplist->al_count)
34608275SEric Cheng 		return (DLADM_STATUS_OK);
34618275SEric Cheng 
34628275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
34638275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
34648275SEric Cheng 		val_desc_t	*vdp;
34658275SEric Cheng 
34668275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
34678275SEric Cheng 		if (vdp == NULL)
34688275SEric Cheng 			return (DLADM_STATUS_NOMEM);
34698275SEric Cheng 
34708275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
34718275SEric Cheng 			continue;
34728275SEric Cheng 
34738275SEric Cheng 		if (aip->ai_val == NULL)
34748275SEric Cheng 			return (DLADM_STATUS_BADARG);
34758275SEric Cheng 
34768275SEric Cheng 		/* Check property value */
34778275SEric Cheng 		if (pdp->pd_check != NULL) {
34788453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
34798275SEric Cheng 			    aip->ai_count, vdp, 0);
34808275SEric Cheng 		} else {
34818275SEric Cheng 			status = DLADM_STATUS_BADARG;
34828275SEric Cheng 		}
34838275SEric Cheng 
34848275SEric Cheng 		if (status != DLADM_STATUS_OK)
34858275SEric Cheng 			return (status);
34868275SEric Cheng 
34878275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
34888275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
34898275SEric Cheng 
34908275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
34918275SEric Cheng 				continue;
34928275SEric Cheng 
34938275SEric Cheng 			/* Extract kernel structure */
34948275SEric Cheng 			if (rpp->rp_extract != NULL) {
34958275SEric Cheng 				status = rpp->rp_extract(vdp, val,
34968275SEric Cheng 				    aip->ai_count);
34978275SEric Cheng 			} else {
34988275SEric Cheng 				status = DLADM_STATUS_BADARG;
34998275SEric Cheng 			}
35008275SEric Cheng 			break;
35018275SEric Cheng 		}
35028275SEric Cheng 
35038275SEric Cheng 		if (status != DLADM_STATUS_OK)
35048275SEric Cheng 			return (status);
35058275SEric Cheng 
35068275SEric Cheng 		break;
35078275SEric Cheng 	}
35088275SEric Cheng 	return (status);
35098275SEric Cheng }
35108275SEric Cheng 
35118275SEric Cheng /*
35128275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
35138275SEric Cheng  */
35148275SEric Cheng dladm_status_t
35158453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
35168275SEric Cheng     mac_resource_props_t *mrp)
35178275SEric Cheng {
35188275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
35198275SEric Cheng 
35208453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "maxbw",
35218453SAnurag.Maskey@Sun.COM 	    mrp);
35228275SEric Cheng 	if (status != DLADM_STATUS_OK)
35238275SEric Cheng 		return (status);
35248453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "priority",
35258453SAnurag.Maskey@Sun.COM 	    mrp);
35268275SEric Cheng 	if (status != DLADM_STATUS_OK)
35278275SEric Cheng 		return (status);
35288453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "cpus",
35298453SAnurag.Maskey@Sun.COM 	    mrp);
35308275SEric Cheng 	if (status != DLADM_STATUS_OK)
35318275SEric Cheng 		return (status);
35328275SEric Cheng 	return (status);
35338275SEric Cheng }
35348275SEric Cheng 
35358275SEric Cheng static const char *
35368275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
35378275SEric Cheng {
35388275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
35398275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
35408275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
35418275SEric Cheng 	return (buf);
35428275SEric Cheng }
35438306SSowmini.Varadhan@Sun.COM 
35448306SSowmini.Varadhan@Sun.COM dladm_status_t
35458453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
35468453SAnurag.Maskey@Sun.COM     link_state_t *state)
35478306SSowmini.Varadhan@Sun.COM {
35488306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
35498306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
35508306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
35518306SSowmini.Varadhan@Sun.COM 
35528453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
35538453SAnurag.Maskey@Sun.COM 	    &perms);
35548306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
35558306SSowmini.Varadhan@Sun.COM 		return (status);
35568306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
35578306SSowmini.Varadhan@Sun.COM 	free(dip);
35588306SSowmini.Varadhan@Sun.COM 	return (status);
35598306SSowmini.Varadhan@Sun.COM }
35608460SArtem.Kachitchkin@Sun.COM 
35618460SArtem.Kachitchkin@Sun.COM boolean_t
35628460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
35638460SArtem.Kachitchkin@Sun.COM {
35648460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
35658460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
35668460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
35678460SArtem.Kachitchkin@Sun.COM 		"name",
35688460SArtem.Kachitchkin@Sun.COM 		"class",
35698460SArtem.Kachitchkin@Sun.COM 		"media",
35708460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
35718460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
35728460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
35738460SArtem.Kachitchkin@Sun.COM 
35748460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
35758460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
35768460SArtem.Kachitchkin@Sun.COM 	};
35778460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
35788460SArtem.Kachitchkin@Sun.COM 	int		i;
35798460SArtem.Kachitchkin@Sun.COM 
35808460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
35818460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
35828460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
35838460SArtem.Kachitchkin@Sun.COM 			break;
35848460SArtem.Kachitchkin@Sun.COM 		}
35858460SArtem.Kachitchkin@Sun.COM 	}
35868460SArtem.Kachitchkin@Sun.COM 
35878460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
35888460SArtem.Kachitchkin@Sun.COM }
3589