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>
545903Ssowmini #include <inttypes.h>
555903Ssowmini #include <sys/ethernet.h>
5610616SSebastien.Roy@Sun.COM #include <inet/iptun.h>
577663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
587663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
5910491SRishi.Srivatsavai@Sun.COM #include <sys/vlan.h>
6010491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
6110491SRishi.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,
13910491SRishi.Srivatsavai@Sun.COM 			i_dladm_tagmode_get, i_dladm_range_get,
14010491SRishi.Srivatsavai@Sun.COM 			get_stp_prop, get_bridge_forward,
141*10734SEric Cheng 			get_bridge_pvid,
142*10734SEric Cheng 			/* the above need to be renamed to "do_get_xxx" */
143*10734SEric Cheng 			do_get_protection;
1448275SEric Cheng 
1457342SAruna.Ramakrishna@Sun.COM static pd_setf_t	do_set_zone, do_set_rate_prop,
1465903Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
14710491SRishi.Srivatsavai@Sun.COM 			i_dladm_set_public_prop, do_set_res, do_set_cpus,
148*10734SEric Cheng 			set_stp_prop, set_bridge_forward, set_bridge_pvid,
149*10734SEric Cheng 			do_set_protection;
1508275SEric Cheng 
1515903Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
15210616SSebastien.Roy@Sun.COM 			do_check_hoplimit, do_check_encaplim,
15310491SRishi.Srivatsavai@Sun.COM 			i_dladm_uint32_check, do_check_maxbw, do_check_cpus,
154*10734SEric Cheng 			do_check_priority, check_stp_prop, check_bridge_pvid,
155*10734SEric Cheng 			do_check_allowedips, do_check_prop;
1568275SEric Cheng 
1578453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_speed_get(dladm_handle_t, prop_desc_t *,
1588453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **, uint_t *, uint_t, uint_t *);
1598453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1608275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1618275SEric Cheng 
1628275SEric Cheng struct prop_desc {
1635895Syz147064 	/*
1645895Syz147064 	 * link property name
1655895Syz147064 	 */
1665895Syz147064 	char			*pd_name;
1675895Syz147064 
1685895Syz147064 	/*
1695895Syz147064 	 * default property value, can be set to { "", NULL }
1705895Syz147064 	 */
1715895Syz147064 	val_desc_t		pd_defval;
1725895Syz147064 
1735895Syz147064 	/*
1745895Syz147064 	 * list of optional property values, can be NULL.
1755895Syz147064 	 *
1765895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1775895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1785895Syz147064 	 */
1795895Syz147064 	val_desc_t		*pd_optval;
1805895Syz147064 
1815895Syz147064 	/*
1825895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1835895Syz147064 	 */
1845895Syz147064 	uint_t			pd_noptval;
1855895Syz147064 
1865895Syz147064 	/*
18710491SRishi.Srivatsavai@Sun.COM 	 * callback to set link property; set to NULL if this property is
18810491SRishi.Srivatsavai@Sun.COM 	 * read-only and may be called before or after permanent update; see
18910491SRishi.Srivatsavai@Sun.COM 	 * flags.
1905895Syz147064 	 */
1915895Syz147064 	pd_setf_t		*pd_set;
1925895Syz147064 
1935895Syz147064 	/*
1945895Syz147064 	 * callback to get modifiable link property
1955895Syz147064 	 */
1965895Syz147064 	pd_getf_t		*pd_getmod;
1975895Syz147064 
1985895Syz147064 	/*
1995895Syz147064 	 * callback to get current link property
2005895Syz147064 	 */
2015895Syz147064 	pd_getf_t		*pd_get;
2025895Syz147064 
2035895Syz147064 	/*
2045895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
2055895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
2065895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
2075895Syz147064 	 * valid.
2085895Syz147064 	 */
2095895Syz147064 	pd_checkf_t		*pd_check;
2105895Syz147064 
2115895Syz147064 	uint_t			pd_flags;
2125903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2135903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
21410491SRishi.Srivatsavai@Sun.COM #define	PD_AFTER_PERM	0x4	/* pd_set after db update; no temporary */
2155895Syz147064 	/*
2165895Syz147064 	 * indicate link classes this property applies to.
2175895Syz147064 	 */
2185895Syz147064 	datalink_class_t	pd_class;
2195895Syz147064 
2205895Syz147064 	/*
2215895Syz147064 	 * indicate link media type this property applies to.
2225895Syz147064 	 */
2235895Syz147064 	datalink_media_t	pd_dmedia;
2248275SEric Cheng };
2253448Sdh155122 
2266789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2275903Ssowmini 
2287663SSowmini.Varadhan@Sun.COM /*
2297663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2307663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2317663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2327663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2337663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2347663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2357663SSowmini.Varadhan@Sun.COM  */
2367663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2377663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2385903Ssowmini 
2397663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2407663SSowmini.Varadhan@Sun.COM 
2417663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2427663SSowmini.Varadhan@Sun.COM 
2437663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2445903Ssowmini 
2457663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2465903Ssowmini 
2477663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2487663SSowmini.Varadhan@Sun.COM 
2497663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2505903Ssowmini 
2517663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2527663SSowmini.Varadhan@Sun.COM 
2539449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),	"adv_10gfdx_cap"},
2549449Sxiuyan.wang@Sun.COM 
2559449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),	"en_10gfdx_cap"},
2569449Sxiuyan.wang@Sun.COM 
2577663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2587663SSowmini.Varadhan@Sun.COM 
2597663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2605903Ssowmini 
2617663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2625903Ssowmini 
2637663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2647663SSowmini.Varadhan@Sun.COM 
2657663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2667342SAruna.Ramakrishna@Sun.COM 
2677663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2687663SSowmini.Varadhan@Sun.COM 
2697663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2707663SSowmini.Varadhan@Sun.COM 
2717663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2727342SAruna.Ramakrishna@Sun.COM 
2737663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2747663SSowmini.Varadhan@Sun.COM 
2757663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2765903Ssowmini 
2777663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2787663SSowmini.Varadhan@Sun.COM 
2797663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2805903Ssowmini 
2817663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2827663SSowmini.Varadhan@Sun.COM 
2837663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2845903Ssowmini 
2857663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2867663SSowmini.Varadhan@Sun.COM 
2877663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2887663SSowmini.Varadhan@Sun.COM 
2897663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2907663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2915903Ssowmini 
2927663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2937663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2947663SSowmini.Varadhan@Sun.COM 
2957663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2965903Ssowmini 
2977663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
2987663SSowmini.Varadhan@Sun.COM 
2997663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
3005903Ssowmini 
3017663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
3027663SSowmini.Varadhan@Sun.COM 
3037663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
3045903Ssowmini 
3057663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
3067663SSowmini.Varadhan@Sun.COM 
3077663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
3087663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
3095903Ssowmini 
3107663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
3117663SSowmini.Varadhan@Sun.COM 
3127663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
3135903Ssowmini 
3147663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3157663SSowmini.Varadhan@Sun.COM 
3167663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3175903Ssowmini 
3187663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3197663SSowmini.Varadhan@Sun.COM 
3207663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3217663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3225903Ssowmini 
3237663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3247663SSowmini.Varadhan@Sun.COM 
3257663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3265903Ssowmini 
3277663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3287663SSowmini.Varadhan@Sun.COM 
3298275SEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
3308275SEric Cheng 
3318275SEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
3328275SEric Cheng 
3338275SEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
3348275SEric Cheng 
3358874SSebastien.Roy@Sun.COM 	{ MAC_PROP_TAGMODE,	sizeof (link_tagmode_t),	"tagmode"},
3368874SSebastien.Roy@Sun.COM 
33710616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t),	"hoplimit"},
33810616SSebastien.Roy@Sun.COM 
33910616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t),	"encaplimit"},
34010616SSebastien.Roy@Sun.COM 
34110491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_PVID,	sizeof (uint16_t),	"default_tag"},
34210491SRishi.Srivatsavai@Sun.COM 
34310491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LLIMIT,	sizeof (uint32_t),	"learn_limit"},
34410491SRishi.Srivatsavai@Sun.COM 
34510491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LDECAY,	sizeof (uint32_t),	"learn_decay"},
34610491SRishi.Srivatsavai@Sun.COM 
347*10734SEric Cheng 	{ MAC_PROP_PROTECT,	sizeof (mac_resource_props_t),	"protection"},
348*10734SEric Cheng 
3497663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3505903Ssowmini };
3515903Ssowmini 
35210491SRishi.Srivatsavai@Sun.COM typedef struct bridge_public_prop_s {
35310491SRishi.Srivatsavai@Sun.COM 	const char	*bpp_name;
35410491SRishi.Srivatsavai@Sun.COM 	int		bpp_code;
35510491SRishi.Srivatsavai@Sun.COM } bridge_public_prop_t;
35610491SRishi.Srivatsavai@Sun.COM 
35710491SRishi.Srivatsavai@Sun.COM static const bridge_public_prop_t bridge_prop[] = {
35810491SRishi.Srivatsavai@Sun.COM 	{ "stp", PT_CFG_NON_STP },
35910491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", PT_CFG_PRIO },
36010491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", PT_CFG_COST },
36110491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", PT_CFG_EDGE },
36210491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", PT_CFG_P2P },
36310491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", PT_CFG_MCHECK },
36410491SRishi.Srivatsavai@Sun.COM 	{ NULL, 0 }
36510491SRishi.Srivatsavai@Sun.COM };
36610491SRishi.Srivatsavai@Sun.COM 
3675903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3685903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3695903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3705903Ssowmini };
3715903Ssowmini static  val_desc_t	link_status_vals[] = {
3725903Ssowmini 	{ "up",		LINK_STATE_UP		},
3735903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3745903Ssowmini };
3755903Ssowmini static  val_desc_t	link_01_vals[] = {
3765903Ssowmini 	{ "1",		1			},
3775903Ssowmini 	{ "0",		0			}
3785903Ssowmini };
3795903Ssowmini static  val_desc_t	link_flow_vals[] = {
3805903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3815903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3825903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3835903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3845903Ssowmini };
3858275SEric Cheng static  val_desc_t	link_priority_vals[] = {
3868275SEric Cheng 	{ "low",	MPL_LOW	},
3878275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
3888275SEric Cheng 	{ "high",	MPL_HIGH	}
3898275SEric Cheng };
3905903Ssowmini 
3918874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
3928874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
3938874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
3948874SSebastien.Roy@Sun.COM };
3958874SSebastien.Roy@Sun.COM 
396*10734SEric Cheng static  val_desc_t	link_protect_vals[] = {
397*10734SEric Cheng 	{ "mac-nospoof",	MPT_MACNOSPOOF	},
398*10734SEric Cheng 	{ "ip-nospoof",		MPT_IPNOSPOOF	},
399*10734SEric Cheng 	{ "restricted",		MPT_RESTRICTED	}
400*10734SEric Cheng };
401*10734SEric Cheng 
4025895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
4035895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
4045895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
4055895Syz147064 };
4065895Syz147064 
4075895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
4085895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
4095895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
4105895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
4115895Syz147064 };
4125895Syz147064 
41310491SRishi.Srivatsavai@Sun.COM static  val_desc_t	stp_p2p_vals[] = {
41410491SRishi.Srivatsavai@Sun.COM 	{ "true",	P2P_FORCE_TRUE		},
41510491SRishi.Srivatsavai@Sun.COM 	{ "false",	P2P_FORCE_FALSE		},
41610491SRishi.Srivatsavai@Sun.COM 	{ "auto",	P2P_AUTO		}
41710491SRishi.Srivatsavai@Sun.COM };
41810491SRishi.Srivatsavai@Sun.COM 
4198275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
4208275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
4218275SEric Cheng 
4223448Sdh155122 static prop_desc_t	prop_table[] = {
4235903Ssowmini 	{ "channel",	{ NULL, 0 },
4245903Ssowmini 	    NULL, 0, NULL, NULL,
4255895Syz147064 	    do_get_channel_prop, NULL, 0,
4265903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4275895Syz147064 
4285895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
4295895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
4305895Syz147064 	    do_set_powermode_prop, NULL,
4315895Syz147064 	    do_get_powermode_prop, NULL, 0,
4325903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4335895Syz147064 
4345895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
4355895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
4365895Syz147064 	    do_set_radio_prop, NULL,
4375895Syz147064 	    do_get_radio_prop, NULL, 0,
4385903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4395895Syz147064 
4405895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
4415895Syz147064 	    do_set_rate_prop, do_get_rate_mod,
4425895Syz147064 	    do_get_rate_prop, do_check_rate, 0,
4435960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
4445895Syz147064 
4456512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
4467342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL,
4477342SAruna.Ramakrishna@Sun.COM 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
4485903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4495895Syz147064 
4506512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
4513448Sdh155122 	    do_set_zone, NULL,
4527342SAruna.Ramakrishna@Sun.COM 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4535903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4545903Ssowmini 
4558275SEric Cheng 	{ "duplex",	{ "", 0 },
4565903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
4577342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_duplex_get, NULL,
4585903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4595903Ssowmini 
4608275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4615903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4627342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_status_get, NULL,
4636512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4645903Ssowmini 
46510191SSowmini.Varadhan@Sun.COM 	{ "adv_autoneg_cap", { "", 0 },
4665903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4677342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4685903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4695903Ssowmini 
4706512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4719514SGirish.Moodalbail@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get,
47210491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_get, i_dladm_uint32_check, 0, DATALINK_CLASS_ALL,
4737342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4745903Ssowmini 
4756512Ssowmini 	{ "flowctrl", { "", 0 },
4765903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4777342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
4785903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4795903Ssowmini 
4809449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
4819449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4829449Sxiuyan.wang@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4839449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4849449Sxiuyan.wang@Sun.COM 
4859449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
4869449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4879449Sxiuyan.wang@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4889449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4899449Sxiuyan.wang@Sun.COM 
4906512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4916512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4927342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4935903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4945903Ssowmini 
4956512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
4965903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4977342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4985903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4995903Ssowmini 
5006512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
5015903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5027342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5035903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5045903Ssowmini 
5056512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
5065903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5077342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5085903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5095903Ssowmini 
5106512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
5115903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5127342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5135903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5145903Ssowmini 
5156512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
5165903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5177342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5185903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5195903Ssowmini 
5206512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
5215903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5227342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5235903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5245903Ssowmini 
5256512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
5265903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5277342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5285903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5295903Ssowmini 
5306512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
5315903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5327342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5335903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5345903Ssowmini 
5356512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
5365903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5377342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5385903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5395903Ssowmini 
5406512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
5415903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5427342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
5435903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5445903Ssowmini 
5456512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
5465903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
5477342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
5488275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5498275SEric Cheng 
5508275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
5518275SEric Cheng 	    do_set_res, NULL,
5528460SArtem.Kachitchkin@Sun.COM 	    i_dladm_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
5538275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5548275SEric Cheng 
5558275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
5568275SEric Cheng 	    do_set_cpus, NULL,
5578460SArtem.Kachitchkin@Sun.COM 	    i_dladm_cpus_get, do_check_cpus, 0,
5588275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5598275SEric Cheng 
5608275SEric Cheng 	{ "priority", { "high", RESET_VAL },
5618275SEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
5628460SArtem.Kachitchkin@Sun.COM 	    i_dladm_priority_get, do_check_priority, PD_CHECK_ALLOC,
5638275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5648874SSebastien.Roy@Sun.COM 
5658874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
5668874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
5678874SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_tagmode_get,
5688874SSebastien.Roy@Sun.COM 	    NULL, 0,
5698874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
57010491SRishi.Srivatsavai@Sun.COM 	    DL_ETHER },
57110491SRishi.Srivatsavai@Sun.COM 
57210616SSebastien.Roy@Sun.COM 	{ "hoplimit", { "", 0 }, NULL, 0,
57310616SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get,
57410616SSebastien.Roy@Sun.COM 	    do_check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
57510616SSebastien.Roy@Sun.COM 
57610616SSebastien.Roy@Sun.COM 	{ "encaplimit", { "", 0 }, NULL, 0,
57710616SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get,
57810616SSebastien.Roy@Sun.COM 	    do_check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
57910616SSebastien.Roy@Sun.COM 
58010491SRishi.Srivatsavai@Sun.COM 	{ "forward", { "1", 1 },
58110491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
58210491SRishi.Srivatsavai@Sun.COM 	    set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
58310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
58410491SRishi.Srivatsavai@Sun.COM 
58510491SRishi.Srivatsavai@Sun.COM 	{ "default_tag", { "1", 1 }, NULL, 0,
58610491SRishi.Srivatsavai@Sun.COM 	    set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
58710491SRishi.Srivatsavai@Sun.COM 	    0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
58810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
58910491SRishi.Srivatsavai@Sun.COM 
59010491SRishi.Srivatsavai@Sun.COM 	{ "learn_limit", { "1000", 1000 }, NULL, 0,
59110491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
59210491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
59310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
59410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
59510491SRishi.Srivatsavai@Sun.COM 
59610491SRishi.Srivatsavai@Sun.COM 	{ "learn_decay", { "200", 200 }, NULL, 0,
59710491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
59810491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
59910491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
60010491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
60110491SRishi.Srivatsavai@Sun.COM 
60210491SRishi.Srivatsavai@Sun.COM 	{ "stp", { "1", 1 },
60310491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
60410491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
60510491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
60610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
60710491SRishi.Srivatsavai@Sun.COM 
60810491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", { "128", 128 }, NULL, 0,
60910491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
61010491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
61110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
61210491SRishi.Srivatsavai@Sun.COM 
61310491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", { "auto", 0 }, NULL, 0,
61410491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
61510491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
61610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
61710491SRishi.Srivatsavai@Sun.COM 
61810491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", { "1", 1 },
61910491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
62010491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
62110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
62210491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
62310491SRishi.Srivatsavai@Sun.COM 
62410491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", { "auto", P2P_AUTO },
62510491SRishi.Srivatsavai@Sun.COM 	    stp_p2p_vals, VALCNT(stp_p2p_vals),
62610491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
62710491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
62810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
62910491SRishi.Srivatsavai@Sun.COM 
63010491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", { "0", 0 },
63110491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
63210491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
63310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
63410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
635*10734SEric Cheng 
636*10734SEric Cheng 	{ "protection", { "--", RESET_VAL },
637*10734SEric Cheng 	    link_protect_vals, VALCNT(link_protect_vals),
638*10734SEric Cheng 	    do_set_protection, NULL, do_get_protection, do_check_prop, 0,
639*10734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
640*10734SEric Cheng 
641*10734SEric Cheng 	{ "allowed-ips", { "--", 0 },
642*10734SEric Cheng 	    NULL, 0, do_set_protection, NULL,
643*10734SEric Cheng 	    do_get_protection, do_check_allowedips, 0,
644*10734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
6453448Sdh155122 };
6463448Sdh155122 
6475895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
6485895Syz147064 
6498275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
6508275SEric Cheng 	{"maxbw",	do_extract_maxbw},
6518275SEric Cheng 	{"priority",	do_extract_priority},
652*10734SEric Cheng 	{"cpus",	do_extract_cpus},
653*10734SEric Cheng 	{"protection",	do_extract_protection},
654*10734SEric Cheng 	{"allowed-ips",	do_extract_allowedips}
6558275SEric Cheng };
6568275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
6578275SEric Cheng 	sizeof (resource_prop_t))
6588275SEric Cheng 
6597663SSowmini.Varadhan@Sun.COM /*
6607663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
6617663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
6627663SSowmini.Varadhan@Sun.COM  */
6637663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
6647663SSowmini.Varadhan@Sun.COM 
6658453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
6668453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
6678453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
6688453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
6698460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
6708460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
6718460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
6728453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
6738453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
6748453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
6758453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
6768453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
6778453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
6788453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
6798275SEric Cheng 
6805895Syz147064 /*
6815895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
6825895Syz147064  * rates to be retrieved. However, we cannot increase it at this
6835895Syz147064  * time because it will break binary compatibility with unbundled
6845895Syz147064  * WiFi drivers and utilities. So for now we define an additional
6855895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
6865895Syz147064  */
6875895Syz147064 #define	MAX_SUPPORT_RATES	64
6885895Syz147064 
6895895Syz147064 #define	AP_ANCHOR	"[anchor]"
6905895Syz147064 #define	AP_DELIMITER	'.'
6915895Syz147064 
692*10734SEric Cheng /* ARGSUSED */
6935895Syz147064 static dladm_status_t
694*10734SEric Cheng do_check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
695*10734SEric Cheng     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
6965895Syz147064 {
6975895Syz147064 	int		i, j;
6983147Sxc151355 
6995895Syz147064 	for (j = 0; j < val_cnt; j++) {
7005895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
701*10734SEric Cheng 			if (strcasecmp(prop_val[j],
7025895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
7035895Syz147064 				break;
7045895Syz147064 			}
7055895Syz147064 		}
706*10734SEric Cheng 		if (i == pdp->pd_noptval)
707*10734SEric Cheng 			return (DLADM_STATUS_BADVAL);
708*10734SEric Cheng 
709*10734SEric Cheng 		(void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
7105895Syz147064 	}
711*10734SEric Cheng 	return (DLADM_STATUS_OK);
7125895Syz147064 }
7135895Syz147064 
7145895Syz147064 static dladm_status_t
7158453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
7168453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
7178453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
7183147Sxc151355 {
7195895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
7205895Syz147064 	val_desc_t	*vdp = NULL;
7215895Syz147064 	boolean_t	needfree = B_FALSE;
7225895Syz147064 	uint_t		cnt, i;
7233147Sxc151355 
7245895Syz147064 	if (!(pdp->pd_class & class))
7255895Syz147064 		return (DLADM_STATUS_BADARG);
7265895Syz147064 
7275895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
7283147Sxc151355 		return (DLADM_STATUS_BADARG);
7293147Sxc151355 
7305895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
7315895Syz147064 		return (DLADM_STATUS_TEMPONLY);
7325895Syz147064 
7335895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
7345895Syz147064 		return (DLADM_STATUS_OK);
7355895Syz147064 
7365895Syz147064 	if (pdp->pd_set == NULL)
7375895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
7383448Sdh155122 
7395895Syz147064 	if (prop_val != NULL) {
7405895Syz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
7415895Syz147064 		if (vdp == NULL)
7425895Syz147064 			return (DLADM_STATUS_NOMEM);
7435895Syz147064 
7445895Syz147064 		if (pdp->pd_check != NULL) {
7458275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
7468453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
7478453SAnurag.Maskey@Sun.COM 			    val_cnt, vdp, media);
7485895Syz147064 		} else if (pdp->pd_optval != NULL) {
749*10734SEric Cheng 			status = do_check_prop(handle, pdp, linkid, prop_val,
750*10734SEric Cheng 			    val_cnt, vdp, media);
7515895Syz147064 		} else {
7523448Sdh155122 			status = DLADM_STATUS_BADARG;
7533147Sxc151355 		}
7545895Syz147064 
7553147Sxc151355 		if (status != DLADM_STATUS_OK)
7565895Syz147064 			goto done;
7575895Syz147064 
7585895Syz147064 		cnt = val_cnt;
7595895Syz147064 	} else {
7608275SEric Cheng 		boolean_t	defval = B_FALSE;
7618275SEric Cheng 
7625895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
7635895Syz147064 			return (DLADM_STATUS_NOTSUP);
7645895Syz147064 
7657342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
7668275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
7678275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
7686512Ssowmini 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
7696512Ssowmini 				return (DLADM_STATUS_NOMEM);
7707342SAruna.Ramakrishna@Sun.COM 
7718275SEric Cheng 			if (defval) {
7728275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
7738275SEric Cheng 				    sizeof (val_desc_t));
7748275SEric Cheng 			} else if (pdp->pd_check != NULL) {
7758453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
7768453SAnurag.Maskey@Sun.COM 				    prop_val, cnt, vdp, media);
7777342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
7787342SAruna.Ramakrishna@Sun.COM 					goto done;
7797342SAruna.Ramakrishna@Sun.COM 			}
7806512Ssowmini 		} else {
7818453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
7826512Ssowmini 			    media, flags);
7836512Ssowmini 			return (status);
7846512Ssowmini 		}
7855895Syz147064 	}
78610491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_AFTER_PERM)
78710491SRishi.Srivatsavai@Sun.COM 		status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
78810491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_PERMONLY;
78910491SRishi.Srivatsavai@Sun.COM 	else
79010491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
79110491SRishi.Srivatsavai@Sun.COM 		    media);
7925895Syz147064 	if (needfree) {
7935895Syz147064 		for (i = 0; i < cnt; i++)
7945903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
7953147Sxc151355 	}
7965895Syz147064 done:
7975895Syz147064 	free(vdp);
7985895Syz147064 	return (status);
7995895Syz147064 }
8005895Syz147064 
8015895Syz147064 static dladm_status_t
8028453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8038453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8045895Syz147064 {
8055895Syz147064 	int			i;
8065895Syz147064 	boolean_t		found = B_FALSE;
8075895Syz147064 	datalink_class_t	class;
8085895Syz147064 	uint32_t		media;
8095895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
8105895Syz147064 
8118453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
8128453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8135895Syz147064 	if (status != DLADM_STATUS_OK)
8145895Syz147064 		return (status);
8155895Syz147064 
8165895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
8175895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
8185895Syz147064 		dladm_status_t	s;
8195895Syz147064 
8205895Syz147064 		if (prop_name != NULL &&
8215895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
8225895Syz147064 			continue;
8235895Syz147064 		found = B_TRUE;
8248453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
8258453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
8263448Sdh155122 
8275895Syz147064 		if (prop_name != NULL) {
8285895Syz147064 			status = s;
8295895Syz147064 			break;
8305895Syz147064 		} else {
8315895Syz147064 			if (s != DLADM_STATUS_OK &&
8325895Syz147064 			    s != DLADM_STATUS_NOTSUP)
8335895Syz147064 				status = s;
8345895Syz147064 		}
8355895Syz147064 	}
8365903Ssowmini 	if (!found) {
8375903Ssowmini 		if (prop_name[0] == '_') {
8385903Ssowmini 			/* other private properties */
8399692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
8409692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
8415903Ssowmini 		} else  {
8425903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
8435903Ssowmini 		}
8445903Ssowmini 	}
8455895Syz147064 
8465895Syz147064 	return (status);
8475895Syz147064 }
8485895Syz147064 
8495895Syz147064 /*
8505895Syz147064  * Set/reset link property for specific link
8515895Syz147064  */
8525895Syz147064 dladm_status_t
8538453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8548453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8555895Syz147064 {
8565895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
8575895Syz147064 
8585895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
8595895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
8605895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
8615895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
8625895Syz147064 		return (DLADM_STATUS_BADARG);
8635895Syz147064 	}
8645895Syz147064 
8659692SRishi.Srivatsavai@Sun.COM 	/*
8669692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
8679692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
8689692SRishi.Srivatsavai@Sun.COM 	 */
8698453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
8705895Syz147064 	    val_cnt, flags);
8715895Syz147064 	if (status != DLADM_STATUS_OK)
8725895Syz147064 		return (status);
8735895Syz147064 
8745895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
8758453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
8763147Sxc151355 		    prop_val, val_cnt);
87710491SRishi.Srivatsavai@Sun.COM 
87810491SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
87910491SRishi.Srivatsavai@Sun.COM 			prop_desc_t *pdp = prop_table;
88010491SRishi.Srivatsavai@Sun.COM 			int i;
88110491SRishi.Srivatsavai@Sun.COM 
88210491SRishi.Srivatsavai@Sun.COM 			for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
88310491SRishi.Srivatsavai@Sun.COM 				if (!(pdp->pd_flags & PD_AFTER_PERM))
88410491SRishi.Srivatsavai@Sun.COM 					continue;
88510491SRishi.Srivatsavai@Sun.COM 				if (prop_name != NULL &&
88610491SRishi.Srivatsavai@Sun.COM 				    strcasecmp(prop_name, pdp->pd_name) != 0)
88710491SRishi.Srivatsavai@Sun.COM 					continue;
88810491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_set(handle, pdp, linkid, NULL,
88910491SRishi.Srivatsavai@Sun.COM 				    0, flags, 0);
89010491SRishi.Srivatsavai@Sun.COM 			}
89110491SRishi.Srivatsavai@Sun.COM 		}
8923147Sxc151355 	}
8933147Sxc151355 	return (status);
8943147Sxc151355 }
8953147Sxc151355 
8965895Syz147064 /*
8978460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
8988460SArtem.Kachitchkin@Sun.COM  *
8998460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
9008460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
9018460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
9028460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
9035895Syz147064  */
9043147Sxc151355 dladm_status_t
9058453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
9068453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
9073147Sxc151355 {
9085895Syz147064 	dladm_status_t		status;
9095895Syz147064 	datalink_class_t	class;
9105895Syz147064 	uint_t			media;
9115895Syz147064 	int			i;
9125895Syz147064 
9135895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
9145895Syz147064 		return (DLADM_STATUS_BADARG);
9155895Syz147064 
9168453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9178453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9185895Syz147064 	if (status != DLADM_STATUS_OK)
9195895Syz147064 		return (status);
9205895Syz147064 
9218460SArtem.Kachitchkin@Sun.COM 	/* public */
9225895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
9235895Syz147064 		if (!(prop_table[i].pd_class & class))
9245895Syz147064 			continue;
9255895Syz147064 
9265895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
9275895Syz147064 			continue;
9285895Syz147064 
9298453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
9305895Syz147064 		    DLADM_WALK_TERMINATE) {
9315895Syz147064 			break;
9325895Syz147064 		}
9335895Syz147064 	}
9345895Syz147064 
9358460SArtem.Kachitchkin@Sun.COM 	/* private */
9368460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
9378460SArtem.Kachitchkin@Sun.COM 
9388460SArtem.Kachitchkin@Sun.COM 	return (status);
9395895Syz147064 }
9403448Sdh155122 
9415895Syz147064 /*
9425895Syz147064  * Get linkprop of the given specific link.
9435895Syz147064  */
9445895Syz147064 dladm_status_t
9458453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9468453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
9478453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
9485895Syz147064 {
9495895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
9505895Syz147064 	datalink_class_t	class;
9515895Syz147064 	uint_t			media;
9525895Syz147064 	prop_desc_t		*pdp;
9536512Ssowmini 	uint_t			cnt, dld_flags = 0;
9545895Syz147064 	int			i;
9558118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
9565895Syz147064 
9576512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
9589514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_DEFAULT;
9599514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
9609514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_POSSIBLE;
9616512Ssowmini 
9625895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
9635895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
9645895Syz147064 		return (DLADM_STATUS_BADARG);
9655895Syz147064 
9665895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
9675895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
9685895Syz147064 			break;
9695895Syz147064 
9705903Ssowmini 	if (i == DLADM_MAX_PROPS) {
9715903Ssowmini 		if (prop_name[0] == '_') {
9725903Ssowmini 			/*
9735903Ssowmini 			 * private property.
9745903Ssowmini 			 */
9758460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
9768460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
9778460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
9788460SArtem.Kachitchkin@Sun.COM 			else
9798460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
9808460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
9818460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
9825903Ssowmini 		} else {
9835903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
9845903Ssowmini 		}
9855903Ssowmini 	}
9865895Syz147064 
9875895Syz147064 	pdp = &prop_table[i];
9885895Syz147064 
9898453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9908453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9915895Syz147064 	if (status != DLADM_STATUS_OK)
9925895Syz147064 		return (status);
9935895Syz147064 
9945895Syz147064 	if (!(pdp->pd_class & class))
9955895Syz147064 		return (DLADM_STATUS_BADARG);
9965895Syz147064 
9975895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
9983147Sxc151355 		return (DLADM_STATUS_BADARG);
9993147Sxc151355 
10005895Syz147064 	switch (type) {
10015895Syz147064 	case DLADM_PROP_VAL_CURRENT:
10028453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
10038453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
10048118SVasumathi.Sundaram@Sun.COM 		break;
10058118SVasumathi.Sundaram@Sun.COM 
10068118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
10078118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
10088118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
10098118SVasumathi.Sundaram@Sun.COM 		} else {
10108453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
10118453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10128118SVasumathi.Sundaram@Sun.COM 		}
10138118SVasumathi.Sundaram@Sun.COM 
10148118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
10159055SMichael.Lim@Sun.COM 		*val_cntp = 1;
10168275SEric Cheng 		if (status == DLADM_STATUS_OK)
10178275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
10185895Syz147064 		break;
10195895Syz147064 
10205895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
10216768Sar224390 		/*
10226768Sar224390 		 * If defaults are not defined for the property,
10236768Sar224390 		 * pd_defval.vd_name should be null. If the driver
10246768Sar224390 		 * has to be contacted for the value, vd_name should
10256768Sar224390 		 * be the empty string (""). Otherwise, dladm will
10266768Sar224390 		 * just print whatever is in the table.
10276768Sar224390 		 */
10285895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
10295895Syz147064 			status = DLADM_STATUS_NOTSUP;
10305895Syz147064 			break;
10315895Syz147064 		}
10326512Ssowmini 
10336512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
10348453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
10358453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10366512Ssowmini 		} else {
10376512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
10386512Ssowmini 		}
10395895Syz147064 		*val_cntp = 1;
10405895Syz147064 		break;
10413448Sdh155122 
10425895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
10435895Syz147064 		if (pdp->pd_getmod != NULL) {
10448453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
10458118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10465895Syz147064 			break;
10475895Syz147064 		}
10485895Syz147064 		cnt = pdp->pd_noptval;
10495895Syz147064 		if (cnt == 0) {
10505895Syz147064 			status = DLADM_STATUS_NOTSUP;
10515895Syz147064 		} else if (cnt > *val_cntp) {
10525895Syz147064 			status = DLADM_STATUS_TOOSMALL;
10535895Syz147064 		} else {
10545895Syz147064 			for (i = 0; i < cnt; i++) {
10555895Syz147064 				(void) strcpy(prop_val[i],
10565895Syz147064 				    pdp->pd_optval[i].vd_name);
10575895Syz147064 			}
10585895Syz147064 			*val_cntp = cnt;
10595895Syz147064 		}
10605895Syz147064 		break;
10615895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
10625895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
10635895Syz147064 			return (DLADM_STATUS_TEMPONLY);
10648453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
10655895Syz147064 		    prop_val, val_cntp);
10665895Syz147064 		break;
10675895Syz147064 	default:
10685895Syz147064 		status = DLADM_STATUS_BADARG;
10695895Syz147064 		break;
10703147Sxc151355 	}
10713448Sdh155122 
10725895Syz147064 	return (status);
10735895Syz147064 }
10745895Syz147064 
107510491SRishi.Srivatsavai@Sun.COM /*
107610491SRishi.Srivatsavai@Sun.COM  * Get linkprop of the given specific link and run any possible conversion
107710491SRishi.Srivatsavai@Sun.COM  * of the values using the check function for the property. Fails if the
107810491SRishi.Srivatsavai@Sun.COM  * check function doesn't succeed for the property value.
107910491SRishi.Srivatsavai@Sun.COM  */
108010491SRishi.Srivatsavai@Sun.COM dladm_status_t
108110491SRishi.Srivatsavai@Sun.COM dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
108210491SRishi.Srivatsavai@Sun.COM     dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
108310491SRishi.Srivatsavai@Sun.COM     uint_t *val_cntp)
108410491SRishi.Srivatsavai@Sun.COM {
108510491SRishi.Srivatsavai@Sun.COM 	dladm_status_t		status;
108610491SRishi.Srivatsavai@Sun.COM 	datalink_class_t	class;
108710491SRishi.Srivatsavai@Sun.COM 	uint_t			media;
108810491SRishi.Srivatsavai@Sun.COM 	prop_desc_t		*pdp;
108910491SRishi.Srivatsavai@Sun.COM 	uint_t			dld_flags;
109010491SRishi.Srivatsavai@Sun.COM 	int			valc, i;
109110491SRishi.Srivatsavai@Sun.COM 	char			**prop_val;
109210491SRishi.Srivatsavai@Sun.COM 	uint_t			perm_flags;
109310491SRishi.Srivatsavai@Sun.COM 
109410491SRishi.Srivatsavai@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
109510491SRishi.Srivatsavai@Sun.COM 	    ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
109610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
109710491SRishi.Srivatsavai@Sun.COM 
109810491SRishi.Srivatsavai@Sun.COM 	for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
109910491SRishi.Srivatsavai@Sun.COM 		if (strcasecmp(prop_name, pdp->pd_name) == 0)
110010491SRishi.Srivatsavai@Sun.COM 			break;
110110491SRishi.Srivatsavai@Sun.COM 
110210491SRishi.Srivatsavai@Sun.COM 	if (pdp == prop_table + DLADM_MAX_PROPS)
110310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
110410491SRishi.Srivatsavai@Sun.COM 
110510491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_CHECK_ALLOC)
110610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
110710491SRishi.Srivatsavai@Sun.COM 
110810491SRishi.Srivatsavai@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
110910491SRishi.Srivatsavai@Sun.COM 	    NULL, 0);
111010491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
111110491SRishi.Srivatsavai@Sun.COM 		return (status);
111210491SRishi.Srivatsavai@Sun.COM 
111310491SRishi.Srivatsavai@Sun.COM 	if (!(pdp->pd_class & class))
111410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
111510491SRishi.Srivatsavai@Sun.COM 
111610491SRishi.Srivatsavai@Sun.COM 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
111710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
111810491SRishi.Srivatsavai@Sun.COM 
111910491SRishi.Srivatsavai@Sun.COM 	prop_val = malloc(*val_cntp * sizeof (*prop_val) +
112010491SRishi.Srivatsavai@Sun.COM 	    *val_cntp * DLADM_PROP_VAL_MAX);
112110491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL)
112210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOMEM);
112310491SRishi.Srivatsavai@Sun.COM 	for (valc = 0; valc < *val_cntp; valc++)
112410491SRishi.Srivatsavai@Sun.COM 		prop_val[valc] = (char *)(prop_val + *val_cntp) +
112510491SRishi.Srivatsavai@Sun.COM 		    valc * DLADM_PROP_VAL_MAX;
112610491SRishi.Srivatsavai@Sun.COM 
112710491SRishi.Srivatsavai@Sun.COM 	dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? MAC_PROP_DEFAULT : 0;
112810491SRishi.Srivatsavai@Sun.COM 
112910491SRishi.Srivatsavai@Sun.COM 	switch (type) {
113010491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_CURRENT:
113110491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
113210491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
113310491SRishi.Srivatsavai@Sun.COM 		break;
113410491SRishi.Srivatsavai@Sun.COM 
113510491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_DEFAULT:
113610491SRishi.Srivatsavai@Sun.COM 		/*
113710491SRishi.Srivatsavai@Sun.COM 		 * If defaults are not defined for the property,
113810491SRishi.Srivatsavai@Sun.COM 		 * pd_defval.vd_name should be null. If the driver
113910491SRishi.Srivatsavai@Sun.COM 		 * has to be contacted for the value, vd_name should
114010491SRishi.Srivatsavai@Sun.COM 		 * be the empty string (""). Otherwise, dladm will
114110491SRishi.Srivatsavai@Sun.COM 		 * just print whatever is in the table.
114210491SRishi.Srivatsavai@Sun.COM 		 */
114310491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name == NULL) {
114410491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_NOTSUP;
114510491SRishi.Srivatsavai@Sun.COM 			break;
114610491SRishi.Srivatsavai@Sun.COM 		}
114710491SRishi.Srivatsavai@Sun.COM 
114810491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name[0] != '\0') {
114910491SRishi.Srivatsavai@Sun.COM 			*val_cntp = 1;
115010491SRishi.Srivatsavai@Sun.COM 			*ret_val = pdp->pd_defval.vd_val;
115110491SRishi.Srivatsavai@Sun.COM 			free(prop_val);
115210491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
115310491SRishi.Srivatsavai@Sun.COM 		}
115410491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
115510491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
115610491SRishi.Srivatsavai@Sun.COM 		break;
115710491SRishi.Srivatsavai@Sun.COM 
115810491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_PERSISTENT:
115910491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_flags & PD_TEMPONLY)
116010491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_TEMPONLY;
116110491SRishi.Srivatsavai@Sun.COM 		else
116210491SRishi.Srivatsavai@Sun.COM 			status = i_dladm_get_linkprop_db(handle, linkid,
116310491SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cntp);
116410491SRishi.Srivatsavai@Sun.COM 		break;
116510491SRishi.Srivatsavai@Sun.COM 
116610491SRishi.Srivatsavai@Sun.COM 	default:
116710491SRishi.Srivatsavai@Sun.COM 		status = DLADM_STATUS_BADARG;
116810491SRishi.Srivatsavai@Sun.COM 		break;
116910491SRishi.Srivatsavai@Sun.COM 	}
117010491SRishi.Srivatsavai@Sun.COM 
117110491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
117210491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_check != NULL) {
117310491SRishi.Srivatsavai@Sun.COM 			val_desc_t *vdp;
117410491SRishi.Srivatsavai@Sun.COM 
117510491SRishi.Srivatsavai@Sun.COM 			vdp = malloc(sizeof (val_desc_t) * *val_cntp);
117610491SRishi.Srivatsavai@Sun.COM 			if (vdp == NULL)
117710491SRishi.Srivatsavai@Sun.COM 				status = DLADM_STATUS_NOMEM;
117810491SRishi.Srivatsavai@Sun.COM 			else
117910491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
118010491SRishi.Srivatsavai@Sun.COM 				    prop_val, *val_cntp, vdp, media);
118110491SRishi.Srivatsavai@Sun.COM 			if (status == DLADM_STATUS_OK) {
118210491SRishi.Srivatsavai@Sun.COM 				for (valc = 0; valc < *val_cntp; valc++)
118310491SRishi.Srivatsavai@Sun.COM 					ret_val[valc] = vdp[valc].vd_val;
118410491SRishi.Srivatsavai@Sun.COM 			}
118510491SRishi.Srivatsavai@Sun.COM 			free(vdp);
118610491SRishi.Srivatsavai@Sun.COM 		} else {
118710491SRishi.Srivatsavai@Sun.COM 			for (valc = 0; valc < *val_cntp; valc++) {
118810491SRishi.Srivatsavai@Sun.COM 				for (i = 0; i < pdp->pd_noptval; i++) {
118910491SRishi.Srivatsavai@Sun.COM 					if (strcmp(pdp->pd_optval[i].vd_name,
119010491SRishi.Srivatsavai@Sun.COM 					    prop_val[valc]) == 0) {
119110491SRishi.Srivatsavai@Sun.COM 						ret_val[valc] =
119210491SRishi.Srivatsavai@Sun.COM 						    pdp->pd_optval[i].vd_val;
119310491SRishi.Srivatsavai@Sun.COM 						break;
119410491SRishi.Srivatsavai@Sun.COM 					}
119510491SRishi.Srivatsavai@Sun.COM 				}
119610491SRishi.Srivatsavai@Sun.COM 				if (i == pdp->pd_noptval) {
119710491SRishi.Srivatsavai@Sun.COM 					status = DLADM_STATUS_FAILED;
119810491SRishi.Srivatsavai@Sun.COM 					break;
119910491SRishi.Srivatsavai@Sun.COM 				}
120010491SRishi.Srivatsavai@Sun.COM 			}
120110491SRishi.Srivatsavai@Sun.COM 		}
120210491SRishi.Srivatsavai@Sun.COM 	}
120310491SRishi.Srivatsavai@Sun.COM 
120410491SRishi.Srivatsavai@Sun.COM 	free(prop_val);
120510491SRishi.Srivatsavai@Sun.COM 
120610491SRishi.Srivatsavai@Sun.COM 	return (status);
120710491SRishi.Srivatsavai@Sun.COM }
120810491SRishi.Srivatsavai@Sun.COM 
12095895Syz147064 /*ARGSUSED*/
12105895Syz147064 static int
12118453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
12128453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
12135895Syz147064 {
12145895Syz147064 	char	*buf, **propvals;
12155895Syz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
12165895Syz147064 
12175895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
12185895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
12195895Syz147064 		return (DLADM_WALK_CONTINUE);
12205895Syz147064 	}
12215895Syz147064 
12225895Syz147064 	propvals = (char **)(void *)buf;
12235895Syz147064 	for (i = 0; i < valcnt; i++) {
12245895Syz147064 		propvals[i] = buf +
12255895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
12265895Syz147064 		    i * DLADM_PROP_VAL_MAX;
12275895Syz147064 	}
12285895Syz147064 
12298453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
12308453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
12315895Syz147064 		goto done;
12325895Syz147064 	}
12335895Syz147064 
12348453SAnurag.Maskey@Sun.COM 	(void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
12355895Syz147064 	    DLADM_OPT_ACTIVE);
12365895Syz147064 
12375895Syz147064 done:
12385895Syz147064 	if (buf != NULL)
12395895Syz147064 		free(buf);
12405895Syz147064 
12415895Syz147064 	return (DLADM_WALK_CONTINUE);
12425895Syz147064 }
12435895Syz147064 
12445895Syz147064 /*ARGSUSED*/
12455895Syz147064 static int
12468453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
12475895Syz147064 {
12488275SEric Cheng 	datalink_class_t	class;
12498275SEric Cheng 	dladm_status_t		status;
12508275SEric Cheng 
12518453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
12528453SAnurag.Maskey@Sun.COM 	    NULL, 0);
12538275SEric Cheng 	if (status != DLADM_STATUS_OK)
12548275SEric Cheng 		return (DLADM_WALK_TERMINATE);
12558275SEric Cheng 
12568275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
12578453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
12588275SEric Cheng 
12595895Syz147064 	return (DLADM_WALK_CONTINUE);
12605895Syz147064 }
12615895Syz147064 
12625895Syz147064 dladm_status_t
12638453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
12648453SAnurag.Maskey@Sun.COM     boolean_t any_media)
12655895Syz147064 {
12666916Sartem 	datalink_media_t	dmedia;
12676916Sartem 	uint32_t		media;
12686916Sartem 
12696916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
12706916Sartem 
12715895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
12728453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
12738453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
12748453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
12758453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
12768453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
12776916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
12788453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, NULL,
12798453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
12803448Sdh155122 	}
12813448Sdh155122 	return (DLADM_STATUS_OK);
12823147Sxc151355 }
12833147Sxc151355 
12845903Ssowmini /* ARGSUSED */
12855895Syz147064 static dladm_status_t
12868453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12878275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12888275SEric Cheng     uint_t flags, uint_t *perm_flags)
12893147Sxc151355 {
12908275SEric Cheng 	char			zone_name[ZONENAME_MAX];
12918275SEric Cheng 	zoneid_t		zid;
12928275SEric Cheng 	dladm_status_t		status;
12938275SEric Cheng 	char			*cp;
12947342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
12953147Sxc151355 
12966512Ssowmini 	if (flags != 0)
12976512Ssowmini 		return (DLADM_STATUS_NOTSUP);
12986512Ssowmini 
12998453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13008275SEric Cheng 	    &status, perm_flags);
13015895Syz147064 	if (status != DLADM_STATUS_OK)
13023448Sdh155122 		return (status);
13033448Sdh155122 
13047342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
13057342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
13067342SAruna.Ramakrishna@Sun.COM 	free(dip);
13077342SAruna.Ramakrishna@Sun.COM 
13085895Syz147064 	*val_cnt = 1;
13095895Syz147064 	if (zid != GLOBAL_ZONEID) {
13108118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
13115895Syz147064 			return (dladm_errno2status(errno));
13128118SVasumathi.Sundaram@Sun.COM 		}
13133147Sxc151355 
13145895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
13153147Sxc151355 	} else {
13165895Syz147064 		*prop_val[0] = '\0';
13173147Sxc151355 	}
13183147Sxc151355 
13193448Sdh155122 	return (DLADM_STATUS_OK);
13203448Sdh155122 }
13213448Sdh155122 
13223448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
13233448Sdh155122 
13243448Sdh155122 static int
13253448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
13263448Sdh155122 {
13273448Sdh155122 	char			root[MAXPATHLEN];
13283448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
13293448Sdh155122 	void			*dlhandle;
13303448Sdh155122 	void			*sym;
13313448Sdh155122 	int			ret;
13323448Sdh155122 
13333448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
13343448Sdh155122 		return (-1);
13353448Sdh155122 
13363448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
13373448Sdh155122 		(void) dlclose(dlhandle);
13383448Sdh155122 		return (-1);
13393448Sdh155122 	}
13403448Sdh155122 
13413448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
13423448Sdh155122 
13433448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
13443448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
13453448Sdh155122 	(void) dlclose(dlhandle);
13463448Sdh155122 	return (ret);
13473448Sdh155122 }
13483448Sdh155122 
13493448Sdh155122 static dladm_status_t
13508453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
13518453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
13523448Sdh155122 {
13533448Sdh155122 	char		path[MAXPATHLEN];
13545895Syz147064 	char		name[MAXLINKNAMELEN];
13553448Sdh155122 	di_prof_t	prof = NULL;
13563448Sdh155122 	char		zone_name[ZONENAME_MAX];
13573448Sdh155122 	dladm_status_t	status;
13585895Syz147064 	int		ret;
13593448Sdh155122 
13603448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
13613448Sdh155122 		return (dladm_errno2status(errno));
13623448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
13633448Sdh155122 		return (dladm_errno2status(errno));
13643448Sdh155122 	if (di_prof_init(path, &prof) != 0)
13653448Sdh155122 		return (dladm_errno2status(errno));
13663448Sdh155122 
13678453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
13685895Syz147064 	if (status != DLADM_STATUS_OK)
13695895Syz147064 		goto cleanup;
13705895Syz147064 
13715895Syz147064 	if (add)
13725895Syz147064 		ret = di_prof_add_dev(prof, name);
13735895Syz147064 	else
13745895Syz147064 		ret = di_prof_add_exclude(prof, name);
13755895Syz147064 
13765895Syz147064 	if (ret != 0) {
13773448Sdh155122 		status = dladm_errno2status(errno);
13783448Sdh155122 		goto cleanup;
13793448Sdh155122 	}
13803448Sdh155122 
13813448Sdh155122 	if (di_prof_commit(prof) != 0)
13823448Sdh155122 		status = dladm_errno2status(errno);
13833448Sdh155122 cleanup:
13843448Sdh155122 	if (prof)
13853448Sdh155122 		di_prof_fini(prof);
13863448Sdh155122 
13873448Sdh155122 	return (status);
13883448Sdh155122 }
13893448Sdh155122 
13905903Ssowmini /* ARGSUSED */
13913448Sdh155122 static dladm_status_t
13928453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13938453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13943448Sdh155122 {
13958275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
13968275SEric Cheng 	zoneid_t		zid_old, zid_new;
13978275SEric Cheng 	char			*cp;
13987342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
13997342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
14003448Sdh155122 
14013448Sdh155122 	if (val_cnt != 1)
14023448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14033448Sdh155122 
14047342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
14057342SAruna.Ramakrishna@Sun.COM 
14068453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
14078275SEric Cheng 	    &status, NULL);
14088275SEric Cheng 	if (status != DLADM_STATUS_OK)
14098275SEric Cheng 		return (status);
14108275SEric Cheng 
14118275SEric Cheng 	cp = dip->pr_val;
14128275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
14138275SEric Cheng 	free(dip);
14147342SAruna.Ramakrishna@Sun.COM 
14157342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
14163448Sdh155122 	if (zid_new == zid_old)
141710616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_OK);
141810616SSebastien.Roy@Sun.COM 
141910616SSebastien.Roy@Sun.COM 	if ((status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, val_cnt,
142010616SSebastien.Roy@Sun.COM 	    flags, media)) != DLADM_STATUS_OK)
14215895Syz147064 		return (status);
14225895Syz147064 
142310616SSebastien.Roy@Sun.COM 	/*
142410616SSebastien.Roy@Sun.COM 	 * It is okay to fail to update the /dev entry (some vanity-named
142510616SSebastien.Roy@Sun.COM 	 * links do not have a /dev entry).
142610616SSebastien.Roy@Sun.COM 	 */
14273448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
14288453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
14298453SAnurag.Maskey@Sun.COM 		    B_FALSE);
14305895Syz147064 	}
143110616SSebastien.Roy@Sun.COM 	if (zid_new != GLOBAL_ZONEID)
14328453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
14333448Sdh155122 
14343448Sdh155122 	return (DLADM_STATUS_OK);
14353448Sdh155122 }
14363448Sdh155122 
14373448Sdh155122 /* ARGSUSED */
14383448Sdh155122 static dladm_status_t
14398453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14408453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14413448Sdh155122 {
14427342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
14437342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
14447342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
14457342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
14463448Sdh155122 
14473448Sdh155122 	if (val_cnt != 1)
14483448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14493448Sdh155122 
14507342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
14517342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
14527342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
14533448Sdh155122 
14548275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
14557342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
14567342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
14577342SAruna.Ramakrishna@Sun.COM 		goto done;
14587342SAruna.Ramakrishna@Sun.COM 	}
14597342SAruna.Ramakrishna@Sun.COM 
14607342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
14613448Sdh155122 		ushort_t	flags;
14623448Sdh155122 
14637342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
14643448Sdh155122 		    sizeof (flags)) < 0) {
14657342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
14667342SAruna.Ramakrishna@Sun.COM 			goto done;
14673448Sdh155122 		}
14683448Sdh155122 
14693448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
14707342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
14717342SAruna.Ramakrishna@Sun.COM 			goto done;
14723448Sdh155122 		}
14733448Sdh155122 	}
14743448Sdh155122 
14757342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
14767342SAruna.Ramakrishna@Sun.COM 
14777342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
147810616SSebastien.Roy@Sun.COM 	dzp->diz_linkid = linkid;
14797342SAruna.Ramakrishna@Sun.COM 
14807342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
14815895Syz147064 	return (DLADM_STATUS_OK);
14827342SAruna.Ramakrishna@Sun.COM done:
14837342SAruna.Ramakrishna@Sun.COM 	free(dzp);
14847342SAruna.Ramakrishna@Sun.COM 	return (status);
14855895Syz147064 }
14865895Syz147064 
14875903Ssowmini /* ARGSUSED */
14885895Syz147064 static dladm_status_t
14898460SArtem.Kachitchkin@Sun.COM i_dladm_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14908275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
14918275SEric Cheng     uint_t flags, uint_t *perm_flags)
14928275SEric Cheng {
14938275SEric Cheng 	dld_ioc_macprop_t	*dip;
14948275SEric Cheng 	mac_resource_props_t	mrp;
14958275SEric Cheng 	dladm_status_t		status;
14968275SEric Cheng 
14978453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
14988275SEric Cheng 	    &status, perm_flags);
14998275SEric Cheng 	if (dip == NULL)
15008275SEric Cheng 		return (status);
15018275SEric Cheng 
15028275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
15038275SEric Cheng 	free(dip);
15048275SEric Cheng 
15058275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
15068275SEric Cheng 		(*prop_val)[0] = '\0';
15078275SEric Cheng 	} else {
15088275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
15098275SEric Cheng 	}
15108275SEric Cheng 	*val_cnt = 1;
15118275SEric Cheng 	return (DLADM_STATUS_OK);
15128275SEric Cheng }
15138275SEric Cheng 
15148275SEric Cheng /* ARGSUSED */
15158275SEric Cheng static dladm_status_t
15168453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15178453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
15188275SEric Cheng {
15198275SEric Cheng 	uint64_t	*maxbw;
15208275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15218275SEric Cheng 
15228275SEric Cheng 	if (val_cnt != 1)
15238275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15248275SEric Cheng 
15258275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
15268275SEric Cheng 	if (maxbw == NULL)
15278275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15288275SEric Cheng 
15298275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
15308275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15318275SEric Cheng 		free(maxbw);
15328275SEric Cheng 		return (status);
15338275SEric Cheng 	}
15348275SEric Cheng 
15358275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
15368275SEric Cheng 		free(maxbw);
15378275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
15388275SEric Cheng 	}
15398275SEric Cheng 
15408275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
15418275SEric Cheng 	return (DLADM_STATUS_OK);
15428275SEric Cheng }
15438275SEric Cheng 
15448275SEric Cheng /* ARGSUSED */
15458275SEric Cheng dladm_status_t
1546*10734SEric Cheng do_extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
15478275SEric Cheng {
1548*10734SEric Cheng 	mac_resource_props_t *mrp = arg;
15498275SEric Cheng 
15508275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
15518275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
15528275SEric Cheng 
15538275SEric Cheng 	return (DLADM_STATUS_OK);
15548275SEric Cheng }
15558275SEric Cheng 
15568275SEric Cheng /* ARGSUSED */
15578275SEric Cheng static dladm_status_t
15588460SArtem.Kachitchkin@Sun.COM i_dladm_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15598275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15608275SEric Cheng     uint_t flags, uint_t *perm_flags)
15618275SEric Cheng {
15628275SEric Cheng 	dld_ioc_macprop_t	*dip;
15638275SEric Cheng 	mac_resource_props_t	mrp;
15648275SEric Cheng 	int			i;
15658275SEric Cheng 	uint32_t		ncpus;
15668275SEric Cheng 	uchar_t			*cp;
15678275SEric Cheng 	dladm_status_t		status;
15688275SEric Cheng 
15698453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15708275SEric Cheng 	    &status, perm_flags);
15718275SEric Cheng 	if (dip == NULL)
15728275SEric Cheng 		return (status);
15738275SEric Cheng 
15748275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
15758275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
15768275SEric Cheng 	free(dip);
15778275SEric Cheng 
15788275SEric Cheng 	ncpus = mrp.mrp_ncpus;
15798275SEric Cheng 
15808275SEric Cheng 	if (ncpus > *val_cnt)
15818275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
15828275SEric Cheng 
15838275SEric Cheng 	if (ncpus == 0) {
15848275SEric Cheng 		(*prop_val)[0] = '\0';
15858275SEric Cheng 		*val_cnt = 1;
15868275SEric Cheng 		return (DLADM_STATUS_OK);
15878275SEric Cheng 	}
15888275SEric Cheng 
15898275SEric Cheng 	*val_cnt = ncpus;
15908275SEric Cheng 	for (i = 0; i < ncpus; i++) {
15918275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
15928275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
15938275SEric Cheng 	}
15948275SEric Cheng 	return (DLADM_STATUS_OK);
15958275SEric Cheng }
15968275SEric Cheng 
15978275SEric Cheng /* ARGSUSED */
15988275SEric Cheng static dladm_status_t
15998453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16008453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16018275SEric Cheng {
16028275SEric Cheng 	mac_resource_props_t	mrp;
16038275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
16048275SEric Cheng 	dld_ioc_macprop_t	*dip;
16058275SEric Cheng 
16068275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16078275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16088275SEric Cheng 	    flags, &status);
16098275SEric Cheng 
16108275SEric Cheng 	if (dip == NULL)
16118275SEric Cheng 		return (status);
16128275SEric Cheng 
16138275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
16148275SEric Cheng 		switch (dip->pr_num) {
16158275SEric Cheng 		case MAC_PROP_MAXBW:
16168275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
16178275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16188275SEric Cheng 			break;
16198275SEric Cheng 		case MAC_PROP_PRIO:
16208275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
16218275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16228275SEric Cheng 			break;
16238275SEric Cheng 		default:
16248275SEric Cheng 			free(dip);
16258275SEric Cheng 			return (DLADM_STATUS_BADARG);
16268275SEric Cheng 		}
16278275SEric Cheng 	} else {
16288275SEric Cheng 		switch (dip->pr_num) {
16298275SEric Cheng 		case MAC_PROP_MAXBW:
16308275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
16318275SEric Cheng 			    sizeof (uint64_t));
16328275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16338275SEric Cheng 			break;
16348275SEric Cheng 		case MAC_PROP_PRIO:
16358275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
16368275SEric Cheng 			    sizeof (mac_priority_level_t));
16378275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16388275SEric Cheng 			break;
16398275SEric Cheng 		default:
16408275SEric Cheng 			free(dip);
16418275SEric Cheng 			return (DLADM_STATUS_BADARG);
16428275SEric Cheng 		}
16438275SEric Cheng 	}
16448275SEric Cheng 
16458275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16468453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16478275SEric Cheng 	free(dip);
16488275SEric Cheng 	return (status);
16498275SEric Cheng }
16508275SEric Cheng 
16518275SEric Cheng /* ARGSUSED */
16528275SEric Cheng static dladm_status_t
16538453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16548453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16558275SEric Cheng {
16568275SEric Cheng 	mac_resource_props_t	mrp;
16578275SEric Cheng 	dladm_status_t		status;
16588275SEric Cheng 	dld_ioc_macprop_t	*dip;
16598275SEric Cheng 	datalink_class_t	class;
16608275SEric Cheng 
16618275SEric Cheng 	/*
16628275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
16638275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
16648275SEric Cheng 	 * the phys_info test only on physical links.
16658275SEric Cheng 	 */
16668453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
16678275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
16688275SEric Cheng 		return (status);
16698275SEric Cheng 	}
16708275SEric Cheng 
16718275SEric Cheng 	/*
16728275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
16738275SEric Cheng 	 * if possible when the setup is complete in MAC.
16748275SEric Cheng 	 */
16758275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16768275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
16778275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
16788275SEric Cheng 		mac_resource_props_t	*vmrp;
16798275SEric Cheng 
16808275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
16818275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
16828275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
16838275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
16848275SEric Cheng 		}
16858275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
16868275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
16878275SEric Cheng 		mrp.mrp_intr_cpu = -1;
16888275SEric Cheng 	}
16898275SEric Cheng 
16908275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16918275SEric Cheng 	    flags, &status);
16928275SEric Cheng 	if (dip == NULL)
16938275SEric Cheng 		return (status);
16948275SEric Cheng 
16958275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16968453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16978275SEric Cheng 	free(dip);
16988275SEric Cheng 	return (status);
16998275SEric Cheng }
17008275SEric Cheng 
17018275SEric Cheng /* ARGSUSED */
17028275SEric Cheng static dladm_status_t
17038453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17048453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17058275SEric Cheng {
17068275SEric Cheng 	uint32_t		cpuid;
17078275SEric Cheng 	int			i, j, rc;
17088275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
17098275SEric Cheng 	mac_resource_props_t	*mrp;
17108275SEric Cheng 
17118275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
17128275SEric Cheng 	if (mrp == NULL)
17138275SEric Cheng 		return (DLADM_STATUS_NOMEM);
17148275SEric Cheng 
17158275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17168275SEric Cheng 		errno = 0;
17178275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
17188275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
17198275SEric Cheng 			free(mrp);
17208275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
17218275SEric Cheng 		}
17228275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
17238275SEric Cheng 		if (rc < 1) {
17248275SEric Cheng 			free(mrp);
17258275SEric Cheng 			return (DLADM_STATUS_CPUERR);
17268275SEric Cheng 		}
17278275SEric Cheng 		if (rc != P_ONLINE) {
17288275SEric Cheng 			free(mrp);
17298275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
17308275SEric Cheng 		}
17318275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
17328275SEric Cheng 	}
17338275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
17348275SEric Cheng 
17358275SEric Cheng 	/* Check for duplicates */
17368275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17378275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
17388275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
17398275SEric Cheng 				free(mrp);
17408275SEric Cheng 				return (DLADM_STATUS_BADARG);
17418275SEric Cheng 			}
17428275SEric Cheng 		}
17438275SEric Cheng 	}
17448275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
17458275SEric Cheng 
17468275SEric Cheng 	return (DLADM_STATUS_OK);
17478275SEric Cheng }
17488275SEric Cheng 
17498275SEric Cheng /* ARGSUSED */
17508275SEric Cheng dladm_status_t
1751*10734SEric Cheng do_extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
17528275SEric Cheng {
1753*10734SEric Cheng 	mac_resource_props_t	*mrp = arg;
17548275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
17558275SEric Cheng 	int			i;
17568275SEric Cheng 
17578275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
17588275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
17598275SEric Cheng 	}
17608275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
17618275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
17628275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
17639055SMichael.Lim@Sun.COM 	mrp->mrp_intr_cpu = -1;
17648275SEric Cheng 
17658275SEric Cheng 	return (DLADM_STATUS_OK);
17668275SEric Cheng }
17678275SEric Cheng 
17688275SEric Cheng /* ARGSUSED */
17698275SEric Cheng static dladm_status_t
17708460SArtem.Kachitchkin@Sun.COM i_dladm_priority_get(dladm_handle_t handle, prop_desc_t *pdp,
17718460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
17728460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
17738275SEric Cheng {
17748275SEric Cheng 	dld_ioc_macprop_t	*dip;
17758275SEric Cheng 	mac_resource_props_t	mrp;
17768275SEric Cheng 	mac_priority_level_t	pri;
17778275SEric Cheng 	dladm_status_t		status;
17788275SEric Cheng 
17798453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
17808275SEric Cheng 	    &status, perm_flags);
17818275SEric Cheng 	if (dip == NULL)
17828275SEric Cheng 		return (status);
17838275SEric Cheng 
17848275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
17858275SEric Cheng 	free(dip);
17868275SEric Cheng 
17878275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
17888275SEric Cheng 	    mrp.mrp_priority;
17898275SEric Cheng 
17908275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
17918275SEric Cheng 	*val_cnt = 1;
17928275SEric Cheng 	return (DLADM_STATUS_OK);
17938275SEric Cheng }
17948275SEric Cheng 
17958275SEric Cheng /* ARGSUSED */
17968275SEric Cheng static dladm_status_t
17978453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17988453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17998275SEric Cheng {
18008275SEric Cheng 	mac_priority_level_t	*pri;
18018275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
18028275SEric Cheng 
18038275SEric Cheng 	if (val_cnt != 1)
18048275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
18058275SEric Cheng 
18068275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
18078275SEric Cheng 	if (pri == NULL)
18088275SEric Cheng 		return (DLADM_STATUS_NOMEM);
18098275SEric Cheng 
18108275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
18118275SEric Cheng 	if (status != DLADM_STATUS_OK) {
18128275SEric Cheng 		free(pri);
18138275SEric Cheng 		return (status);
18148275SEric Cheng 	}
18158275SEric Cheng 
18168275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
18178275SEric Cheng 		free(pri);
18188275SEric Cheng 		return (DLADM_STATUS_BADVAL);
18198275SEric Cheng 	}
18208275SEric Cheng 
18218275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
18228275SEric Cheng 	return (DLADM_STATUS_OK);
18238275SEric Cheng }
18248275SEric Cheng 
18258275SEric Cheng /* ARGSUSED */
18268275SEric Cheng dladm_status_t
1827*10734SEric Cheng do_extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
18288275SEric Cheng {
1829*10734SEric Cheng 	mac_resource_props_t *mrp = arg;
18308275SEric Cheng 
18318275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
18328275SEric Cheng 	    sizeof (mac_priority_level_t));
18338275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
18348275SEric Cheng 
18358275SEric Cheng 	return (DLADM_STATUS_OK);
18368275SEric Cheng }
18378275SEric Cheng 
18388275SEric Cheng /* ARGSUSED */
18398275SEric Cheng static dladm_status_t
1840*10734SEric Cheng do_set_protection(dladm_handle_t handle, prop_desc_t *pdp,
1841*10734SEric Cheng     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
1842*10734SEric Cheng     uint_t flags, datalink_media_t media)
1843*10734SEric Cheng {
1844*10734SEric Cheng 	mac_resource_props_t	mrp;
1845*10734SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
1846*10734SEric Cheng 	dld_ioc_macprop_t	*dip;
1847*10734SEric Cheng 
1848*10734SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
1849*10734SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, "protection",
1850*10734SEric Cheng 	    flags, &status);
1851*10734SEric Cheng 
1852*10734SEric Cheng 	if (dip == NULL)
1853*10734SEric Cheng 		return (status);
1854*10734SEric Cheng 
1855*10734SEric Cheng 	if (strcmp(pdp->pd_name, "protection") == 0) {
1856*10734SEric Cheng 		status = do_extract_protection(vdp, val_cnt, &mrp);
1857*10734SEric Cheng 		if (status != DLADM_STATUS_OK)
1858*10734SEric Cheng 			goto done;
1859*10734SEric Cheng 
1860*10734SEric Cheng 	} else if (strcmp(pdp->pd_name, "allowed-ips") == 0) {
1861*10734SEric Cheng 		status = do_extract_allowedips(vdp, val_cnt, &mrp);
1862*10734SEric Cheng 		if (status != DLADM_STATUS_OK)
1863*10734SEric Cheng 			goto done;
1864*10734SEric Cheng 	} else {
1865*10734SEric Cheng 		status = DLADM_STATUS_BADARG;
1866*10734SEric Cheng 		goto done;
1867*10734SEric Cheng 	}
1868*10734SEric Cheng 
1869*10734SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
1870*10734SEric Cheng 	status = i_dladm_macprop(handle, dip, B_TRUE);
1871*10734SEric Cheng 
1872*10734SEric Cheng done:
1873*10734SEric Cheng 	free(dip);
1874*10734SEric Cheng 	return (status);
1875*10734SEric Cheng }
1876*10734SEric Cheng 
1877*10734SEric Cheng /* ARGSUSED */
1878*10734SEric Cheng static dladm_status_t
1879*10734SEric Cheng do_get_protection(dladm_handle_t handle, prop_desc_t *pdp,
1880*10734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
1881*10734SEric Cheng     datalink_media_t media, uint_t flags, uint_t *perm_flags)
1882*10734SEric Cheng {
1883*10734SEric Cheng 	dld_ioc_macprop_t	*dip;
1884*10734SEric Cheng 	mac_resource_props_t	mrp;
1885*10734SEric Cheng 	mac_protect_t		*p;
1886*10734SEric Cheng 	dladm_status_t		status;
1887*10734SEric Cheng 	int			i;
1888*10734SEric Cheng 
1889*10734SEric Cheng 	dip = i_dladm_get_public_prop(handle, linkid, "protection", flags,
1890*10734SEric Cheng 	    &status, perm_flags);
1891*10734SEric Cheng 	if (dip == NULL)
1892*10734SEric Cheng 		return (status);
1893*10734SEric Cheng 
1894*10734SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
1895*10734SEric Cheng 	free(dip);
1896*10734SEric Cheng 
1897*10734SEric Cheng 	p = &mrp.mrp_protect;
1898*10734SEric Cheng 	if ((mrp.mrp_mask & MRP_PROTECT) != 0 &&
1899*10734SEric Cheng 	    strcmp(pdp->pd_name, "protection") == 0) {
1900*10734SEric Cheng 		uint32_t	cnt = 0, setbits[32];
1901*10734SEric Cheng 
1902*10734SEric Cheng 		dladm_find_setbits32(p->mp_types, setbits, &cnt);
1903*10734SEric Cheng 		if (cnt > *val_cnt)
1904*10734SEric Cheng 			return (DLADM_STATUS_BADVALCNT);
1905*10734SEric Cheng 
1906*10734SEric Cheng 		for (i = 0; i < cnt; i++)
1907*10734SEric Cheng 			(void) dladm_protect2str(setbits[i], prop_val[i]);
1908*10734SEric Cheng 
1909*10734SEric Cheng 		*val_cnt = cnt;
1910*10734SEric Cheng 		return (DLADM_STATUS_OK);
1911*10734SEric Cheng 	}
1912*10734SEric Cheng 
1913*10734SEric Cheng 	if (p->mp_ipaddrcnt > 0 &&
1914*10734SEric Cheng 	    strcmp(pdp->pd_name, "allowed-ips") == 0) {
1915*10734SEric Cheng 		if (p->mp_ipaddrcnt > *val_cnt)
1916*10734SEric Cheng 			return (DLADM_STATUS_BADVALCNT);
1917*10734SEric Cheng 
1918*10734SEric Cheng 		for (i = 0; i < p->mp_ipaddrcnt; i++) {
1919*10734SEric Cheng 			(void) dladm_ipv4addr2str(&p->mp_ipaddrs[i],
1920*10734SEric Cheng 			    prop_val[i]);
1921*10734SEric Cheng 		}
1922*10734SEric Cheng 		*val_cnt = p->mp_ipaddrcnt;
1923*10734SEric Cheng 		return (DLADM_STATUS_OK);
1924*10734SEric Cheng 	}
1925*10734SEric Cheng 
1926*10734SEric Cheng 	*val_cnt = 0;
1927*10734SEric Cheng 	return (DLADM_STATUS_OK);
1928*10734SEric Cheng }
1929*10734SEric Cheng 
1930*10734SEric Cheng dladm_status_t
1931*10734SEric Cheng do_extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
1932*10734SEric Cheng {
1933*10734SEric Cheng 	mac_resource_props_t	*mrp = arg;
1934*10734SEric Cheng 	uint32_t		types = 0;
1935*10734SEric Cheng 	int			i;
1936*10734SEric Cheng 
1937*10734SEric Cheng 	for (i = 0; i < cnt; i++)
1938*10734SEric Cheng 		types |= (uint32_t)vdp[i].vd_val;
1939*10734SEric Cheng 
1940*10734SEric Cheng 	mrp->mrp_protect.mp_types = types;
1941*10734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
1942*10734SEric Cheng 	return (DLADM_STATUS_OK);
1943*10734SEric Cheng }
1944*10734SEric Cheng 
1945*10734SEric Cheng dladm_status_t
1946*10734SEric Cheng do_extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
1947*10734SEric Cheng {
1948*10734SEric Cheng 	mac_resource_props_t	*mrp = arg;
1949*10734SEric Cheng 	mac_protect_t		*p = &mrp->mrp_protect;
1950*10734SEric Cheng 	int			i;
1951*10734SEric Cheng 
1952*10734SEric Cheng 	if (vdp->vd_val == 0) {
1953*10734SEric Cheng 		cnt = (uint_t)-1;
1954*10734SEric Cheng 	} else {
1955*10734SEric Cheng 		for (i = 0; i < cnt; i++)
1956*10734SEric Cheng 			p->mp_ipaddrs[i] = (ipaddr_t)vdp[i].vd_val;
1957*10734SEric Cheng 	}
1958*10734SEric Cheng 	p->mp_ipaddrcnt = cnt;
1959*10734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
1960*10734SEric Cheng 	return (DLADM_STATUS_OK);
1961*10734SEric Cheng }
1962*10734SEric Cheng 
1963*10734SEric Cheng /* ARGSUSED */
1964*10734SEric Cheng static dladm_status_t
1965*10734SEric Cheng do_check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
1966*10734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t val_cnt,
1967*10734SEric Cheng     val_desc_t *vdp, datalink_media_t media)
1968*10734SEric Cheng {
1969*10734SEric Cheng 	dladm_status_t	status;
1970*10734SEric Cheng 	ipaddr_t	addr;
1971*10734SEric Cheng 	int		i;
1972*10734SEric Cheng 
1973*10734SEric Cheng 	if (val_cnt > MPT_MAXIPADDR)
1974*10734SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
1975*10734SEric Cheng 
1976*10734SEric Cheng 	for (i = 0; i < val_cnt; i++) {
1977*10734SEric Cheng 		status = dladm_str2ipv4addr(prop_val[i], &addr);
1978*10734SEric Cheng 		if (status != DLADM_STATUS_OK)
1979*10734SEric Cheng 			return (status);
1980*10734SEric Cheng 
1981*10734SEric Cheng 		if (addr == 0)
1982*10734SEric Cheng 			return (DLADM_STATUS_BADVAL);
1983*10734SEric Cheng 
1984*10734SEric Cheng 		vdp[i].vd_val = (uintptr_t)addr;
1985*10734SEric Cheng 	}
1986*10734SEric Cheng 	return (DLADM_STATUS_OK);
1987*10734SEric Cheng }
1988*10734SEric Cheng 
1989*10734SEric Cheng /* ARGSUSED */
1990*10734SEric Cheng static dladm_status_t
19918453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19928275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
19938275SEric Cheng     uint_t flags, uint_t *perm_flags)
19945895Syz147064 {
19957342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
19967342SAruna.Ramakrishna@Sun.COM 	int		i, len;
19977342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
19987342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
19995895Syz147064 
20006789Sam223141 	if (flags & MAC_PROP_DEFAULT)
20017776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
20026512Ssowmini 
20035895Syz147064 	*val_cnt = 1;
20048453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
20058275SEric Cheng 	    &status, perm_flags);
20067342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
20075895Syz147064 		(*prop_val)[0] = '\0';
20088275SEric Cheng 		return (DLADM_STATUS_OK);
20095895Syz147064 	}
20107342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
20115895Syz147064 
20127342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
20135895Syz147064 		if (i != 0) {
20145895Syz147064 			(void) snprintf(*prop_val + len,
20155895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
20165895Syz147064 			len += 1;
20175895Syz147064 		}
20185895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
20197342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
20207342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
20217342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
20225895Syz147064 			(void) snprintf(*prop_val + len,
20235895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
20245895Syz147064 			    AP_ANCHOR);
20255895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
20265895Syz147064 		}
20275895Syz147064 	}
20287342SAruna.Ramakrishna@Sun.COM 	free(dip);
20295895Syz147064 done:
20305895Syz147064 	return (DLADM_STATUS_OK);
20315895Syz147064 }
20325895Syz147064 
20335895Syz147064 /*
20345895Syz147064  * Add the specified module to the dlautopush structure; returns a
20355895Syz147064  * DLADM_STATUS_* code.
20365895Syz147064  */
20375895Syz147064 dladm_status_t
20385895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
20395895Syz147064 {
20405895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
20415895Syz147064 		return (DLADM_STATUS_BADVAL);
20425895Syz147064 
20435895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
20445895Syz147064 		/*
20455895Syz147064 		 * We don't allow multiple anchors, and the anchor must
20465895Syz147064 		 * be after at least one module.
20475895Syz147064 		 */
20485895Syz147064 		if (dlap->dap_anchor != 0)
20495895Syz147064 			return (DLADM_STATUS_BADVAL);
20505895Syz147064 		if (dlap->dap_npush == 0)
20515895Syz147064 			return (DLADM_STATUS_BADVAL);
20525895Syz147064 
20535895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
20545895Syz147064 		return (DLADM_STATUS_OK);
20555895Syz147064 	}
20568957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
20575895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20585895Syz147064 
20595895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
20605895Syz147064 	    FMNAMESZ + 1);
20615895Syz147064 
20625895Syz147064 	return (DLADM_STATUS_OK);
20635895Syz147064 }
20645895Syz147064 
20655895Syz147064 /*
20665895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
20675895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
20685895Syz147064  * latter is used in the autopush(1M) file.
20695895Syz147064  */
20705895Syz147064 /* ARGSUSED */
20715895Syz147064 static dladm_status_t
20728453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20738453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
20745895Syz147064 {
20755895Syz147064 	char			*module;
20765895Syz147064 	struct dlautopush	*dlap;
20775895Syz147064 	dladm_status_t		status;
20785895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
20795895Syz147064 	char			delimiters[4];
20805895Syz147064 
20815895Syz147064 	if (val_cnt != 1)
20825895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20835895Syz147064 
20847342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
20857342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
20867342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
20877342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
20883448Sdh155122 
20897342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
20907342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
20917342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
20927342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
20937342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
20947342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
20957342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
20967342SAruna.Ramakrishna@Sun.COM 				return (status);
20977342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
20987342SAruna.Ramakrishna@Sun.COM 		}
20997342SAruna.Ramakrishna@Sun.COM 
21007342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
21017342SAruna.Ramakrishna@Sun.COM 	} else {
21027342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
21035895Syz147064 	}
21043448Sdh155122 	return (DLADM_STATUS_OK);
21053448Sdh155122 }
21063448Sdh155122 
21077663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
21087663SSowmini.Varadhan@Sun.COM 
21095903Ssowmini /* ARGSUSED */
21103448Sdh155122 static dladm_status_t
21118453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
21128453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
21138453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
21143448Sdh155122 {
21155895Syz147064 	wl_rates_t	*wrp;
21165895Syz147064 	uint_t		i;
21175895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21185895Syz147064 
21197663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
21207663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
21217663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
21225895Syz147064 
21238453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
21248453SAnurag.Maskey@Sun.COM 	    B_FALSE);
21255895Syz147064 	if (status != DLADM_STATUS_OK)
21265895Syz147064 		goto done;
21275895Syz147064 
21285895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
21295895Syz147064 		status = DLADM_STATUS_TOOSMALL;
21305895Syz147064 		goto done;
21315895Syz147064 	}
21325895Syz147064 
21335895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
21345895Syz147064 		prop_val[0][0] = '\0';
21355895Syz147064 		*val_cnt = 1;
21365895Syz147064 		goto done;
21375895Syz147064 	}
21385895Syz147064 
21395895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
21405895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
21415895Syz147064 		    wrp->wl_rates_rates[i] % 2,
21425895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
21435895Syz147064 	}
21445895Syz147064 	*val_cnt = wrp->wl_rates_num;
21458275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
21463448Sdh155122 
21475895Syz147064 done:
21487663SSowmini.Varadhan@Sun.COM 	free(wrp);
21495895Syz147064 	return (status);
21505895Syz147064 }
21515895Syz147064 
21525895Syz147064 static dladm_status_t
21538453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21548275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
21558275SEric Cheng     uint_t flags, uint_t *perm_flags)
21565895Syz147064 {
21578118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
21588453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
21598275SEric Cheng 		    val_cnt, flags, perm_flags));
21608118SVasumathi.Sundaram@Sun.COM 	}
21615960Ssowmini 
21628453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
21638275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
21645895Syz147064 }
21655895Syz147064 
21666512Ssowmini /* ARGSUSED */
21675895Syz147064 static dladm_status_t
21688453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21698275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
21708275SEric Cheng     uint_t flags, uint_t *perm_flags)
21715895Syz147064 {
21725960Ssowmini 	switch (media) {
21735960Ssowmini 	case DL_ETHER:
21746512Ssowmini 		/*
21756512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
21766512Ssowmini 		 * links can have a speed of 5.5 Gbps.
21776512Ssowmini 		 */
21786512Ssowmini 		return (DLADM_STATUS_NOTSUP);
21795960Ssowmini 
21805960Ssowmini 	case DL_WIFI:
21818453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
21828453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
21835960Ssowmini 	default:
21845960Ssowmini 		return (DLADM_STATUS_BADARG);
21855960Ssowmini 	}
21865895Syz147064 }
21875895Syz147064 
21885895Syz147064 static dladm_status_t
21898453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
21908453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
21915895Syz147064 {
21925895Syz147064 	int		i;
21935895Syz147064 	uint_t		len;
21945895Syz147064 	wl_rates_t	*wrp;
21955895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21965895Syz147064 
21977663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
21987663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
21995895Syz147064 		return (DLADM_STATUS_NOMEM);
22005895Syz147064 
22017663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
22025895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
22035895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
22045895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
22055895Syz147064 
22065895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
22075895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
22088453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
22098453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
22105895Syz147064 
22117663SSowmini.Varadhan@Sun.COM 	free(wrp);
22125895Syz147064 	return (status);
22135895Syz147064 }
22143448Sdh155122 
22155903Ssowmini /* ARGSUSED */
22165895Syz147064 static dladm_status_t
22178453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22185960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
22195895Syz147064 {
22205895Syz147064 	dladm_wlan_rates_t	rates;
22215895Syz147064 	dladm_status_t		status;
22225895Syz147064 
22235960Ssowmini 	/*
22245960Ssowmini 	 * can currently set rate on WIFI links only.
22255960Ssowmini 	 */
22265960Ssowmini 	if (media != DL_WIFI)
22275960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
22285960Ssowmini 
22295895Syz147064 	if (val_cnt != 1)
22305895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22315895Syz147064 
22325895Syz147064 	rates.wr_cnt = 1;
22335895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
22345895Syz147064 
22358453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
22365895Syz147064 
22375895Syz147064 done:
22385895Syz147064 	return (status);
22395895Syz147064 }
22403448Sdh155122 
22415895Syz147064 /* ARGSUSED */
22425895Syz147064 static dladm_status_t
22438453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22448453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
22455895Syz147064 {
22465895Syz147064 	int		i;
22475895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
22485895Syz147064 	char		*buf, **modval;
22495895Syz147064 	dladm_status_t	status;
22508118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
22515895Syz147064 
22525895Syz147064 	if (val_cnt != 1)
22535895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22545895Syz147064 
22555895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
22565895Syz147064 	    MAX_SUPPORT_RATES);
22575895Syz147064 	if (buf == NULL) {
22585895Syz147064 		status = DLADM_STATUS_NOMEM;
22595895Syz147064 		goto done;
22605895Syz147064 	}
22613448Sdh155122 
22625895Syz147064 	modval = (char **)(void *)buf;
22635895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
22645895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
22655895Syz147064 		    i * DLADM_STRSIZE;
22665895Syz147064 	}
22675895Syz147064 
22688453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
22698453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
22705895Syz147064 	if (status != DLADM_STATUS_OK)
22715895Syz147064 		goto done;
22725895Syz147064 
22735895Syz147064 	for (i = 0; i < modval_cnt; i++) {
22745895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
22755903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
22765903Ssowmini 			    (atof(*prop_val) * 2);
22775895Syz147064 			status = DLADM_STATUS_OK;
22783448Sdh155122 			break;
22793448Sdh155122 		}
22805895Syz147064 	}
22815895Syz147064 	if (i == modval_cnt)
22825895Syz147064 		status = DLADM_STATUS_BADVAL;
22835895Syz147064 done:
22845895Syz147064 	free(buf);
22855895Syz147064 	return (status);
22865895Syz147064 }
22875895Syz147064 
22885895Syz147064 static dladm_status_t
22898453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
22908453SAnurag.Maskey@Sun.COM     int buflen)
22915895Syz147064 {
22928453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
22937663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
22945895Syz147064 }
22955895Syz147064 
22965903Ssowmini /* ARGSUSED */
22975895Syz147064 static dladm_status_t
22988453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
22998453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
23008453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23015895Syz147064 {
23025895Syz147064 	uint32_t	channel;
23037663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
23045895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
23057663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
23065895Syz147064 
23078453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
23087663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
23095895Syz147064 		goto done;
23105895Syz147064 
23117663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
23127663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
23135895Syz147064 		status = DLADM_STATUS_NOTFOUND;
23145895Syz147064 		goto done;
23155895Syz147064 	}
23165895Syz147064 
23175895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
23185895Syz147064 	*val_cnt = 1;
23198275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
23205895Syz147064 done:
23215895Syz147064 	return (status);
23225895Syz147064 }
23235895Syz147064 
23245895Syz147064 static dladm_status_t
23258453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
23268453SAnurag.Maskey@Sun.COM     int buflen)
23275895Syz147064 {
23288453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
23297663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
23305895Syz147064 }
23315895Syz147064 
23325903Ssowmini /* ARGSUSED */
23335895Syz147064 static dladm_status_t
23348453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
23358453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
23368453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23375895Syz147064 {
23387663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
23395895Syz147064 	const char	*s;
23407663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
23415895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
23425895Syz147064 
23438453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
23447663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
23455895Syz147064 		goto done;
23465895Syz147064 
23477663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
23487663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
23495895Syz147064 	case WL_PM_AM:
23505895Syz147064 		s = "off";
23515895Syz147064 		break;
23525895Syz147064 	case WL_PM_MPS:
23535895Syz147064 		s = "max";
23545895Syz147064 		break;
23555895Syz147064 	case WL_PM_FAST:
23565895Syz147064 		s = "fast";
23573448Sdh155122 		break;
23583448Sdh155122 	default:
23595895Syz147064 		status = DLADM_STATUS_NOTFOUND;
23605895Syz147064 		goto done;
23615895Syz147064 	}
23625895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
23635895Syz147064 	*val_cnt = 1;
23648275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
23655895Syz147064 done:
23665895Syz147064 	return (status);
23675895Syz147064 }
23685895Syz147064 
23695895Syz147064 static dladm_status_t
23708453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
23718453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
23725895Syz147064 {
23735895Syz147064 	wl_ps_mode_t    ps_mode;
23745895Syz147064 
23755895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
23765895Syz147064 
23775895Syz147064 	switch (*pm) {
23785895Syz147064 	case DLADM_WLAN_PM_OFF:
23795895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
23803448Sdh155122 		break;
23815895Syz147064 	case DLADM_WLAN_PM_MAX:
23825895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
23835895Syz147064 		break;
23845895Syz147064 	case DLADM_WLAN_PM_FAST:
23855895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
23865895Syz147064 		break;
23875895Syz147064 	default:
23885895Syz147064 		return (DLADM_STATUS_NOTSUP);
23893448Sdh155122 	}
23908453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
23918453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
23925895Syz147064 }
23935895Syz147064 
23945895Syz147064 /* ARGSUSED */
23955895Syz147064 static dladm_status_t
23968453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
23978453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
23988453SAnurag.Maskey@Sun.COM     datalink_media_t media)
23995895Syz147064 {
24005895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
24015895Syz147064 	dladm_status_t status;
24025895Syz147064 
24035895Syz147064 	if (val_cnt != 1)
24045895Syz147064 		return (DLADM_STATUS_BADVALCNT);
24055895Syz147064 
24068453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
24073448Sdh155122 
24083448Sdh155122 	return (status);
24093448Sdh155122 }
24103448Sdh155122 
24113448Sdh155122 static dladm_status_t
24128453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
24133448Sdh155122 {
24148453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
24158453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
24165895Syz147064 }
24173448Sdh155122 
24185903Ssowmini /* ARGSUSED */
24195895Syz147064 static dladm_status_t
24208453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
24218275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
24228275SEric Cheng     uint_t flags, uint_t *perm_flags)
24235895Syz147064 {
24245895Syz147064 	wl_radio_t	radio;
24255895Syz147064 	const char	*s;
24267663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
24275895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
24283448Sdh155122 
24298453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
24307663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
24315895Syz147064 		goto done;
24323448Sdh155122 
24337663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
24345895Syz147064 	switch (radio) {
24355895Syz147064 	case B_TRUE:
24365895Syz147064 		s = "on";
24375895Syz147064 		break;
24385895Syz147064 	case B_FALSE:
24395895Syz147064 		s = "off";
24405895Syz147064 		break;
24415895Syz147064 	default:
24425895Syz147064 		status = DLADM_STATUS_NOTFOUND;
24435895Syz147064 		goto done;
24445895Syz147064 	}
24455895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
24465895Syz147064 	*val_cnt = 1;
24478275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
24485895Syz147064 done:
24493448Sdh155122 	return (status);
24503448Sdh155122 }
24513448Sdh155122 
24523448Sdh155122 static dladm_status_t
24538453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
24548453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
24553448Sdh155122 {
24565895Syz147064 	wl_radio_t r;
24573448Sdh155122 
24585895Syz147064 	switch (*radio) {
24595895Syz147064 	case DLADM_WLAN_RADIO_ON:
24605895Syz147064 		r = B_TRUE;
24615895Syz147064 		break;
24625895Syz147064 	case DLADM_WLAN_RADIO_OFF:
24635895Syz147064 		r = B_FALSE;
24645895Syz147064 		break;
24655895Syz147064 	default:
24665895Syz147064 		return (DLADM_STATUS_NOTSUP);
24675895Syz147064 	}
24688453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
24697663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
24705895Syz147064 }
24713448Sdh155122 
24725895Syz147064 /* ARGSUSED */
24735895Syz147064 static dladm_status_t
24748453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
247510616SSebastien.Roy@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
24765895Syz147064 {
24775895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
24785895Syz147064 	dladm_status_t status;
24793448Sdh155122 
24805895Syz147064 	if (val_cnt != 1)
24815895Syz147064 		return (DLADM_STATUS_BADVALCNT);
24825895Syz147064 
24838453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
24843448Sdh155122 
24853448Sdh155122 	return (status);
24863448Sdh155122 }
24873448Sdh155122 
248810616SSebastien.Roy@Sun.COM /* ARGSUSED */
248910616SSebastien.Roy@Sun.COM static dladm_status_t
249010616SSebastien.Roy@Sun.COM do_check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
249110616SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
249210616SSebastien.Roy@Sun.COM     datalink_media_t media)
249310616SSebastien.Roy@Sun.COM {
249410616SSebastien.Roy@Sun.COM 	int32_t	hlim;
249510616SSebastien.Roy@Sun.COM 	char	*ep;
249610616SSebastien.Roy@Sun.COM 
249710616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
249810616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
249910616SSebastien.Roy@Sun.COM 
250010616SSebastien.Roy@Sun.COM 	errno = 0;
250110616SSebastien.Roy@Sun.COM 	hlim = strtol(*prop_val, &ep, 10);
250210616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || hlim < 1 ||
250310616SSebastien.Roy@Sun.COM 	    hlim > (int32_t)UINT8_MAX)
250410616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
250510616SSebastien.Roy@Sun.COM 	vdp->vd_val = hlim;
250610616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
250710616SSebastien.Roy@Sun.COM }
250810616SSebastien.Roy@Sun.COM 
250910616SSebastien.Roy@Sun.COM /* ARGSUSED */
251010616SSebastien.Roy@Sun.COM static dladm_status_t
251110616SSebastien.Roy@Sun.COM do_check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
251210616SSebastien.Roy@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
251310616SSebastien.Roy@Sun.COM {
251410616SSebastien.Roy@Sun.COM 	int32_t	elim;
251510616SSebastien.Roy@Sun.COM 	char	*ep;
251610616SSebastien.Roy@Sun.COM 
251710616SSebastien.Roy@Sun.COM 	if (media != DL_IPV6)
251810616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADARG);
251910616SSebastien.Roy@Sun.COM 
252010616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
252110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
252210616SSebastien.Roy@Sun.COM 
252310616SSebastien.Roy@Sun.COM 	errno = 0;
252410616SSebastien.Roy@Sun.COM 	elim = strtol(*prop_val, &ep, 10);
252510616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || elim < 0 ||
252610616SSebastien.Roy@Sun.COM 	    elim > (int32_t)UINT8_MAX)
252710616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
252810616SSebastien.Roy@Sun.COM 	vdp->vd_val = elim;
252910616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
253010616SSebastien.Roy@Sun.COM }
253110616SSebastien.Roy@Sun.COM 
25325895Syz147064 static dladm_status_t
25338453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
25348453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
25353448Sdh155122 {
25365895Syz147064 	char		buf[MAXLINELEN];
25375895Syz147064 	int		i;
25385895Syz147064 	dladm_conf_t	conf;
25395895Syz147064 	dladm_status_t	status;
25403448Sdh155122 
25418453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
25425895Syz147064 	if (status != DLADM_STATUS_OK)
25435895Syz147064 		return (status);
25443448Sdh155122 
25455895Syz147064 	/*
25465895Syz147064 	 * reset case.
25475895Syz147064 	 */
25485895Syz147064 	if (val_cnt == 0) {
25498453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
25505895Syz147064 		if (status == DLADM_STATUS_OK)
25518453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
25525895Syz147064 		goto done;
25535895Syz147064 	}
25543448Sdh155122 
25555895Syz147064 	buf[0] = '\0';
25565895Syz147064 	for (i = 0; i < val_cnt; i++) {
25575895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
25585895Syz147064 		if (i != val_cnt - 1)
25595895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
25603448Sdh155122 	}
25613448Sdh155122 
25628453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
25638453SAnurag.Maskey@Sun.COM 	    buf);
25645895Syz147064 	if (status == DLADM_STATUS_OK)
25658453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
25665895Syz147064 
25675895Syz147064 done:
25688453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
25695895Syz147064 	return (status);
25703448Sdh155122 }
25715895Syz147064 
25725895Syz147064 static dladm_status_t
25738453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
25748453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
25755895Syz147064 {
25765895Syz147064 	char		buf[MAXLINELEN], *str;
25775895Syz147064 	uint_t		cnt = 0;
25785895Syz147064 	dladm_conf_t	conf;
25795895Syz147064 	dladm_status_t	status;
25805895Syz147064 
25818453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
25825895Syz147064 	if (status != DLADM_STATUS_OK)
25835895Syz147064 		return (status);
25845895Syz147064 
25858453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
25865895Syz147064 	if (status != DLADM_STATUS_OK)
25875895Syz147064 		goto done;
25885895Syz147064 
25895895Syz147064 	str = strtok(buf, ",");
25905895Syz147064 	while (str != NULL) {
25915895Syz147064 		if (cnt == *val_cntp) {
25925895Syz147064 			status = DLADM_STATUS_TOOSMALL;
25935895Syz147064 			goto done;
25945895Syz147064 		}
25955895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
25965895Syz147064 		str = strtok(NULL, ",");
25975895Syz147064 	}
25985895Syz147064 
25995895Syz147064 	*val_cntp = cnt;
26005895Syz147064 
26015895Syz147064 done:
26028453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
26035895Syz147064 	return (status);
26045895Syz147064 }
26055903Ssowmini 
26068460SArtem.Kachitchkin@Sun.COM /*
26078460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
26088460SArtem.Kachitchkin@Sun.COM  */
26098460SArtem.Kachitchkin@Sun.COM static dladm_status_t
26108460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
26118460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
26128460SArtem.Kachitchkin@Sun.COM {
26138460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
26148460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
26158460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
26168460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
26178460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
26188460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
26198460SArtem.Kachitchkin@Sun.COM 
26208460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
26218460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
26228460SArtem.Kachitchkin@Sun.COM 
26238460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
26248460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
26258460SArtem.Kachitchkin@Sun.COM 		return (status);
26268460SArtem.Kachitchkin@Sun.COM 
26278460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
26288460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
26298460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
26308460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
26318460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
26328460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
26338460SArtem.Kachitchkin@Sun.COM 				break;
26348460SArtem.Kachitchkin@Sun.COM 		}
26358460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
26368460SArtem.Kachitchkin@Sun.COM 	}
26378460SArtem.Kachitchkin@Sun.COM 
26388460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
26398460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
26408460SArtem.Kachitchkin@Sun.COM }
26418460SArtem.Kachitchkin@Sun.COM 
26427663SSowmini.Varadhan@Sun.COM static link_attr_t *
26435903Ssowmini dladm_name2prop(const char *prop_name)
26445903Ssowmini {
26457663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
26465903Ssowmini 
26477663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
26485903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
26495903Ssowmini 			break;
26505903Ssowmini 	}
26515903Ssowmini 	return (p);
26525903Ssowmini }
26535903Ssowmini 
26547663SSowmini.Varadhan@Sun.COM static link_attr_t *
26557663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
26567663SSowmini.Varadhan@Sun.COM {
26577663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
26587663SSowmini.Varadhan@Sun.COM 
26597663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
26607663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
26617663SSowmini.Varadhan@Sun.COM 			break;
26627663SSowmini.Varadhan@Sun.COM 	}
26637663SSowmini.Varadhan@Sun.COM 	return (p);
26647663SSowmini.Varadhan@Sun.COM }
26655903Ssowmini 
26666789Sam223141 static dld_ioc_macprop_t *
26677663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
26687663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
26697663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
26705903Ssowmini {
26715903Ssowmini 	int dsize;
26726789Sam223141 	dld_ioc_macprop_t *dip;
26735903Ssowmini 
26745903Ssowmini 	*status = DLADM_STATUS_OK;
26756789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
26765903Ssowmini 	dip = malloc(dsize);
26775903Ssowmini 	if (dip == NULL) {
26785903Ssowmini 		*status = DLADM_STATUS_NOMEM;
26795903Ssowmini 		return (NULL);
26805903Ssowmini 	}
26815903Ssowmini 	bzero(dip, dsize);
26825903Ssowmini 	dip->pr_valsize = valsize;
26836512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
26846789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
26855960Ssowmini 	dip->pr_linkid = linkid;
26867663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
26876512Ssowmini 	dip->pr_flags = flags;
26885903Ssowmini 	return (dip);
26895903Ssowmini }
26905903Ssowmini 
26917663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
26927663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
26937663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
26947663SSowmini.Varadhan@Sun.COM {
26957663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
26967663SSowmini.Varadhan@Sun.COM 
26977663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
26987663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
26997663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
27007663SSowmini.Varadhan@Sun.COM 	    flags, status));
27017663SSowmini.Varadhan@Sun.COM }
27027663SSowmini.Varadhan@Sun.COM 
27037663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
27047663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
27057663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
27067663SSowmini.Varadhan@Sun.COM {
27077663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
27087663SSowmini.Varadhan@Sun.COM 
27097663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
27107663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
27117663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
27127663SSowmini.Varadhan@Sun.COM 	    flags, status));
27137663SSowmini.Varadhan@Sun.COM }
27147663SSowmini.Varadhan@Sun.COM 
27155903Ssowmini /* ARGSUSED */
27165903Ssowmini static dladm_status_t
27178453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
27188453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
27198453SAnurag.Maskey@Sun.COM     datalink_media_t media)
27205903Ssowmini {
27216789Sam223141 	dld_ioc_macprop_t	*dip;
27225903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
27235903Ssowmini 	uint8_t		u8;
27245903Ssowmini 	uint16_t	u16;
27255903Ssowmini 	uint32_t	u32;
27265903Ssowmini 	void		*val;
27275903Ssowmini 
27288275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
27295903Ssowmini 	if (dip == NULL)
27305903Ssowmini 		return (status);
27315903Ssowmini 
27328275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
27335903Ssowmini 		val = (void *)vdp->vd_val;
27345903Ssowmini 	else {
27355903Ssowmini 		/*
27365903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
27375903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
27385903Ssowmini 		 */
27395903Ssowmini 		switch (dip->pr_valsize) {
27405903Ssowmini 		case 1:
27415903Ssowmini 			u8 = vdp->vd_val;
27425903Ssowmini 			val = &u8;
27435903Ssowmini 			break;
27445903Ssowmini 		case 2:
27455903Ssowmini 			u16 = vdp->vd_val;
27465903Ssowmini 			val = &u16;
27475903Ssowmini 			break;
27485903Ssowmini 		case 4:
27495903Ssowmini 			u32 = vdp->vd_val;
27505903Ssowmini 			val = &u32;
27515903Ssowmini 			break;
27525903Ssowmini 		default:
27535903Ssowmini 			val = &vdp->vd_val;
27545903Ssowmini 			break;
27555903Ssowmini 		}
27565903Ssowmini 	}
27575903Ssowmini 
27587342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
27597342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
27607342SAruna.Ramakrishna@Sun.COM 	else
27617342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
27627342SAruna.Ramakrishna@Sun.COM 
27638453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
27647663SSowmini.Varadhan@Sun.COM 
27657663SSowmini.Varadhan@Sun.COM done:
27667663SSowmini.Varadhan@Sun.COM 	free(dip);
27677663SSowmini.Varadhan@Sun.COM 	return (status);
27687663SSowmini.Varadhan@Sun.COM }
27697663SSowmini.Varadhan@Sun.COM 
27707663SSowmini.Varadhan@Sun.COM dladm_status_t
27718453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
27727663SSowmini.Varadhan@Sun.COM {
27737663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
27747663SSowmini.Varadhan@Sun.COM 
27758453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
27768453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
27775903Ssowmini 		status = dladm_errno2status(errno);
27788453SAnurag.Maskey@Sun.COM 
27795903Ssowmini 	return (status);
27805903Ssowmini }
27815903Ssowmini 
27826789Sam223141 static dld_ioc_macprop_t *
27838453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
27848453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
27855903Ssowmini {
27866789Sam223141 	dld_ioc_macprop_t *dip = NULL;
27876512Ssowmini 
27887663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
27896512Ssowmini 	if (dip == NULL)
27906512Ssowmini 		return (NULL);
27915903Ssowmini 
27928453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
27936512Ssowmini 	if (*status != DLADM_STATUS_OK) {
27946512Ssowmini 		free(dip);
27956512Ssowmini 		return (NULL);
27966512Ssowmini 	}
27978275SEric Cheng 	if (perm_flags != NULL)
27988275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
27998275SEric Cheng 
28006512Ssowmini 	return (dip);
28015903Ssowmini }
28025903Ssowmini 
28035903Ssowmini /* ARGSUSED */
28045903Ssowmini static dladm_status_t
280510491SRishi.Srivatsavai@Sun.COM i_dladm_uint32_check(dladm_handle_t handle, prop_desc_t *pdp,
28068453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
28078453SAnurag.Maskey@Sun.COM     datalink_media_t media)
28085903Ssowmini {
28095903Ssowmini 	if (val_cnt != 1)
28105903Ssowmini 		return (DLADM_STATUS_BADVAL);
281110491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
28125903Ssowmini 	return (DLADM_STATUS_OK);
28135903Ssowmini }
28145903Ssowmini 
28155903Ssowmini /* ARGSUSED */
28165903Ssowmini static dladm_status_t
28178453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
28188453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28198453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28205903Ssowmini {
28215903Ssowmini 	link_duplex_t   link_duplex;
28225903Ssowmini 	dladm_status_t  status;
28235903Ssowmini 
28248453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
28255903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
28265903Ssowmini 		return (status);
28275903Ssowmini 
28285903Ssowmini 	switch (link_duplex) {
28295903Ssowmini 	case LINK_DUPLEX_FULL:
28305903Ssowmini 		(void) strcpy(*prop_val, "full");
28315903Ssowmini 		break;
28325903Ssowmini 	case LINK_DUPLEX_HALF:
28335903Ssowmini 		(void) strcpy(*prop_val, "half");
28345903Ssowmini 		break;
28355903Ssowmini 	default:
28365903Ssowmini 		(void) strcpy(*prop_val, "unknown");
28375903Ssowmini 		break;
28385903Ssowmini 	}
28395903Ssowmini 	*val_cnt = 1;
28405903Ssowmini 	return (DLADM_STATUS_OK);
28415903Ssowmini }
28425903Ssowmini 
28435903Ssowmini /* ARGSUSED */
28445903Ssowmini static dladm_status_t
28458453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
28468275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
28475903Ssowmini {
28485903Ssowmini 	uint64_t	ifspeed = 0;
28495903Ssowmini 	dladm_status_t status;
28505903Ssowmini 
28518453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
28525903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
28535903Ssowmini 		return (status);
28546512Ssowmini 
28555960Ssowmini 	if ((ifspeed % 1000000) != 0) {
28565960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
28575960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
28585960Ssowmini 	} else {
28595960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
28605960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
28615960Ssowmini 	}
28625903Ssowmini 	*val_cnt = 1;
28638275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
28645903Ssowmini 	return (DLADM_STATUS_OK);
28655903Ssowmini }
28665903Ssowmini 
28675903Ssowmini /* ARGSUSED */
28685903Ssowmini static dladm_status_t
28698453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
28708453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28718453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28725903Ssowmini {
28738275SEric Cheng 	link_state_t		link_state;
28748275SEric Cheng 	dladm_status_t		status;
28758306SSowmini.Varadhan@Sun.COM 
28768453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
28776512Ssowmini 	if (status != DLADM_STATUS_OK)
28785903Ssowmini 		return (status);
28798275SEric Cheng 
28805903Ssowmini 	switch (link_state) {
28815903Ssowmini 	case LINK_STATE_UP:
28825903Ssowmini 		(void) strcpy(*prop_val, "up");
28835903Ssowmini 		break;
28845903Ssowmini 	case LINK_STATE_DOWN:
28855903Ssowmini 		(void) strcpy(*prop_val, "down");
28865903Ssowmini 		break;
28875903Ssowmini 	default:
28885903Ssowmini 		(void) strcpy(*prop_val, "unknown");
28895903Ssowmini 		break;
28905903Ssowmini 	}
28915903Ssowmini 	*val_cnt = 1;
28928306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
28935903Ssowmini 	return (DLADM_STATUS_OK);
28945903Ssowmini }
28955903Ssowmini 
28965903Ssowmini /* ARGSUSED */
28975903Ssowmini static dladm_status_t
28988453SAnurag.Maskey@Sun.COM i_dladm_binary_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 	dladm_status_t status;
29045903Ssowmini 
29058453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29068275SEric Cheng 	    &status, perm_flags);
29076512Ssowmini 	if (dip == NULL)
29085903Ssowmini 		return (status);
29098275SEric Cheng 
29105903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
29115903Ssowmini 	free(dip);
29125903Ssowmini 	*val_cnt = 1;
29135903Ssowmini 	return (DLADM_STATUS_OK);
29145903Ssowmini }
29155903Ssowmini 
29165960Ssowmini /* ARGSUSED */
29175903Ssowmini static dladm_status_t
29188453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
29198453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29208453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29215903Ssowmini {
29226789Sam223141 	dld_ioc_macprop_t *dip;
29238275SEric Cheng 	uint32_t v = 0;
29245903Ssowmini 	uchar_t *cp;
29255903Ssowmini 	dladm_status_t status;
29265903Ssowmini 
29278453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29288275SEric Cheng 	    &status, perm_flags);
29296512Ssowmini 	if (dip == NULL)
29305903Ssowmini 		return (status);
29318275SEric Cheng 
29325903Ssowmini 	cp = (uchar_t *)dip->pr_val;
29335903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
29346512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
29355903Ssowmini 	free(dip);
29365903Ssowmini 	*val_cnt = 1;
29375903Ssowmini 	return (DLADM_STATUS_OK);
29385903Ssowmini }
29395903Ssowmini 
29409514SGirish.Moodalbail@Sun.COM /*
29419514SGirish.Moodalbail@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
29429514SGirish.Moodalbail@Sun.COM  * for retrieving the property range values.
29439514SGirish.Moodalbail@Sun.COM  */
29449514SGirish.Moodalbail@Sun.COM static int
29459514SGirish.Moodalbail@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
29469514SGirish.Moodalbail@Sun.COM {
29479514SGirish.Moodalbail@Sun.COM 	uint_t count = r->mpr_count;
29489514SGirish.Moodalbail@Sun.COM 
29499514SGirish.Moodalbail@Sun.COM 	*sz = sizeof (mac_propval_range_t);
29509514SGirish.Moodalbail@Sun.COM 	--count;
29519514SGirish.Moodalbail@Sun.COM 
29529514SGirish.Moodalbail@Sun.COM 	switch (r->mpr_type) {
29539514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32:
29549514SGirish.Moodalbail@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
29559514SGirish.Moodalbail@Sun.COM 		return (0);
29569514SGirish.Moodalbail@Sun.COM 	default:
29579514SGirish.Moodalbail@Sun.COM 		break;
29589514SGirish.Moodalbail@Sun.COM 	}
29599514SGirish.Moodalbail@Sun.COM 	*sz = 0;
29609514SGirish.Moodalbail@Sun.COM 	return (EINVAL);
29619514SGirish.Moodalbail@Sun.COM }
29629514SGirish.Moodalbail@Sun.COM 
29639514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
29649514SGirish.Moodalbail@Sun.COM static dladm_status_t
29659514SGirish.Moodalbail@Sun.COM i_dladm_range_get(dladm_handle_t handle, prop_desc_t *pdp,
29669514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29679514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29689514SGirish.Moodalbail@Sun.COM {
29699514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
29709514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
29719514SGirish.Moodalbail@Sun.COM 	size_t	sz;
29729514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
29739514SGirish.Moodalbail@Sun.COM 
29749514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
29759514SGirish.Moodalbail@Sun.COM 
29769514SGirish.Moodalbail@Sun.COM 	/*
29779514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
29789514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
29799514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
29809514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
29819514SGirish.Moodalbail@Sun.COM 	 */
29829514SGirish.Moodalbail@Sun.COM retry:
29839514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
29849514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
29859514SGirish.Moodalbail@Sun.COM 		return (status);
29869514SGirish.Moodalbail@Sun.COM 
29879514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
29889514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
29899514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
29909514SGirish.Moodalbail@Sun.COM 			int err;
29919514SGirish.Moodalbail@Sun.COM 
29929514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
29939514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
29949514SGirish.Moodalbail@Sun.COM 				free(dip);
29959514SGirish.Moodalbail@Sun.COM 				goto retry;
29969514SGirish.Moodalbail@Sun.COM 			} else {
29979514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
29989514SGirish.Moodalbail@Sun.COM 			}
29999514SGirish.Moodalbail@Sun.COM 		}
30009514SGirish.Moodalbail@Sun.COM 		free(dip);
30019514SGirish.Moodalbail@Sun.COM 		return (status);
30029514SGirish.Moodalbail@Sun.COM 	}
30039514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
30049514SGirish.Moodalbail@Sun.COM 
30059514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
30069514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
30079514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
30089514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
30099514SGirish.Moodalbail@Sun.COM 
30109514SGirish.Moodalbail@Sun.COM 		ur = &rangep->range_uint32[0];
30119514SGirish.Moodalbail@Sun.COM 
30129514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
30139514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
30149514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
30159514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
30169514SGirish.Moodalbail@Sun.COM 			} else {
30179514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
30189514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
30199514SGirish.Moodalbail@Sun.COM 			}
30209514SGirish.Moodalbail@Sun.COM 		}
30219514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
30229514SGirish.Moodalbail@Sun.COM 		break;
30239514SGirish.Moodalbail@Sun.COM 	}
30249514SGirish.Moodalbail@Sun.COM 	default:
30259514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
30269514SGirish.Moodalbail@Sun.COM 		break;
30279514SGirish.Moodalbail@Sun.COM 	}
30289514SGirish.Moodalbail@Sun.COM 	free(dip);
30299514SGirish.Moodalbail@Sun.COM 	return (status);
30309514SGirish.Moodalbail@Sun.COM }
30319514SGirish.Moodalbail@Sun.COM 
30325960Ssowmini /* ARGSUSED */
30335903Ssowmini static dladm_status_t
30348874SSebastien.Roy@Sun.COM i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
30358874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30368874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30378874SSebastien.Roy@Sun.COM {
30388874SSebastien.Roy@Sun.COM 	dld_ioc_macprop_t	*dip;
30398874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
30408874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
30418874SSebastien.Roy@Sun.COM 
30428874SSebastien.Roy@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
30438874SSebastien.Roy@Sun.COM 	    &status, perm_flags);
30448874SSebastien.Roy@Sun.COM 	if (dip == NULL)
30458874SSebastien.Roy@Sun.COM 		return (status);
30468874SSebastien.Roy@Sun.COM 	(void) memcpy(&mode, dip->pr_val, sizeof (mode));
30478874SSebastien.Roy@Sun.COM 	free(dip);
30488874SSebastien.Roy@Sun.COM 
30498874SSebastien.Roy@Sun.COM 	switch (mode) {
30508874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
30518874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
30528874SSebastien.Roy@Sun.COM 		break;
30538874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
30548874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
30558874SSebastien.Roy@Sun.COM 		break;
30568874SSebastien.Roy@Sun.COM 	default:
30578874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
30588874SSebastien.Roy@Sun.COM 	}
30598874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
30608874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
30618874SSebastien.Roy@Sun.COM }
30628874SSebastien.Roy@Sun.COM 
30638874SSebastien.Roy@Sun.COM /* ARGSUSED */
30648874SSebastien.Roy@Sun.COM static dladm_status_t
30658453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
30668453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30678453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30685903Ssowmini {
30696789Sam223141 	dld_ioc_macprop_t *dip;
30705903Ssowmini 	link_flowctrl_t v;
30715903Ssowmini 	dladm_status_t status;
30725903Ssowmini 	uchar_t *cp;
30735903Ssowmini 
30748453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
30758275SEric Cheng 	    &status, perm_flags);
30766512Ssowmini 	if (dip == NULL)
30775903Ssowmini 		return (status);
30788275SEric Cheng 
30795903Ssowmini 	cp = (uchar_t *)dip->pr_val;
30805903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
30815903Ssowmini 	switch (v) {
30825903Ssowmini 	case LINK_FLOWCTRL_NONE:
30835903Ssowmini 		(void) sprintf(*prop_val, "no");
30845903Ssowmini 		break;
30855903Ssowmini 	case LINK_FLOWCTRL_RX:
30865903Ssowmini 		(void) sprintf(*prop_val, "rx");
30875903Ssowmini 		break;
30885903Ssowmini 	case LINK_FLOWCTRL_TX:
30895903Ssowmini 		(void) sprintf(*prop_val, "tx");
30905903Ssowmini 		break;
30915903Ssowmini 	case LINK_FLOWCTRL_BI:
30925903Ssowmini 		(void) sprintf(*prop_val, "bi");
30935903Ssowmini 		break;
30945903Ssowmini 	}
30955903Ssowmini 	free(dip);
30965903Ssowmini 	*val_cnt = 1;
30975903Ssowmini 	return (DLADM_STATUS_OK);
30985903Ssowmini }
30995903Ssowmini 
31005903Ssowmini 
31015903Ssowmini /* ARGSUSED */
31025903Ssowmini static dladm_status_t
31039692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
31048453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
31058453SAnurag.Maskey@Sun.COM 
31065903Ssowmini {
31077663SSowmini.Varadhan@Sun.COM 	int		i, slen;
31087408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
31096789Sam223141 	dld_ioc_macprop_t *dip = NULL;
31105903Ssowmini 	uchar_t 	*dp;
31117663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
31126512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
31135903Ssowmini 
31145903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
31155903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
31165903Ssowmini 		return (DLADM_STATUS_BADARG);
31175903Ssowmini 	p = dladm_name2prop(prop_name);
31186789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
31195903Ssowmini 		return (DLADM_STATUS_BADARG);
31205903Ssowmini 
31219692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
31229692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
31239692SRishi.Srivatsavai@Sun.COM 
31245903Ssowmini 	/*
31255903Ssowmini 	 * private properties: all parsing is done in the kernel.
31265903Ssowmini 	 * allocate a enough space for each property + its separator (',').
31275903Ssowmini 	 */
31285903Ssowmini 	for (i = 0; i < val_cnt; i++) {
31295903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
31305903Ssowmini 	}
31316512Ssowmini 
31326512Ssowmini 	if (prop_val == NULL) {
31336512Ssowmini 		/*
31346512Ssowmini 		 * getting default value. so use more buffer space.
31356512Ssowmini 		 */
31367663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
31376512Ssowmini 	}
31386512Ssowmini 
31397663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
31406789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
31415903Ssowmini 	if (dip == NULL)
31425903Ssowmini 		return (status);
31435903Ssowmini 
31445903Ssowmini 	dp = (uchar_t *)dip->pr_val;
31455903Ssowmini 	slen = 0;
31467663SSowmini.Varadhan@Sun.COM 
31476512Ssowmini 	if (prop_val == NULL) {
31488453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
31498460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
31506512Ssowmini 	} else {
31516512Ssowmini 		for (i = 0; i < val_cnt; i++) {
31526512Ssowmini 			int plen = 0;
31535903Ssowmini 
31546512Ssowmini 			plen = strlen(prop_val[i]);
31556512Ssowmini 			bcopy(prop_val[i], dp, plen);
31566512Ssowmini 			slen += plen;
31576512Ssowmini 			/*
31586512Ssowmini 			 * add a "," separator and update dp.
31596512Ssowmini 			 */
31606512Ssowmini 			if (i != (val_cnt -1))
31616512Ssowmini 				dp[slen++] = ',';
31626512Ssowmini 			dp += (plen + 1);
31636512Ssowmini 		}
31648460SArtem.Kachitchkin@Sun.COM 	}
31658460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
31668453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
31676512Ssowmini 
31685903Ssowmini 	free(dip);
31696512Ssowmini 	return (status);
31705903Ssowmini }
31715903Ssowmini 
31725903Ssowmini static dladm_status_t
31738460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
31748453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
31758453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
31765903Ssowmini {
31777663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
31786789Sam223141 	dld_ioc_macprop_t *dip = NULL;
31797663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
31805903Ssowmini 
31815903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
31825903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
31835903Ssowmini 		return (DLADM_STATUS_BADARG);
31845903Ssowmini 
31855903Ssowmini 	p = dladm_name2prop(prop_name);
31866789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
31875903Ssowmini 		return (DLADM_STATUS_BADARG);
31885903Ssowmini 
31895903Ssowmini 	/*
31905903Ssowmini 	 * private properties: all parsing is done in the kernel.
31915903Ssowmini 	 */
31927663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
31937663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
31945903Ssowmini 	if (dip == NULL)
31955903Ssowmini 		return (status);
31965903Ssowmini 
31978453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
31988453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
31998118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
32008275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
32018460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
32028460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
32038118SVasumathi.Sundaram@Sun.COM 		} else {
32048118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
32058118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
32068118SVasumathi.Sundaram@Sun.COM 		}
32075903Ssowmini 		*val_cnt = 1;
32088460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
32098460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
32108460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
32115903Ssowmini 	}
32126512Ssowmini 	free(dip);
32135903Ssowmini 	return (status);
32145903Ssowmini }
32156512Ssowmini 
32166512Ssowmini 
32176512Ssowmini static dladm_status_t
32188453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
32198453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
32206512Ssowmini {
32216512Ssowmini 	dladm_status_t status;
32226512Ssowmini 	char **prop_vals = NULL, *buf;
32236512Ssowmini 	size_t bufsize;
32246512Ssowmini 	uint_t cnt;
32256512Ssowmini 	int i;
32268118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
32276512Ssowmini 
32286512Ssowmini 	/*
32296512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
32306512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
32316512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
32326512Ssowmini 	 */
32336512Ssowmini 	bufsize =
32346512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
32356512Ssowmini 	buf = malloc(bufsize);
32366512Ssowmini 	prop_vals = (char **)(void *)buf;
32376512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
32386512Ssowmini 		prop_vals[i] = buf +
32396512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
32406512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
32416512Ssowmini 	}
32426768Sar224390 
32436768Sar224390 	/*
32447342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
32457342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
32467342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
32477342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
32487342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
32497342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
32507342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
32517342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
32526768Sar224390 	 */
32538453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
32548118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
32556512Ssowmini 	if (status == DLADM_STATUS_OK) {
32568118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
32578453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
32588453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
32598118SVasumathi.Sundaram@Sun.COM 		}
32608118SVasumathi.Sundaram@Sun.COM 		else
32618118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
32626512Ssowmini 	}
32636512Ssowmini 	free(buf);
32646512Ssowmini 	return (status);
32656512Ssowmini }
32667663SSowmini.Varadhan@Sun.COM 
326710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
326810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
326910491SRishi.Srivatsavai@Sun.COM get_stp_prop(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
327010491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
327110491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
327210491SRishi.Srivatsavai@Sun.COM {
327310491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
327410491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
327510491SRishi.Srivatsavai@Sun.COM 	int val, i;
327610491SRishi.Srivatsavai@Sun.COM 
327710491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
327810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
327910491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
328010491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
328110491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
328210491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
328310491SRishi.Srivatsavai@Sun.COM 			break;
328410491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
328510491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
328610491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
328710491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
328810491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
328910491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
329010491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
329110491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
329210491SRishi.Srivatsavai@Sun.COM 	}
329310491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
329410491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
329510491SRishi.Srivatsavai@Sun.COM 		return (retv);
329610491SRishi.Srivatsavai@Sun.COM 	}
329710491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
329810491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
329910491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
330010491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
330110491SRishi.Srivatsavai@Sun.COM 	}
330210491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
330310491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
330410491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
330510491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
330610491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
330710491SRishi.Srivatsavai@Sun.COM 		}
330810491SRishi.Srivatsavai@Sun.COM 	}
330910491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
331010491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
331110491SRishi.Srivatsavai@Sun.COM }
331210491SRishi.Srivatsavai@Sun.COM 
331310491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
331410491SRishi.Srivatsavai@Sun.COM static dladm_status_t
331510491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
331610491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
331710491SRishi.Srivatsavai@Sun.COM {
331810491SRishi.Srivatsavai@Sun.COM 	/*
331910491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
332010491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
332110491SRishi.Srivatsavai@Sun.COM 	 */
332210491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
332310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
332410491SRishi.Srivatsavai@Sun.COM 
332510491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
332610491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
332710491SRishi.Srivatsavai@Sun.COM }
332810491SRishi.Srivatsavai@Sun.COM 
332910491SRishi.Srivatsavai@Sun.COM /*
333010491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
333110491SRishi.Srivatsavai@Sun.COM  */
333210491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
333310491SRishi.Srivatsavai@Sun.COM static dladm_status_t
333410491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
333510491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
333610491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
333710491SRishi.Srivatsavai@Sun.COM {
333810491SRishi.Srivatsavai@Sun.COM 	char *cp;
333910491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
334010491SRishi.Srivatsavai@Sun.COM 
334110491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
334210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
334310491SRishi.Srivatsavai@Sun.COM 
334410491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
334510491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
334610491SRishi.Srivatsavai@Sun.COM 	} else {
334710491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
334810491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
334910491SRishi.Srivatsavai@Sun.COM 
335010491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
335110491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
335210491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
335310491SRishi.Srivatsavai@Sun.COM 		} else {
335410491SRishi.Srivatsavai@Sun.COM 			errno = 0;
335510491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
335610491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
335710491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
335810491SRishi.Srivatsavai@Sun.COM 		}
335910491SRishi.Srivatsavai@Sun.COM 	}
336010491SRishi.Srivatsavai@Sun.COM 
336110491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
336210491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
336310491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
336410491SRishi.Srivatsavai@Sun.COM 	} else {
336510491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
336610491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
336710491SRishi.Srivatsavai@Sun.COM 		/*
336810491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
336910491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
337010491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
337110491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
337210491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
337310491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
337410491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
337510491SRishi.Srivatsavai@Sun.COM 		 */
337610491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
337710491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
337810491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
337910491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
338010491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
338110491SRishi.Srivatsavai@Sun.COM 
338210491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
338310491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
338410491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
338510491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
338610491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
338710491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
338810491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
338910491SRishi.Srivatsavai@Sun.COM 		}
339010491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
339110491SRishi.Srivatsavai@Sun.COM 	}
339210491SRishi.Srivatsavai@Sun.COM }
339310491SRishi.Srivatsavai@Sun.COM 
339410491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
339510491SRishi.Srivatsavai@Sun.COM static dladm_status_t
339610491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
339710491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
339810491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
339910491SRishi.Srivatsavai@Sun.COM {
340010491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
340110491SRishi.Srivatsavai@Sun.COM 	uint_t val;
340210491SRishi.Srivatsavai@Sun.COM 
340310491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
340410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
340510491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
340610491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
340710491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
340810491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
340910491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
341010491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
341110491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
341210491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
341310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
341410491SRishi.Srivatsavai@Sun.COM 	}
341510491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
341610491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
341710491SRishi.Srivatsavai@Sun.COM 	else
341810491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
341910491SRishi.Srivatsavai@Sun.COM 	return (retv);
342010491SRishi.Srivatsavai@Sun.COM }
342110491SRishi.Srivatsavai@Sun.COM 
342210491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
342310491SRishi.Srivatsavai@Sun.COM static dladm_status_t
342410491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
342510491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
342610491SRishi.Srivatsavai@Sun.COM {
342710491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
342810491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
342910491SRishi.Srivatsavai@Sun.COM }
343010491SRishi.Srivatsavai@Sun.COM 
343110491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
343210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
343310491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
343410491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
343510491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
343610491SRishi.Srivatsavai@Sun.COM {
343710491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
343810491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
343910491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
344010491SRishi.Srivatsavai@Sun.COM 
344110491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
344210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
344310491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
344410491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
344510491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
344610491SRishi.Srivatsavai@Sun.COM 	    0, &status);
344710491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
344810491SRishi.Srivatsavai@Sun.COM 		return (status);
344910491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
345010491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
345110491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
345210491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
345310491SRishi.Srivatsavai@Sun.COM 	} else {
345410491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
345510491SRishi.Srivatsavai@Sun.COM 	}
345610491SRishi.Srivatsavai@Sun.COM 	free(dip);
345710491SRishi.Srivatsavai@Sun.COM 	return (status);
345810491SRishi.Srivatsavai@Sun.COM }
345910491SRishi.Srivatsavai@Sun.COM 
346010491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
346110491SRishi.Srivatsavai@Sun.COM static dladm_status_t
346210491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
346310491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
346410491SRishi.Srivatsavai@Sun.COM {
346510491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
346610491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
346710491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
346810491SRishi.Srivatsavai@Sun.COM 
346910491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
347010491SRishi.Srivatsavai@Sun.COM 	    0, &status);
347110491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
347210491SRishi.Srivatsavai@Sun.COM 		return (status);
347310491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
347410491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
347510491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
347610491SRishi.Srivatsavai@Sun.COM 	free(dip);
347710491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
347810491SRishi.Srivatsavai@Sun.COM 		return (status);
347910491SRishi.Srivatsavai@Sun.COM 
348010491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
348110491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
348210491SRishi.Srivatsavai@Sun.COM }
348310491SRishi.Srivatsavai@Sun.COM 
348410491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
348510491SRishi.Srivatsavai@Sun.COM static dladm_status_t
348610491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
348710491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
348810491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
348910491SRishi.Srivatsavai@Sun.COM {
349010491SRishi.Srivatsavai@Sun.COM 	char *cp;
349110491SRishi.Srivatsavai@Sun.COM 
349210491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
349310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
349410491SRishi.Srivatsavai@Sun.COM 
349510491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
349610491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
349710491SRishi.Srivatsavai@Sun.COM 	} else {
349810491SRishi.Srivatsavai@Sun.COM 		errno = 0;
349910491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
350010491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
350110491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
350210491SRishi.Srivatsavai@Sun.COM 	}
350310491SRishi.Srivatsavai@Sun.COM 
350410491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
350510491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
350610491SRishi.Srivatsavai@Sun.COM }
350710491SRishi.Srivatsavai@Sun.COM 
35087663SSowmini.Varadhan@Sun.COM dladm_status_t
35098453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
35108453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
35117663SSowmini.Varadhan@Sun.COM {
35127663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
35137663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
35147663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
35157663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
35167663SSowmini.Varadhan@Sun.COM 	void			*dp;
35177663SSowmini.Varadhan@Sun.COM 
35188453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
35198453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
35207663SSowmini.Varadhan@Sun.COM 		return (status);
35217663SSowmini.Varadhan@Sun.COM 	}
35227663SSowmini.Varadhan@Sun.COM 
35237663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
35247663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
35257663SSowmini.Varadhan@Sun.COM 
35267663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
35277663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
35287663SSowmini.Varadhan@Sun.COM 
35297663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
35307663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
35317663SSowmini.Varadhan@Sun.COM 
35327663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
35337663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
35347663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
35357663SSowmini.Varadhan@Sun.COM 
35367663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
35377663SSowmini.Varadhan@Sun.COM 	if (set)
35387663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
35397663SSowmini.Varadhan@Sun.COM 
35408453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
354110191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
35427663SSowmini.Varadhan@Sun.COM 		if (!set)
35437663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
35447663SSowmini.Varadhan@Sun.COM 	}
35457663SSowmini.Varadhan@Sun.COM 
35467663SSowmini.Varadhan@Sun.COM 	free(dip);
35477663SSowmini.Varadhan@Sun.COM 	return (status);
35487663SSowmini.Varadhan@Sun.COM }
35497663SSowmini.Varadhan@Sun.COM 
35508275SEric Cheng dladm_status_t
35518275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
35528275SEric Cheng {
35538460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
35548275SEric Cheng }
35558275SEric Cheng 
35568275SEric Cheng /*
35578275SEric Cheng  * Retrieve the one link property from the database
35588275SEric Cheng  */
35598275SEric Cheng /*ARGSUSED*/
35608275SEric Cheng static int
35618453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
35628453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
35638275SEric Cheng {
35648275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
35658275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
35668275SEric Cheng 
35678275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
35688275SEric Cheng 	/*
35698275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
35708275SEric Cheng 	 * prop_table[n].pd_name.
35718275SEric Cheng 	 */
35728275SEric Cheng 	aip->ai_name = prop_name;
35738275SEric Cheng 
35748453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
35758453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
35768275SEric Cheng 
35778275SEric Cheng 	if (aip->ai_count != 0)
35788275SEric Cheng 		proplist->al_count++;
35798275SEric Cheng 
35808275SEric Cheng 	return (DLADM_WALK_CONTINUE);
35818275SEric Cheng }
35828275SEric Cheng 
35838275SEric Cheng 
35848275SEric Cheng /*
35858275SEric Cheng  * Retrieve all link properties for a link from the database and
35868275SEric Cheng  * return a property list.
35878275SEric Cheng  */
35888275SEric Cheng dladm_status_t
35898453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
35908453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
35918275SEric Cheng {
35928275SEric Cheng 	dladm_arg_list_t	*list;
35938275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
35948275SEric Cheng 
35958275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
35968275SEric Cheng 	if (list == NULL)
35978275SEric Cheng 		return (dladm_errno2status(errno));
35988275SEric Cheng 
35998453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
36008453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
36018275SEric Cheng 
36028275SEric Cheng 	*listp = list;
36038275SEric Cheng 	return (status);
36048275SEric Cheng }
36058275SEric Cheng 
36068275SEric Cheng /*
36078275SEric Cheng  * Retrieve the named property from a proplist, check the value and
36088275SEric Cheng  * convert to a kernel structure.
36098275SEric Cheng  */
36108275SEric Cheng static dladm_status_t
36118453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
3612*10734SEric Cheng     dladm_arg_list_t *proplist, const char *name, void *arg)
36138275SEric Cheng {
36148275SEric Cheng 	dladm_status_t		status;
36158275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
36168275SEric Cheng 	int			i, j;
36178275SEric Cheng 
36188275SEric Cheng 	/* Find named property in proplist */
36198275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
36208275SEric Cheng 		aip = &proplist->al_info[i];
36218275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
36228275SEric Cheng 			break;
36238275SEric Cheng 	}
36248275SEric Cheng 
36258275SEric Cheng 	/* Property not in list */
36268275SEric Cheng 	if (i == proplist->al_count)
36278275SEric Cheng 		return (DLADM_STATUS_OK);
36288275SEric Cheng 
36298275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
36308275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
36318275SEric Cheng 		val_desc_t	*vdp;
36328275SEric Cheng 
36338275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
36348275SEric Cheng 		if (vdp == NULL)
36358275SEric Cheng 			return (DLADM_STATUS_NOMEM);
36368275SEric Cheng 
36378275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
36388275SEric Cheng 			continue;
36398275SEric Cheng 
36408275SEric Cheng 		if (aip->ai_val == NULL)
36418275SEric Cheng 			return (DLADM_STATUS_BADARG);
36428275SEric Cheng 
36438275SEric Cheng 		/* Check property value */
36448275SEric Cheng 		if (pdp->pd_check != NULL) {
36458453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
36468275SEric Cheng 			    aip->ai_count, vdp, 0);
36478275SEric Cheng 		} else {
36488275SEric Cheng 			status = DLADM_STATUS_BADARG;
36498275SEric Cheng 		}
36508275SEric Cheng 
36518275SEric Cheng 		if (status != DLADM_STATUS_OK)
36528275SEric Cheng 			return (status);
36538275SEric Cheng 
36548275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
36558275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
36568275SEric Cheng 
36578275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
36588275SEric Cheng 				continue;
36598275SEric Cheng 
36608275SEric Cheng 			/* Extract kernel structure */
36618275SEric Cheng 			if (rpp->rp_extract != NULL) {
3662*10734SEric Cheng 				status = rpp->rp_extract(vdp,
3663*10734SEric Cheng 				    aip->ai_count, arg);
36648275SEric Cheng 			} else {
36658275SEric Cheng 				status = DLADM_STATUS_BADARG;
36668275SEric Cheng 			}
36678275SEric Cheng 			break;
36688275SEric Cheng 		}
36698275SEric Cheng 
36708275SEric Cheng 		if (status != DLADM_STATUS_OK)
36718275SEric Cheng 			return (status);
36728275SEric Cheng 
36738275SEric Cheng 		break;
36748275SEric Cheng 	}
36758275SEric Cheng 	return (status);
36768275SEric Cheng }
36778275SEric Cheng 
36788275SEric Cheng /*
36798275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
36808275SEric Cheng  */
36818275SEric Cheng dladm_status_t
36828453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
36838275SEric Cheng     mac_resource_props_t *mrp)
36848275SEric Cheng {
3685*10734SEric Cheng 	dladm_status_t	status;
3686*10734SEric Cheng 	int		i;
3687*10734SEric Cheng 
3688*10734SEric Cheng 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
3689*10734SEric Cheng 		status = i_dladm_link_proplist_extract_one(handle,
3690*10734SEric Cheng 		    proplist, rsrc_prop_table[i].rp_name, mrp);
3691*10734SEric Cheng 		if (status != DLADM_STATUS_OK)
3692*10734SEric Cheng 			return (status);
3693*10734SEric Cheng 	}
36948275SEric Cheng 	return (status);
36958275SEric Cheng }
36968275SEric Cheng 
36978275SEric Cheng static const char *
36988275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
36998275SEric Cheng {
37008275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
37018275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
37028275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
37038275SEric Cheng 	return (buf);
37048275SEric Cheng }
37058306SSowmini.Varadhan@Sun.COM 
37068306SSowmini.Varadhan@Sun.COM dladm_status_t
37078453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
37088453SAnurag.Maskey@Sun.COM     link_state_t *state)
37098306SSowmini.Varadhan@Sun.COM {
37108306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
37118306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
37128306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
37138306SSowmini.Varadhan@Sun.COM 
37148453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
37158453SAnurag.Maskey@Sun.COM 	    &perms);
37168306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
37178306SSowmini.Varadhan@Sun.COM 		return (status);
37188306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
37198306SSowmini.Varadhan@Sun.COM 	free(dip);
37208306SSowmini.Varadhan@Sun.COM 	return (status);
37218306SSowmini.Varadhan@Sun.COM }
37228460SArtem.Kachitchkin@Sun.COM 
37238460SArtem.Kachitchkin@Sun.COM boolean_t
37248460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
37258460SArtem.Kachitchkin@Sun.COM {
37268460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
37278460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
37288460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
37298460SArtem.Kachitchkin@Sun.COM 		"name",
37308460SArtem.Kachitchkin@Sun.COM 		"class",
37318460SArtem.Kachitchkin@Sun.COM 		"media",
37328460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
37338460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
37348460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
37358460SArtem.Kachitchkin@Sun.COM 
37368460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
37378460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
37388460SArtem.Kachitchkin@Sun.COM 	};
37398460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
37408460SArtem.Kachitchkin@Sun.COM 	int		i;
37418460SArtem.Kachitchkin@Sun.COM 
37428460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
37438460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
37448460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
37458460SArtem.Kachitchkin@Sun.COM 			break;
37468460SArtem.Kachitchkin@Sun.COM 		}
37478460SArtem.Kachitchkin@Sun.COM 	}
37488460SArtem.Kachitchkin@Sun.COM 
37498460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
37508460SArtem.Kachitchkin@Sun.COM }
3751