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,
14110734SEric Cheng 			get_bridge_pvid,
14210734SEric Cheng 			/* the above need to be renamed to "do_get_xxx" */
14310734SEric 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,
14810734SEric Cheng 			set_stp_prop, set_bridge_forward, set_bridge_pvid,
14910734SEric 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,
15410734SEric Cheng 			do_check_priority, check_stp_prop, check_bridge_pvid,
15510734SEric 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 
34710734SEric Cheng 	{ MAC_PROP_PROTECT,	sizeof (mac_resource_props_t),	"protection"},
34810734SEric 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 
39610734SEric Cheng static  val_desc_t	link_protect_vals[] = {
39710734SEric Cheng 	{ "mac-nospoof",	MPT_MACNOSPOOF	},
39810734SEric Cheng 	{ "ip-nospoof",		MPT_IPNOSPOOF	},
39910734SEric Cheng 	{ "restricted",		MPT_RESTRICTED	}
40010734SEric Cheng };
40110734SEric 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 },
63510734SEric Cheng 
63610734SEric Cheng 	{ "protection", { "--", RESET_VAL },
63710734SEric Cheng 	    link_protect_vals, VALCNT(link_protect_vals),
63810734SEric Cheng 	    do_set_protection, NULL, do_get_protection, do_check_prop, 0,
63910734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
64010734SEric Cheng 
64110734SEric Cheng 	{ "allowed-ips", { "--", 0 },
64210734SEric Cheng 	    NULL, 0, do_set_protection, NULL,
64310734SEric Cheng 	    do_get_protection, do_check_allowedips, 0,
64410734SEric 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},
65210734SEric Cheng 	{"cpus",	do_extract_cpus},
65310734SEric Cheng 	{"protection",	do_extract_protection},
65410734SEric 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 
69210734SEric Cheng /* ARGSUSED */
6935895Syz147064 static dladm_status_t
69410734SEric Cheng do_check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
69510734SEric 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++) {
70110734SEric Cheng 			if (strcasecmp(prop_val[j],
7025895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
7035895Syz147064 				break;
7045895Syz147064 			}
7055895Syz147064 		}
70610734SEric Cheng 		if (i == pdp->pd_noptval)
70710734SEric Cheng 			return (DLADM_STATUS_BADVAL);
70810734SEric Cheng 
70910734SEric Cheng 		(void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
7105895Syz147064 	}
71110734SEric 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) {
74910734SEric Cheng 			status = do_check_prop(handle, pdp, linkid, prop_val,
75010734SEric 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 {
1214*11021SEric.Cheng@Sun.COM 	char		*buf, **propvals;
1215*11021SEric.Cheng@Sun.COM 	uint_t		i, valcnt = DLADM_MAX_PROP_VALCNT;
1216*11021SEric.Cheng@Sun.COM 	dladm_status_t	status, *retval = arg;
12175895Syz147064 
12185895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
12195895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
12205895Syz147064 		return (DLADM_WALK_CONTINUE);
12215895Syz147064 	}
12225895Syz147064 
12235895Syz147064 	propvals = (char **)(void *)buf;
12245895Syz147064 	for (i = 0; i < valcnt; i++) {
12255895Syz147064 		propvals[i] = buf +
12265895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
12275895Syz147064 		    i * DLADM_PROP_VAL_MAX;
12285895Syz147064 	}
12295895Syz147064 
12308453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
12318453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
12325895Syz147064 		goto done;
12335895Syz147064 	}
12345895Syz147064 
1235*11021SEric.Cheng@Sun.COM 	status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
1236*11021SEric.Cheng@Sun.COM 	    valcnt, DLADM_OPT_ACTIVE);
1237*11021SEric.Cheng@Sun.COM 	if (status != DLADM_STATUS_OK)
1238*11021SEric.Cheng@Sun.COM 		*retval = status;
12395895Syz147064 
12405895Syz147064 done:
12415895Syz147064 	if (buf != NULL)
12425895Syz147064 		free(buf);
12435895Syz147064 
12445895Syz147064 	return (DLADM_WALK_CONTINUE);
12455895Syz147064 }
12465895Syz147064 
12475895Syz147064 /*ARGSUSED*/
12485895Syz147064 static int
12498453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
12505895Syz147064 {
12518275SEric Cheng 	datalink_class_t	class;
12528275SEric Cheng 	dladm_status_t		status;
12538275SEric Cheng 
12548453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
12558453SAnurag.Maskey@Sun.COM 	    NULL, 0);
12568275SEric Cheng 	if (status != DLADM_STATUS_OK)
12578275SEric Cheng 		return (DLADM_WALK_TERMINATE);
12588275SEric Cheng 
12598275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
12608453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
12618275SEric Cheng 
12625895Syz147064 	return (DLADM_WALK_CONTINUE);
12635895Syz147064 }
12645895Syz147064 
12655895Syz147064 dladm_status_t
12668453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
12678453SAnurag.Maskey@Sun.COM     boolean_t any_media)
12685895Syz147064 {
1269*11021SEric.Cheng@Sun.COM 	dladm_status_t		status = DLADM_STATUS_OK;
12706916Sartem 	datalink_media_t	dmedia;
12716916Sartem 	uint32_t		media;
12726916Sartem 
12736916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
12746916Sartem 
12755895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
12768453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
12778453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
12788453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
12798453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
12808453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
12816916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
1282*11021SEric.Cheng@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, &status,
12838453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
12843448Sdh155122 	}
1285*11021SEric.Cheng@Sun.COM 	return (status);
12863147Sxc151355 }
12873147Sxc151355 
12885903Ssowmini /* ARGSUSED */
12895895Syz147064 static dladm_status_t
12908453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12918275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12928275SEric Cheng     uint_t flags, uint_t *perm_flags)
12933147Sxc151355 {
12948275SEric Cheng 	char			zone_name[ZONENAME_MAX];
12958275SEric Cheng 	zoneid_t		zid;
12968275SEric Cheng 	dladm_status_t		status;
12978275SEric Cheng 	char			*cp;
12987342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
12993147Sxc151355 
13006512Ssowmini 	if (flags != 0)
13016512Ssowmini 		return (DLADM_STATUS_NOTSUP);
13026512Ssowmini 
13038453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13048275SEric Cheng 	    &status, perm_flags);
13055895Syz147064 	if (status != DLADM_STATUS_OK)
13063448Sdh155122 		return (status);
13073448Sdh155122 
13087342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
13097342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
13107342SAruna.Ramakrishna@Sun.COM 	free(dip);
13117342SAruna.Ramakrishna@Sun.COM 
13125895Syz147064 	*val_cnt = 1;
13135895Syz147064 	if (zid != GLOBAL_ZONEID) {
13148118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
13155895Syz147064 			return (dladm_errno2status(errno));
13168118SVasumathi.Sundaram@Sun.COM 		}
13173147Sxc151355 
13185895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
13193147Sxc151355 	} else {
13205895Syz147064 		*prop_val[0] = '\0';
13213147Sxc151355 	}
13223147Sxc151355 
13233448Sdh155122 	return (DLADM_STATUS_OK);
13243448Sdh155122 }
13253448Sdh155122 
13263448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
13273448Sdh155122 
13283448Sdh155122 static int
13293448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
13303448Sdh155122 {
13313448Sdh155122 	char			root[MAXPATHLEN];
13323448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
13333448Sdh155122 	void			*dlhandle;
13343448Sdh155122 	void			*sym;
13353448Sdh155122 	int			ret;
13363448Sdh155122 
13373448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
13383448Sdh155122 		return (-1);
13393448Sdh155122 
13403448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
13413448Sdh155122 		(void) dlclose(dlhandle);
13423448Sdh155122 		return (-1);
13433448Sdh155122 	}
13443448Sdh155122 
13453448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
13463448Sdh155122 
13473448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
13483448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
13493448Sdh155122 	(void) dlclose(dlhandle);
13503448Sdh155122 	return (ret);
13513448Sdh155122 }
13523448Sdh155122 
13533448Sdh155122 static dladm_status_t
13548453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
13558453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
13563448Sdh155122 {
13573448Sdh155122 	char		path[MAXPATHLEN];
13585895Syz147064 	char		name[MAXLINKNAMELEN];
13593448Sdh155122 	di_prof_t	prof = NULL;
13603448Sdh155122 	char		zone_name[ZONENAME_MAX];
13613448Sdh155122 	dladm_status_t	status;
13625895Syz147064 	int		ret;
13633448Sdh155122 
13643448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
13653448Sdh155122 		return (dladm_errno2status(errno));
13663448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
13673448Sdh155122 		return (dladm_errno2status(errno));
13683448Sdh155122 	if (di_prof_init(path, &prof) != 0)
13693448Sdh155122 		return (dladm_errno2status(errno));
13703448Sdh155122 
13718453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
13725895Syz147064 	if (status != DLADM_STATUS_OK)
13735895Syz147064 		goto cleanup;
13745895Syz147064 
13755895Syz147064 	if (add)
13765895Syz147064 		ret = di_prof_add_dev(prof, name);
13775895Syz147064 	else
13785895Syz147064 		ret = di_prof_add_exclude(prof, name);
13795895Syz147064 
13805895Syz147064 	if (ret != 0) {
13813448Sdh155122 		status = dladm_errno2status(errno);
13823448Sdh155122 		goto cleanup;
13833448Sdh155122 	}
13843448Sdh155122 
13853448Sdh155122 	if (di_prof_commit(prof) != 0)
13863448Sdh155122 		status = dladm_errno2status(errno);
13873448Sdh155122 cleanup:
13883448Sdh155122 	if (prof)
13893448Sdh155122 		di_prof_fini(prof);
13903448Sdh155122 
13913448Sdh155122 	return (status);
13923448Sdh155122 }
13933448Sdh155122 
13945903Ssowmini /* ARGSUSED */
13953448Sdh155122 static dladm_status_t
13968453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13978453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13983448Sdh155122 {
13998275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
14008275SEric Cheng 	zoneid_t		zid_old, zid_new;
14018275SEric Cheng 	char			*cp;
14027342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
14037342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
14043448Sdh155122 
14053448Sdh155122 	if (val_cnt != 1)
14063448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14073448Sdh155122 
14087342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
14097342SAruna.Ramakrishna@Sun.COM 
14108453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
14118275SEric Cheng 	    &status, NULL);
14128275SEric Cheng 	if (status != DLADM_STATUS_OK)
14138275SEric Cheng 		return (status);
14148275SEric Cheng 
14158275SEric Cheng 	cp = dip->pr_val;
14168275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
14178275SEric Cheng 	free(dip);
14187342SAruna.Ramakrishna@Sun.COM 
14197342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
14203448Sdh155122 	if (zid_new == zid_old)
142110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_OK);
142210616SSebastien.Roy@Sun.COM 
142310616SSebastien.Roy@Sun.COM 	if ((status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, val_cnt,
142410616SSebastien.Roy@Sun.COM 	    flags, media)) != DLADM_STATUS_OK)
14255895Syz147064 		return (status);
14265895Syz147064 
142710616SSebastien.Roy@Sun.COM 	/*
142810616SSebastien.Roy@Sun.COM 	 * It is okay to fail to update the /dev entry (some vanity-named
142910616SSebastien.Roy@Sun.COM 	 * links do not have a /dev entry).
143010616SSebastien.Roy@Sun.COM 	 */
14313448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
14328453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
14338453SAnurag.Maskey@Sun.COM 		    B_FALSE);
14345895Syz147064 	}
143510616SSebastien.Roy@Sun.COM 	if (zid_new != GLOBAL_ZONEID)
14368453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
14373448Sdh155122 
14383448Sdh155122 	return (DLADM_STATUS_OK);
14393448Sdh155122 }
14403448Sdh155122 
14413448Sdh155122 /* ARGSUSED */
14423448Sdh155122 static dladm_status_t
14438453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14448453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14453448Sdh155122 {
14467342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
14477342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
14487342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
14497342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
14503448Sdh155122 
14513448Sdh155122 	if (val_cnt != 1)
14523448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14533448Sdh155122 
14547342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
14557342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
14567342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
14573448Sdh155122 
14588275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
14597342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
14607342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
14617342SAruna.Ramakrishna@Sun.COM 		goto done;
14627342SAruna.Ramakrishna@Sun.COM 	}
14637342SAruna.Ramakrishna@Sun.COM 
14647342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
14653448Sdh155122 		ushort_t	flags;
14663448Sdh155122 
14677342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
14683448Sdh155122 		    sizeof (flags)) < 0) {
14697342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
14707342SAruna.Ramakrishna@Sun.COM 			goto done;
14713448Sdh155122 		}
14723448Sdh155122 
14733448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
14747342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
14757342SAruna.Ramakrishna@Sun.COM 			goto done;
14763448Sdh155122 		}
14773448Sdh155122 	}
14783448Sdh155122 
14797342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
14807342SAruna.Ramakrishna@Sun.COM 
14817342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
148210616SSebastien.Roy@Sun.COM 	dzp->diz_linkid = linkid;
14837342SAruna.Ramakrishna@Sun.COM 
14847342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
14855895Syz147064 	return (DLADM_STATUS_OK);
14867342SAruna.Ramakrishna@Sun.COM done:
14877342SAruna.Ramakrishna@Sun.COM 	free(dzp);
14887342SAruna.Ramakrishna@Sun.COM 	return (status);
14895895Syz147064 }
14905895Syz147064 
14915903Ssowmini /* ARGSUSED */
14925895Syz147064 static dladm_status_t
14938460SArtem.Kachitchkin@Sun.COM i_dladm_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14948275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
14958275SEric Cheng     uint_t flags, uint_t *perm_flags)
14968275SEric Cheng {
14978275SEric Cheng 	dld_ioc_macprop_t	*dip;
14988275SEric Cheng 	mac_resource_props_t	mrp;
14998275SEric Cheng 	dladm_status_t		status;
15008275SEric Cheng 
15018453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15028275SEric Cheng 	    &status, perm_flags);
15038275SEric Cheng 	if (dip == NULL)
15048275SEric Cheng 		return (status);
15058275SEric Cheng 
15068275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
15078275SEric Cheng 	free(dip);
15088275SEric Cheng 
15098275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
15108275SEric Cheng 		(*prop_val)[0] = '\0';
15118275SEric Cheng 	} else {
15128275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
15138275SEric Cheng 	}
15148275SEric Cheng 	*val_cnt = 1;
15158275SEric Cheng 	return (DLADM_STATUS_OK);
15168275SEric Cheng }
15178275SEric Cheng 
15188275SEric Cheng /* ARGSUSED */
15198275SEric Cheng static dladm_status_t
15208453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15218453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
15228275SEric Cheng {
15238275SEric Cheng 	uint64_t	*maxbw;
15248275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15258275SEric Cheng 
15268275SEric Cheng 	if (val_cnt != 1)
15278275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15288275SEric Cheng 
15298275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
15308275SEric Cheng 	if (maxbw == NULL)
15318275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15328275SEric Cheng 
15338275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
15348275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15358275SEric Cheng 		free(maxbw);
15368275SEric Cheng 		return (status);
15378275SEric Cheng 	}
15388275SEric Cheng 
15398275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
15408275SEric Cheng 		free(maxbw);
15418275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
15428275SEric Cheng 	}
15438275SEric Cheng 
15448275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
15458275SEric Cheng 	return (DLADM_STATUS_OK);
15468275SEric Cheng }
15478275SEric Cheng 
15488275SEric Cheng /* ARGSUSED */
15498275SEric Cheng dladm_status_t
155010734SEric Cheng do_extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
15518275SEric Cheng {
155210734SEric Cheng 	mac_resource_props_t *mrp = arg;
15538275SEric Cheng 
15548275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
15558275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
15568275SEric Cheng 
15578275SEric Cheng 	return (DLADM_STATUS_OK);
15588275SEric Cheng }
15598275SEric Cheng 
15608275SEric Cheng /* ARGSUSED */
15618275SEric Cheng static dladm_status_t
15628460SArtem.Kachitchkin@Sun.COM i_dladm_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15638275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15648275SEric Cheng     uint_t flags, uint_t *perm_flags)
15658275SEric Cheng {
15668275SEric Cheng 	dld_ioc_macprop_t	*dip;
15678275SEric Cheng 	mac_resource_props_t	mrp;
15688275SEric Cheng 	int			i;
15698275SEric Cheng 	uint32_t		ncpus;
15708275SEric Cheng 	uchar_t			*cp;
15718275SEric Cheng 	dladm_status_t		status;
15728275SEric Cheng 
15738453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15748275SEric Cheng 	    &status, perm_flags);
15758275SEric Cheng 	if (dip == NULL)
15768275SEric Cheng 		return (status);
15778275SEric Cheng 
15788275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
15798275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
15808275SEric Cheng 	free(dip);
15818275SEric Cheng 
15828275SEric Cheng 	ncpus = mrp.mrp_ncpus;
15838275SEric Cheng 
15848275SEric Cheng 	if (ncpus > *val_cnt)
15858275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
15868275SEric Cheng 
15878275SEric Cheng 	if (ncpus == 0) {
15888275SEric Cheng 		(*prop_val)[0] = '\0';
15898275SEric Cheng 		*val_cnt = 1;
15908275SEric Cheng 		return (DLADM_STATUS_OK);
15918275SEric Cheng 	}
15928275SEric Cheng 
15938275SEric Cheng 	*val_cnt = ncpus;
15948275SEric Cheng 	for (i = 0; i < ncpus; i++) {
15958275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
15968275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
15978275SEric Cheng 	}
15988275SEric Cheng 	return (DLADM_STATUS_OK);
15998275SEric Cheng }
16008275SEric Cheng 
16018275SEric Cheng /* ARGSUSED */
16028275SEric Cheng static dladm_status_t
16038453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16048453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16058275SEric Cheng {
16068275SEric Cheng 	mac_resource_props_t	mrp;
16078275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
16088275SEric Cheng 	dld_ioc_macprop_t	*dip;
16098275SEric Cheng 
16108275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16118275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16128275SEric Cheng 	    flags, &status);
16138275SEric Cheng 
16148275SEric Cheng 	if (dip == NULL)
16158275SEric Cheng 		return (status);
16168275SEric Cheng 
16178275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
16188275SEric Cheng 		switch (dip->pr_num) {
16198275SEric Cheng 		case MAC_PROP_MAXBW:
16208275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
16218275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16228275SEric Cheng 			break;
16238275SEric Cheng 		case MAC_PROP_PRIO:
16248275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
16258275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16268275SEric Cheng 			break;
16278275SEric Cheng 		default:
16288275SEric Cheng 			free(dip);
16298275SEric Cheng 			return (DLADM_STATUS_BADARG);
16308275SEric Cheng 		}
16318275SEric Cheng 	} else {
16328275SEric Cheng 		switch (dip->pr_num) {
16338275SEric Cheng 		case MAC_PROP_MAXBW:
16348275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
16358275SEric Cheng 			    sizeof (uint64_t));
16368275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16378275SEric Cheng 			break;
16388275SEric Cheng 		case MAC_PROP_PRIO:
16398275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
16408275SEric Cheng 			    sizeof (mac_priority_level_t));
16418275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16428275SEric Cheng 			break;
16438275SEric Cheng 		default:
16448275SEric Cheng 			free(dip);
16458275SEric Cheng 			return (DLADM_STATUS_BADARG);
16468275SEric Cheng 		}
16478275SEric Cheng 	}
16488275SEric Cheng 
16498275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16508453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16518275SEric Cheng 	free(dip);
16528275SEric Cheng 	return (status);
16538275SEric Cheng }
16548275SEric Cheng 
16558275SEric Cheng /* ARGSUSED */
16568275SEric Cheng static dladm_status_t
16578453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16588453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16598275SEric Cheng {
16608275SEric Cheng 	mac_resource_props_t	mrp;
16618275SEric Cheng 	dladm_status_t		status;
16628275SEric Cheng 	dld_ioc_macprop_t	*dip;
16638275SEric Cheng 	datalink_class_t	class;
16648275SEric Cheng 
16658275SEric Cheng 	/*
16668275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
16678275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
16688275SEric Cheng 	 * the phys_info test only on physical links.
16698275SEric Cheng 	 */
16708453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
16718275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
16728275SEric Cheng 		return (status);
16738275SEric Cheng 	}
16748275SEric Cheng 
16758275SEric Cheng 	/*
16768275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
16778275SEric Cheng 	 * if possible when the setup is complete in MAC.
16788275SEric Cheng 	 */
16798275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16808275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
16818275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
16828275SEric Cheng 		mac_resource_props_t	*vmrp;
16838275SEric Cheng 
16848275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
16858275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
16868275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
16878275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
16888275SEric Cheng 		}
16898275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
16908275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
16918275SEric Cheng 		mrp.mrp_intr_cpu = -1;
16928275SEric Cheng 	}
16938275SEric Cheng 
16948275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16958275SEric Cheng 	    flags, &status);
16968275SEric Cheng 	if (dip == NULL)
16978275SEric Cheng 		return (status);
16988275SEric Cheng 
16998275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
17008453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
17018275SEric Cheng 	free(dip);
17028275SEric Cheng 	return (status);
17038275SEric Cheng }
17048275SEric Cheng 
17058275SEric Cheng /* ARGSUSED */
17068275SEric Cheng static dladm_status_t
17078453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17088453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17098275SEric Cheng {
17108275SEric Cheng 	uint32_t		cpuid;
17118275SEric Cheng 	int			i, j, rc;
17128275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
17138275SEric Cheng 	mac_resource_props_t	*mrp;
17148275SEric Cheng 
17158275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
17168275SEric Cheng 	if (mrp == NULL)
17178275SEric Cheng 		return (DLADM_STATUS_NOMEM);
17188275SEric Cheng 
17198275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17208275SEric Cheng 		errno = 0;
17218275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
17228275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
17238275SEric Cheng 			free(mrp);
17248275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
17258275SEric Cheng 		}
17268275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
17278275SEric Cheng 		if (rc < 1) {
17288275SEric Cheng 			free(mrp);
17298275SEric Cheng 			return (DLADM_STATUS_CPUERR);
17308275SEric Cheng 		}
17318275SEric Cheng 		if (rc != P_ONLINE) {
17328275SEric Cheng 			free(mrp);
17338275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
17348275SEric Cheng 		}
17358275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
17368275SEric Cheng 	}
17378275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
17388275SEric Cheng 
17398275SEric Cheng 	/* Check for duplicates */
17408275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17418275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
17428275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
17438275SEric Cheng 				free(mrp);
17448275SEric Cheng 				return (DLADM_STATUS_BADARG);
17458275SEric Cheng 			}
17468275SEric Cheng 		}
17478275SEric Cheng 	}
17488275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
17498275SEric Cheng 
17508275SEric Cheng 	return (DLADM_STATUS_OK);
17518275SEric Cheng }
17528275SEric Cheng 
17538275SEric Cheng /* ARGSUSED */
17548275SEric Cheng dladm_status_t
175510734SEric Cheng do_extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
17568275SEric Cheng {
175710734SEric Cheng 	mac_resource_props_t	*mrp = arg;
17588275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
17598275SEric Cheng 	int			i;
17608275SEric Cheng 
17618275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
17628275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
17638275SEric Cheng 	}
17648275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
17658275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
17668275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
17679055SMichael.Lim@Sun.COM 	mrp->mrp_intr_cpu = -1;
17688275SEric Cheng 
17698275SEric Cheng 	return (DLADM_STATUS_OK);
17708275SEric Cheng }
17718275SEric Cheng 
17728275SEric Cheng /* ARGSUSED */
17738275SEric Cheng static dladm_status_t
17748460SArtem.Kachitchkin@Sun.COM i_dladm_priority_get(dladm_handle_t handle, prop_desc_t *pdp,
17758460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
17768460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
17778275SEric Cheng {
17788275SEric Cheng 	dld_ioc_macprop_t	*dip;
17798275SEric Cheng 	mac_resource_props_t	mrp;
17808275SEric Cheng 	mac_priority_level_t	pri;
17818275SEric Cheng 	dladm_status_t		status;
17828275SEric Cheng 
17838453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
17848275SEric Cheng 	    &status, perm_flags);
17858275SEric Cheng 	if (dip == NULL)
17868275SEric Cheng 		return (status);
17878275SEric Cheng 
17888275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
17898275SEric Cheng 	free(dip);
17908275SEric Cheng 
17918275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
17928275SEric Cheng 	    mrp.mrp_priority;
17938275SEric Cheng 
17948275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
17958275SEric Cheng 	*val_cnt = 1;
17968275SEric Cheng 	return (DLADM_STATUS_OK);
17978275SEric Cheng }
17988275SEric Cheng 
17998275SEric Cheng /* ARGSUSED */
18008275SEric Cheng static dladm_status_t
18018453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18028453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
18038275SEric Cheng {
18048275SEric Cheng 	mac_priority_level_t	*pri;
18058275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
18068275SEric Cheng 
18078275SEric Cheng 	if (val_cnt != 1)
18088275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
18098275SEric Cheng 
18108275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
18118275SEric Cheng 	if (pri == NULL)
18128275SEric Cheng 		return (DLADM_STATUS_NOMEM);
18138275SEric Cheng 
18148275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
18158275SEric Cheng 	if (status != DLADM_STATUS_OK) {
18168275SEric Cheng 		free(pri);
18178275SEric Cheng 		return (status);
18188275SEric Cheng 	}
18198275SEric Cheng 
18208275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
18218275SEric Cheng 		free(pri);
18228275SEric Cheng 		return (DLADM_STATUS_BADVAL);
18238275SEric Cheng 	}
18248275SEric Cheng 
18258275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
18268275SEric Cheng 	return (DLADM_STATUS_OK);
18278275SEric Cheng }
18288275SEric Cheng 
18298275SEric Cheng /* ARGSUSED */
18308275SEric Cheng dladm_status_t
183110734SEric Cheng do_extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
18328275SEric Cheng {
183310734SEric Cheng 	mac_resource_props_t *mrp = arg;
18348275SEric Cheng 
18358275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
18368275SEric Cheng 	    sizeof (mac_priority_level_t));
18378275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
18388275SEric Cheng 
18398275SEric Cheng 	return (DLADM_STATUS_OK);
18408275SEric Cheng }
18418275SEric Cheng 
18428275SEric Cheng /* ARGSUSED */
18438275SEric Cheng static dladm_status_t
184410734SEric Cheng do_set_protection(dladm_handle_t handle, prop_desc_t *pdp,
184510734SEric Cheng     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
184610734SEric Cheng     uint_t flags, datalink_media_t media)
184710734SEric Cheng {
184810734SEric Cheng 	mac_resource_props_t	mrp;
184910734SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
185010734SEric Cheng 	dld_ioc_macprop_t	*dip;
185110734SEric Cheng 
185210734SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
185310734SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, "protection",
185410734SEric Cheng 	    flags, &status);
185510734SEric Cheng 
185610734SEric Cheng 	if (dip == NULL)
185710734SEric Cheng 		return (status);
185810734SEric Cheng 
185910734SEric Cheng 	if (strcmp(pdp->pd_name, "protection") == 0) {
186010734SEric Cheng 		status = do_extract_protection(vdp, val_cnt, &mrp);
186110734SEric Cheng 		if (status != DLADM_STATUS_OK)
186210734SEric Cheng 			goto done;
186310734SEric Cheng 
186410734SEric Cheng 	} else if (strcmp(pdp->pd_name, "allowed-ips") == 0) {
186510734SEric Cheng 		status = do_extract_allowedips(vdp, val_cnt, &mrp);
186610734SEric Cheng 		if (status != DLADM_STATUS_OK)
186710734SEric Cheng 			goto done;
186810734SEric Cheng 	} else {
186910734SEric Cheng 		status = DLADM_STATUS_BADARG;
187010734SEric Cheng 		goto done;
187110734SEric Cheng 	}
187210734SEric Cheng 
187310734SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
187410734SEric Cheng 	status = i_dladm_macprop(handle, dip, B_TRUE);
187510734SEric Cheng 
187610734SEric Cheng done:
187710734SEric Cheng 	free(dip);
187810734SEric Cheng 	return (status);
187910734SEric Cheng }
188010734SEric Cheng 
188110734SEric Cheng /* ARGSUSED */
188210734SEric Cheng static dladm_status_t
188310734SEric Cheng do_get_protection(dladm_handle_t handle, prop_desc_t *pdp,
188410734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
188510734SEric Cheng     datalink_media_t media, uint_t flags, uint_t *perm_flags)
188610734SEric Cheng {
188710734SEric Cheng 	dld_ioc_macprop_t	*dip;
188810734SEric Cheng 	mac_resource_props_t	mrp;
188910734SEric Cheng 	mac_protect_t		*p;
189010734SEric Cheng 	dladm_status_t		status;
189110734SEric Cheng 	int			i;
189210734SEric Cheng 
189310734SEric Cheng 	dip = i_dladm_get_public_prop(handle, linkid, "protection", flags,
189410734SEric Cheng 	    &status, perm_flags);
189510734SEric Cheng 	if (dip == NULL)
189610734SEric Cheng 		return (status);
189710734SEric Cheng 
189810734SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
189910734SEric Cheng 	free(dip);
190010734SEric Cheng 
190110734SEric Cheng 	p = &mrp.mrp_protect;
190210734SEric Cheng 	if ((mrp.mrp_mask & MRP_PROTECT) != 0 &&
190310734SEric Cheng 	    strcmp(pdp->pd_name, "protection") == 0) {
190410734SEric Cheng 		uint32_t	cnt = 0, setbits[32];
190510734SEric Cheng 
190610734SEric Cheng 		dladm_find_setbits32(p->mp_types, setbits, &cnt);
190710734SEric Cheng 		if (cnt > *val_cnt)
190810734SEric Cheng 			return (DLADM_STATUS_BADVALCNT);
190910734SEric Cheng 
191010734SEric Cheng 		for (i = 0; i < cnt; i++)
191110734SEric Cheng 			(void) dladm_protect2str(setbits[i], prop_val[i]);
191210734SEric Cheng 
191310734SEric Cheng 		*val_cnt = cnt;
191410734SEric Cheng 		return (DLADM_STATUS_OK);
191510734SEric Cheng 	}
191610734SEric Cheng 
191710734SEric Cheng 	if (p->mp_ipaddrcnt > 0 &&
191810734SEric Cheng 	    strcmp(pdp->pd_name, "allowed-ips") == 0) {
191910734SEric Cheng 		if (p->mp_ipaddrcnt > *val_cnt)
192010734SEric Cheng 			return (DLADM_STATUS_BADVALCNT);
192110734SEric Cheng 
192210734SEric Cheng 		for (i = 0; i < p->mp_ipaddrcnt; i++) {
192310734SEric Cheng 			(void) dladm_ipv4addr2str(&p->mp_ipaddrs[i],
192410734SEric Cheng 			    prop_val[i]);
192510734SEric Cheng 		}
192610734SEric Cheng 		*val_cnt = p->mp_ipaddrcnt;
192710734SEric Cheng 		return (DLADM_STATUS_OK);
192810734SEric Cheng 	}
192910734SEric Cheng 
193010734SEric Cheng 	*val_cnt = 0;
193110734SEric Cheng 	return (DLADM_STATUS_OK);
193210734SEric Cheng }
193310734SEric Cheng 
193410734SEric Cheng dladm_status_t
193510734SEric Cheng do_extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
193610734SEric Cheng {
193710734SEric Cheng 	mac_resource_props_t	*mrp = arg;
193810734SEric Cheng 	uint32_t		types = 0;
193910734SEric Cheng 	int			i;
194010734SEric Cheng 
194110734SEric Cheng 	for (i = 0; i < cnt; i++)
194210734SEric Cheng 		types |= (uint32_t)vdp[i].vd_val;
194310734SEric Cheng 
194410734SEric Cheng 	mrp->mrp_protect.mp_types = types;
194510734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
194610734SEric Cheng 	return (DLADM_STATUS_OK);
194710734SEric Cheng }
194810734SEric Cheng 
194910734SEric Cheng dladm_status_t
195010734SEric Cheng do_extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
195110734SEric Cheng {
195210734SEric Cheng 	mac_resource_props_t	*mrp = arg;
195310734SEric Cheng 	mac_protect_t		*p = &mrp->mrp_protect;
195410734SEric Cheng 	int			i;
195510734SEric Cheng 
195610734SEric Cheng 	if (vdp->vd_val == 0) {
195710734SEric Cheng 		cnt = (uint_t)-1;
195810734SEric Cheng 	} else {
195910734SEric Cheng 		for (i = 0; i < cnt; i++)
196010734SEric Cheng 			p->mp_ipaddrs[i] = (ipaddr_t)vdp[i].vd_val;
196110734SEric Cheng 	}
196210734SEric Cheng 	p->mp_ipaddrcnt = cnt;
196310734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
196410734SEric Cheng 	return (DLADM_STATUS_OK);
196510734SEric Cheng }
196610734SEric Cheng 
196710734SEric Cheng /* ARGSUSED */
196810734SEric Cheng static dladm_status_t
196910734SEric Cheng do_check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
197010734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t val_cnt,
197110734SEric Cheng     val_desc_t *vdp, datalink_media_t media)
197210734SEric Cheng {
197310734SEric Cheng 	dladm_status_t	status;
197410734SEric Cheng 	ipaddr_t	addr;
197510734SEric Cheng 	int		i;
197610734SEric Cheng 
197710734SEric Cheng 	if (val_cnt > MPT_MAXIPADDR)
197810734SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
197910734SEric Cheng 
198010734SEric Cheng 	for (i = 0; i < val_cnt; i++) {
198110734SEric Cheng 		status = dladm_str2ipv4addr(prop_val[i], &addr);
198210734SEric Cheng 		if (status != DLADM_STATUS_OK)
198310734SEric Cheng 			return (status);
198410734SEric Cheng 
198510734SEric Cheng 		if (addr == 0)
198610734SEric Cheng 			return (DLADM_STATUS_BADVAL);
198710734SEric Cheng 
198810734SEric Cheng 		vdp[i].vd_val = (uintptr_t)addr;
198910734SEric Cheng 	}
199010734SEric Cheng 	return (DLADM_STATUS_OK);
199110734SEric Cheng }
199210734SEric Cheng 
199310734SEric Cheng /* ARGSUSED */
199410734SEric Cheng static dladm_status_t
19958453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19968275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
19978275SEric Cheng     uint_t flags, uint_t *perm_flags)
19985895Syz147064 {
19997342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
20007342SAruna.Ramakrishna@Sun.COM 	int		i, len;
20017342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
20027342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
20035895Syz147064 
20046789Sam223141 	if (flags & MAC_PROP_DEFAULT)
20057776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
20066512Ssowmini 
20075895Syz147064 	*val_cnt = 1;
20088453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
20098275SEric Cheng 	    &status, perm_flags);
20107342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
20115895Syz147064 		(*prop_val)[0] = '\0';
20128275SEric Cheng 		return (DLADM_STATUS_OK);
20135895Syz147064 	}
20147342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
20155895Syz147064 
20167342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
20175895Syz147064 		if (i != 0) {
20185895Syz147064 			(void) snprintf(*prop_val + len,
20195895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
20205895Syz147064 			len += 1;
20215895Syz147064 		}
20225895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
20237342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
20247342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
20257342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
20265895Syz147064 			(void) snprintf(*prop_val + len,
20275895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
20285895Syz147064 			    AP_ANCHOR);
20295895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
20305895Syz147064 		}
20315895Syz147064 	}
20327342SAruna.Ramakrishna@Sun.COM 	free(dip);
20335895Syz147064 done:
20345895Syz147064 	return (DLADM_STATUS_OK);
20355895Syz147064 }
20365895Syz147064 
20375895Syz147064 /*
20385895Syz147064  * Add the specified module to the dlautopush structure; returns a
20395895Syz147064  * DLADM_STATUS_* code.
20405895Syz147064  */
20415895Syz147064 dladm_status_t
20425895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
20435895Syz147064 {
20445895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
20455895Syz147064 		return (DLADM_STATUS_BADVAL);
20465895Syz147064 
20475895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
20485895Syz147064 		/*
20495895Syz147064 		 * We don't allow multiple anchors, and the anchor must
20505895Syz147064 		 * be after at least one module.
20515895Syz147064 		 */
20525895Syz147064 		if (dlap->dap_anchor != 0)
20535895Syz147064 			return (DLADM_STATUS_BADVAL);
20545895Syz147064 		if (dlap->dap_npush == 0)
20555895Syz147064 			return (DLADM_STATUS_BADVAL);
20565895Syz147064 
20575895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
20585895Syz147064 		return (DLADM_STATUS_OK);
20595895Syz147064 	}
20608957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
20615895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20625895Syz147064 
20635895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
20645895Syz147064 	    FMNAMESZ + 1);
20655895Syz147064 
20665895Syz147064 	return (DLADM_STATUS_OK);
20675895Syz147064 }
20685895Syz147064 
20695895Syz147064 /*
20705895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
20715895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
20725895Syz147064  * latter is used in the autopush(1M) file.
20735895Syz147064  */
20745895Syz147064 /* ARGSUSED */
20755895Syz147064 static dladm_status_t
20768453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20778453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
20785895Syz147064 {
20795895Syz147064 	char			*module;
20805895Syz147064 	struct dlautopush	*dlap;
20815895Syz147064 	dladm_status_t		status;
20825895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
20835895Syz147064 	char			delimiters[4];
20845895Syz147064 
20855895Syz147064 	if (val_cnt != 1)
20865895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20875895Syz147064 
20887342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
20897342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
20907342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
20917342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
20923448Sdh155122 
20937342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
20947342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
20957342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
20967342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
20977342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
20987342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
20997342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
21007342SAruna.Ramakrishna@Sun.COM 				return (status);
21017342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
21027342SAruna.Ramakrishna@Sun.COM 		}
21037342SAruna.Ramakrishna@Sun.COM 
21047342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
21057342SAruna.Ramakrishna@Sun.COM 	} else {
21067342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
21075895Syz147064 	}
21083448Sdh155122 	return (DLADM_STATUS_OK);
21093448Sdh155122 }
21103448Sdh155122 
21117663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
21127663SSowmini.Varadhan@Sun.COM 
21135903Ssowmini /* ARGSUSED */
21143448Sdh155122 static dladm_status_t
21158453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
21168453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
21178453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
21183448Sdh155122 {
21195895Syz147064 	wl_rates_t	*wrp;
21205895Syz147064 	uint_t		i;
21215895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21225895Syz147064 
21237663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
21247663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
21257663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
21265895Syz147064 
21278453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
21288453SAnurag.Maskey@Sun.COM 	    B_FALSE);
21295895Syz147064 	if (status != DLADM_STATUS_OK)
21305895Syz147064 		goto done;
21315895Syz147064 
21325895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
21335895Syz147064 		status = DLADM_STATUS_TOOSMALL;
21345895Syz147064 		goto done;
21355895Syz147064 	}
21365895Syz147064 
21375895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
21385895Syz147064 		prop_val[0][0] = '\0';
21395895Syz147064 		*val_cnt = 1;
21405895Syz147064 		goto done;
21415895Syz147064 	}
21425895Syz147064 
21435895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
21445895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
21455895Syz147064 		    wrp->wl_rates_rates[i] % 2,
21465895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
21475895Syz147064 	}
21485895Syz147064 	*val_cnt = wrp->wl_rates_num;
21498275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
21503448Sdh155122 
21515895Syz147064 done:
21527663SSowmini.Varadhan@Sun.COM 	free(wrp);
21535895Syz147064 	return (status);
21545895Syz147064 }
21555895Syz147064 
21565895Syz147064 static dladm_status_t
21578453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21588275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
21598275SEric Cheng     uint_t flags, uint_t *perm_flags)
21605895Syz147064 {
21618118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
21628453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
21638275SEric Cheng 		    val_cnt, flags, perm_flags));
21648118SVasumathi.Sundaram@Sun.COM 	}
21655960Ssowmini 
21668453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
21678275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
21685895Syz147064 }
21695895Syz147064 
21706512Ssowmini /* ARGSUSED */
21715895Syz147064 static dladm_status_t
21728453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
21738275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
21748275SEric Cheng     uint_t flags, uint_t *perm_flags)
21755895Syz147064 {
21765960Ssowmini 	switch (media) {
21775960Ssowmini 	case DL_ETHER:
21786512Ssowmini 		/*
21796512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
21806512Ssowmini 		 * links can have a speed of 5.5 Gbps.
21816512Ssowmini 		 */
21826512Ssowmini 		return (DLADM_STATUS_NOTSUP);
21835960Ssowmini 
21845960Ssowmini 	case DL_WIFI:
21858453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
21868453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
21875960Ssowmini 	default:
21885960Ssowmini 		return (DLADM_STATUS_BADARG);
21895960Ssowmini 	}
21905895Syz147064 }
21915895Syz147064 
21925895Syz147064 static dladm_status_t
21938453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
21948453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
21955895Syz147064 {
21965895Syz147064 	int		i;
21975895Syz147064 	uint_t		len;
21985895Syz147064 	wl_rates_t	*wrp;
21995895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
22005895Syz147064 
22017663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
22027663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
22035895Syz147064 		return (DLADM_STATUS_NOMEM);
22045895Syz147064 
22057663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
22065895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
22075895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
22085895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
22095895Syz147064 
22105895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
22115895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
22128453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
22138453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
22145895Syz147064 
22157663SSowmini.Varadhan@Sun.COM 	free(wrp);
22165895Syz147064 	return (status);
22175895Syz147064 }
22183448Sdh155122 
22195903Ssowmini /* ARGSUSED */
22205895Syz147064 static dladm_status_t
22218453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22225960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
22235895Syz147064 {
22245895Syz147064 	dladm_wlan_rates_t	rates;
22255895Syz147064 	dladm_status_t		status;
22265895Syz147064 
22275960Ssowmini 	/*
22285960Ssowmini 	 * can currently set rate on WIFI links only.
22295960Ssowmini 	 */
22305960Ssowmini 	if (media != DL_WIFI)
22315960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
22325960Ssowmini 
22335895Syz147064 	if (val_cnt != 1)
22345895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22355895Syz147064 
22365895Syz147064 	rates.wr_cnt = 1;
22375895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
22385895Syz147064 
22398453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
22405895Syz147064 
22415895Syz147064 done:
22425895Syz147064 	return (status);
22435895Syz147064 }
22443448Sdh155122 
22455895Syz147064 /* ARGSUSED */
22465895Syz147064 static dladm_status_t
22478453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22488453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
22495895Syz147064 {
22505895Syz147064 	int		i;
22515895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
22525895Syz147064 	char		*buf, **modval;
22535895Syz147064 	dladm_status_t	status;
22548118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
22555895Syz147064 
22565895Syz147064 	if (val_cnt != 1)
22575895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22585895Syz147064 
22595895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
22605895Syz147064 	    MAX_SUPPORT_RATES);
22615895Syz147064 	if (buf == NULL) {
22625895Syz147064 		status = DLADM_STATUS_NOMEM;
22635895Syz147064 		goto done;
22645895Syz147064 	}
22653448Sdh155122 
22665895Syz147064 	modval = (char **)(void *)buf;
22675895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
22685895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
22695895Syz147064 		    i * DLADM_STRSIZE;
22705895Syz147064 	}
22715895Syz147064 
22728453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
22738453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
22745895Syz147064 	if (status != DLADM_STATUS_OK)
22755895Syz147064 		goto done;
22765895Syz147064 
22775895Syz147064 	for (i = 0; i < modval_cnt; i++) {
22785895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
22795903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
22805903Ssowmini 			    (atof(*prop_val) * 2);
22815895Syz147064 			status = DLADM_STATUS_OK;
22823448Sdh155122 			break;
22833448Sdh155122 		}
22845895Syz147064 	}
22855895Syz147064 	if (i == modval_cnt)
22865895Syz147064 		status = DLADM_STATUS_BADVAL;
22875895Syz147064 done:
22885895Syz147064 	free(buf);
22895895Syz147064 	return (status);
22905895Syz147064 }
22915895Syz147064 
22925895Syz147064 static dladm_status_t
22938453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
22948453SAnurag.Maskey@Sun.COM     int buflen)
22955895Syz147064 {
22968453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
22977663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
22985895Syz147064 }
22995895Syz147064 
23005903Ssowmini /* ARGSUSED */
23015895Syz147064 static dladm_status_t
23028453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
23038453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
23048453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23055895Syz147064 {
23065895Syz147064 	uint32_t	channel;
23077663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
23085895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
23097663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
23105895Syz147064 
23118453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
23127663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
23135895Syz147064 		goto done;
23145895Syz147064 
23157663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
23167663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
23175895Syz147064 		status = DLADM_STATUS_NOTFOUND;
23185895Syz147064 		goto done;
23195895Syz147064 	}
23205895Syz147064 
23215895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
23225895Syz147064 	*val_cnt = 1;
23238275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
23245895Syz147064 done:
23255895Syz147064 	return (status);
23265895Syz147064 }
23275895Syz147064 
23285895Syz147064 static dladm_status_t
23298453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
23308453SAnurag.Maskey@Sun.COM     int buflen)
23315895Syz147064 {
23328453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
23337663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
23345895Syz147064 }
23355895Syz147064 
23365903Ssowmini /* ARGSUSED */
23375895Syz147064 static dladm_status_t
23388453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
23398453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
23408453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
23415895Syz147064 {
23427663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
23435895Syz147064 	const char	*s;
23447663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
23455895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
23465895Syz147064 
23478453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
23487663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
23495895Syz147064 		goto done;
23505895Syz147064 
23517663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
23527663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
23535895Syz147064 	case WL_PM_AM:
23545895Syz147064 		s = "off";
23555895Syz147064 		break;
23565895Syz147064 	case WL_PM_MPS:
23575895Syz147064 		s = "max";
23585895Syz147064 		break;
23595895Syz147064 	case WL_PM_FAST:
23605895Syz147064 		s = "fast";
23613448Sdh155122 		break;
23623448Sdh155122 	default:
23635895Syz147064 		status = DLADM_STATUS_NOTFOUND;
23645895Syz147064 		goto done;
23655895Syz147064 	}
23665895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
23675895Syz147064 	*val_cnt = 1;
23688275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
23695895Syz147064 done:
23705895Syz147064 	return (status);
23715895Syz147064 }
23725895Syz147064 
23735895Syz147064 static dladm_status_t
23748453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
23758453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
23765895Syz147064 {
23775895Syz147064 	wl_ps_mode_t    ps_mode;
23785895Syz147064 
23795895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
23805895Syz147064 
23815895Syz147064 	switch (*pm) {
23825895Syz147064 	case DLADM_WLAN_PM_OFF:
23835895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
23843448Sdh155122 		break;
23855895Syz147064 	case DLADM_WLAN_PM_MAX:
23865895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
23875895Syz147064 		break;
23885895Syz147064 	case DLADM_WLAN_PM_FAST:
23895895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
23905895Syz147064 		break;
23915895Syz147064 	default:
23925895Syz147064 		return (DLADM_STATUS_NOTSUP);
23933448Sdh155122 	}
23948453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
23958453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
23965895Syz147064 }
23975895Syz147064 
23985895Syz147064 /* ARGSUSED */
23995895Syz147064 static dladm_status_t
24008453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
24018453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
24028453SAnurag.Maskey@Sun.COM     datalink_media_t media)
24035895Syz147064 {
24045895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
24055895Syz147064 	dladm_status_t status;
24065895Syz147064 
24075895Syz147064 	if (val_cnt != 1)
24085895Syz147064 		return (DLADM_STATUS_BADVALCNT);
24095895Syz147064 
24108453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
24113448Sdh155122 
24123448Sdh155122 	return (status);
24133448Sdh155122 }
24143448Sdh155122 
24153448Sdh155122 static dladm_status_t
24168453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
24173448Sdh155122 {
24188453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
24198453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
24205895Syz147064 }
24213448Sdh155122 
24225903Ssowmini /* ARGSUSED */
24235895Syz147064 static dladm_status_t
24248453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
24258275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
24268275SEric Cheng     uint_t flags, uint_t *perm_flags)
24275895Syz147064 {
24285895Syz147064 	wl_radio_t	radio;
24295895Syz147064 	const char	*s;
24307663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
24315895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
24323448Sdh155122 
24338453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
24347663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
24355895Syz147064 		goto done;
24363448Sdh155122 
24377663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
24385895Syz147064 	switch (radio) {
24395895Syz147064 	case B_TRUE:
24405895Syz147064 		s = "on";
24415895Syz147064 		break;
24425895Syz147064 	case B_FALSE:
24435895Syz147064 		s = "off";
24445895Syz147064 		break;
24455895Syz147064 	default:
24465895Syz147064 		status = DLADM_STATUS_NOTFOUND;
24475895Syz147064 		goto done;
24485895Syz147064 	}
24495895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
24505895Syz147064 	*val_cnt = 1;
24518275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
24525895Syz147064 done:
24533448Sdh155122 	return (status);
24543448Sdh155122 }
24553448Sdh155122 
24563448Sdh155122 static dladm_status_t
24578453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
24588453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
24593448Sdh155122 {
24605895Syz147064 	wl_radio_t r;
24613448Sdh155122 
24625895Syz147064 	switch (*radio) {
24635895Syz147064 	case DLADM_WLAN_RADIO_ON:
24645895Syz147064 		r = B_TRUE;
24655895Syz147064 		break;
24665895Syz147064 	case DLADM_WLAN_RADIO_OFF:
24675895Syz147064 		r = B_FALSE;
24685895Syz147064 		break;
24695895Syz147064 	default:
24705895Syz147064 		return (DLADM_STATUS_NOTSUP);
24715895Syz147064 	}
24728453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
24737663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
24745895Syz147064 }
24753448Sdh155122 
24765895Syz147064 /* ARGSUSED */
24775895Syz147064 static dladm_status_t
24788453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
247910616SSebastien.Roy@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
24805895Syz147064 {
24815895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
24825895Syz147064 	dladm_status_t status;
24833448Sdh155122 
24845895Syz147064 	if (val_cnt != 1)
24855895Syz147064 		return (DLADM_STATUS_BADVALCNT);
24865895Syz147064 
24878453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
24883448Sdh155122 
24893448Sdh155122 	return (status);
24903448Sdh155122 }
24913448Sdh155122 
249210616SSebastien.Roy@Sun.COM /* ARGSUSED */
249310616SSebastien.Roy@Sun.COM static dladm_status_t
249410616SSebastien.Roy@Sun.COM do_check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
249510616SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
249610616SSebastien.Roy@Sun.COM     datalink_media_t media)
249710616SSebastien.Roy@Sun.COM {
249810616SSebastien.Roy@Sun.COM 	int32_t	hlim;
249910616SSebastien.Roy@Sun.COM 	char	*ep;
250010616SSebastien.Roy@Sun.COM 
250110616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
250210616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
250310616SSebastien.Roy@Sun.COM 
250410616SSebastien.Roy@Sun.COM 	errno = 0;
250510616SSebastien.Roy@Sun.COM 	hlim = strtol(*prop_val, &ep, 10);
250610616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || hlim < 1 ||
250710616SSebastien.Roy@Sun.COM 	    hlim > (int32_t)UINT8_MAX)
250810616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
250910616SSebastien.Roy@Sun.COM 	vdp->vd_val = hlim;
251010616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
251110616SSebastien.Roy@Sun.COM }
251210616SSebastien.Roy@Sun.COM 
251310616SSebastien.Roy@Sun.COM /* ARGSUSED */
251410616SSebastien.Roy@Sun.COM static dladm_status_t
251510616SSebastien.Roy@Sun.COM do_check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
251610616SSebastien.Roy@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
251710616SSebastien.Roy@Sun.COM {
251810616SSebastien.Roy@Sun.COM 	int32_t	elim;
251910616SSebastien.Roy@Sun.COM 	char	*ep;
252010616SSebastien.Roy@Sun.COM 
252110616SSebastien.Roy@Sun.COM 	if (media != DL_IPV6)
252210616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADARG);
252310616SSebastien.Roy@Sun.COM 
252410616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
252510616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
252610616SSebastien.Roy@Sun.COM 
252710616SSebastien.Roy@Sun.COM 	errno = 0;
252810616SSebastien.Roy@Sun.COM 	elim = strtol(*prop_val, &ep, 10);
252910616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || elim < 0 ||
253010616SSebastien.Roy@Sun.COM 	    elim > (int32_t)UINT8_MAX)
253110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
253210616SSebastien.Roy@Sun.COM 	vdp->vd_val = elim;
253310616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
253410616SSebastien.Roy@Sun.COM }
253510616SSebastien.Roy@Sun.COM 
25365895Syz147064 static dladm_status_t
25378453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
25388453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
25393448Sdh155122 {
25405895Syz147064 	char		buf[MAXLINELEN];
25415895Syz147064 	int		i;
25425895Syz147064 	dladm_conf_t	conf;
25435895Syz147064 	dladm_status_t	status;
25443448Sdh155122 
25458453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
25465895Syz147064 	if (status != DLADM_STATUS_OK)
25475895Syz147064 		return (status);
25483448Sdh155122 
25495895Syz147064 	/*
25505895Syz147064 	 * reset case.
25515895Syz147064 	 */
25525895Syz147064 	if (val_cnt == 0) {
25538453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
25545895Syz147064 		if (status == DLADM_STATUS_OK)
25558453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
25565895Syz147064 		goto done;
25575895Syz147064 	}
25583448Sdh155122 
25595895Syz147064 	buf[0] = '\0';
25605895Syz147064 	for (i = 0; i < val_cnt; i++) {
25615895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
25625895Syz147064 		if (i != val_cnt - 1)
25635895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
25643448Sdh155122 	}
25653448Sdh155122 
25668453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
25678453SAnurag.Maskey@Sun.COM 	    buf);
25685895Syz147064 	if (status == DLADM_STATUS_OK)
25698453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
25705895Syz147064 
25715895Syz147064 done:
25728453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
25735895Syz147064 	return (status);
25743448Sdh155122 }
25755895Syz147064 
25765895Syz147064 static dladm_status_t
25778453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
25788453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
25795895Syz147064 {
25805895Syz147064 	char		buf[MAXLINELEN], *str;
25815895Syz147064 	uint_t		cnt = 0;
25825895Syz147064 	dladm_conf_t	conf;
25835895Syz147064 	dladm_status_t	status;
25845895Syz147064 
25858453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
25865895Syz147064 	if (status != DLADM_STATUS_OK)
25875895Syz147064 		return (status);
25885895Syz147064 
25898453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
25905895Syz147064 	if (status != DLADM_STATUS_OK)
25915895Syz147064 		goto done;
25925895Syz147064 
25935895Syz147064 	str = strtok(buf, ",");
25945895Syz147064 	while (str != NULL) {
25955895Syz147064 		if (cnt == *val_cntp) {
25965895Syz147064 			status = DLADM_STATUS_TOOSMALL;
25975895Syz147064 			goto done;
25985895Syz147064 		}
25995895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
26005895Syz147064 		str = strtok(NULL, ",");
26015895Syz147064 	}
26025895Syz147064 
26035895Syz147064 	*val_cntp = cnt;
26045895Syz147064 
26055895Syz147064 done:
26068453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
26075895Syz147064 	return (status);
26085895Syz147064 }
26095903Ssowmini 
26108460SArtem.Kachitchkin@Sun.COM /*
26118460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
26128460SArtem.Kachitchkin@Sun.COM  */
26138460SArtem.Kachitchkin@Sun.COM static dladm_status_t
26148460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
26158460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
26168460SArtem.Kachitchkin@Sun.COM {
26178460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
26188460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
26198460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
26208460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
26218460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
26228460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
26238460SArtem.Kachitchkin@Sun.COM 
26248460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
26258460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
26268460SArtem.Kachitchkin@Sun.COM 
26278460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
26288460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
26298460SArtem.Kachitchkin@Sun.COM 		return (status);
26308460SArtem.Kachitchkin@Sun.COM 
26318460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
26328460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
26338460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
26348460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
26358460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
26368460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
26378460SArtem.Kachitchkin@Sun.COM 				break;
26388460SArtem.Kachitchkin@Sun.COM 		}
26398460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
26408460SArtem.Kachitchkin@Sun.COM 	}
26418460SArtem.Kachitchkin@Sun.COM 
26428460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
26438460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
26448460SArtem.Kachitchkin@Sun.COM }
26458460SArtem.Kachitchkin@Sun.COM 
26467663SSowmini.Varadhan@Sun.COM static link_attr_t *
26475903Ssowmini dladm_name2prop(const char *prop_name)
26485903Ssowmini {
26497663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
26505903Ssowmini 
26517663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
26525903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
26535903Ssowmini 			break;
26545903Ssowmini 	}
26555903Ssowmini 	return (p);
26565903Ssowmini }
26575903Ssowmini 
26587663SSowmini.Varadhan@Sun.COM static link_attr_t *
26597663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
26607663SSowmini.Varadhan@Sun.COM {
26617663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
26627663SSowmini.Varadhan@Sun.COM 
26637663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
26647663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
26657663SSowmini.Varadhan@Sun.COM 			break;
26667663SSowmini.Varadhan@Sun.COM 	}
26677663SSowmini.Varadhan@Sun.COM 	return (p);
26687663SSowmini.Varadhan@Sun.COM }
26695903Ssowmini 
26706789Sam223141 static dld_ioc_macprop_t *
26717663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
26727663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
26737663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
26745903Ssowmini {
26755903Ssowmini 	int dsize;
26766789Sam223141 	dld_ioc_macprop_t *dip;
26775903Ssowmini 
26785903Ssowmini 	*status = DLADM_STATUS_OK;
26796789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
26805903Ssowmini 	dip = malloc(dsize);
26815903Ssowmini 	if (dip == NULL) {
26825903Ssowmini 		*status = DLADM_STATUS_NOMEM;
26835903Ssowmini 		return (NULL);
26845903Ssowmini 	}
26855903Ssowmini 	bzero(dip, dsize);
26865903Ssowmini 	dip->pr_valsize = valsize;
26876512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
26886789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
26895960Ssowmini 	dip->pr_linkid = linkid;
26907663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
26916512Ssowmini 	dip->pr_flags = flags;
26925903Ssowmini 	return (dip);
26935903Ssowmini }
26945903Ssowmini 
26957663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
26967663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
26977663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
26987663SSowmini.Varadhan@Sun.COM {
26997663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
27007663SSowmini.Varadhan@Sun.COM 
27017663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
27027663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
27037663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
27047663SSowmini.Varadhan@Sun.COM 	    flags, status));
27057663SSowmini.Varadhan@Sun.COM }
27067663SSowmini.Varadhan@Sun.COM 
27077663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
27087663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
27097663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
27107663SSowmini.Varadhan@Sun.COM {
27117663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
27127663SSowmini.Varadhan@Sun.COM 
27137663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
27147663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
27157663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
27167663SSowmini.Varadhan@Sun.COM 	    flags, status));
27177663SSowmini.Varadhan@Sun.COM }
27187663SSowmini.Varadhan@Sun.COM 
27195903Ssowmini /* ARGSUSED */
27205903Ssowmini static dladm_status_t
27218453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
27228453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
27238453SAnurag.Maskey@Sun.COM     datalink_media_t media)
27245903Ssowmini {
27256789Sam223141 	dld_ioc_macprop_t	*dip;
27265903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
27275903Ssowmini 	uint8_t		u8;
27285903Ssowmini 	uint16_t	u16;
27295903Ssowmini 	uint32_t	u32;
27305903Ssowmini 	void		*val;
27315903Ssowmini 
27328275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
27335903Ssowmini 	if (dip == NULL)
27345903Ssowmini 		return (status);
27355903Ssowmini 
27368275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
27375903Ssowmini 		val = (void *)vdp->vd_val;
27385903Ssowmini 	else {
27395903Ssowmini 		/*
27405903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
27415903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
27425903Ssowmini 		 */
27435903Ssowmini 		switch (dip->pr_valsize) {
27445903Ssowmini 		case 1:
27455903Ssowmini 			u8 = vdp->vd_val;
27465903Ssowmini 			val = &u8;
27475903Ssowmini 			break;
27485903Ssowmini 		case 2:
27495903Ssowmini 			u16 = vdp->vd_val;
27505903Ssowmini 			val = &u16;
27515903Ssowmini 			break;
27525903Ssowmini 		case 4:
27535903Ssowmini 			u32 = vdp->vd_val;
27545903Ssowmini 			val = &u32;
27555903Ssowmini 			break;
27565903Ssowmini 		default:
27575903Ssowmini 			val = &vdp->vd_val;
27585903Ssowmini 			break;
27595903Ssowmini 		}
27605903Ssowmini 	}
27615903Ssowmini 
27627342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
27637342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
27647342SAruna.Ramakrishna@Sun.COM 	else
27657342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
27667342SAruna.Ramakrishna@Sun.COM 
27678453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
27687663SSowmini.Varadhan@Sun.COM 
27697663SSowmini.Varadhan@Sun.COM done:
27707663SSowmini.Varadhan@Sun.COM 	free(dip);
27717663SSowmini.Varadhan@Sun.COM 	return (status);
27727663SSowmini.Varadhan@Sun.COM }
27737663SSowmini.Varadhan@Sun.COM 
27747663SSowmini.Varadhan@Sun.COM dladm_status_t
27758453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
27767663SSowmini.Varadhan@Sun.COM {
27777663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
27787663SSowmini.Varadhan@Sun.COM 
27798453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
27808453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
27815903Ssowmini 		status = dladm_errno2status(errno);
27828453SAnurag.Maskey@Sun.COM 
27835903Ssowmini 	return (status);
27845903Ssowmini }
27855903Ssowmini 
27866789Sam223141 static dld_ioc_macprop_t *
27878453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
27888453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
27895903Ssowmini {
27906789Sam223141 	dld_ioc_macprop_t *dip = NULL;
27916512Ssowmini 
27927663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
27936512Ssowmini 	if (dip == NULL)
27946512Ssowmini 		return (NULL);
27955903Ssowmini 
27968453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
27976512Ssowmini 	if (*status != DLADM_STATUS_OK) {
27986512Ssowmini 		free(dip);
27996512Ssowmini 		return (NULL);
28006512Ssowmini 	}
28018275SEric Cheng 	if (perm_flags != NULL)
28028275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
28038275SEric Cheng 
28046512Ssowmini 	return (dip);
28055903Ssowmini }
28065903Ssowmini 
28075903Ssowmini /* ARGSUSED */
28085903Ssowmini static dladm_status_t
280910491SRishi.Srivatsavai@Sun.COM i_dladm_uint32_check(dladm_handle_t handle, prop_desc_t *pdp,
28108453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
28118453SAnurag.Maskey@Sun.COM     datalink_media_t media)
28125903Ssowmini {
28135903Ssowmini 	if (val_cnt != 1)
28145903Ssowmini 		return (DLADM_STATUS_BADVAL);
281510491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
28165903Ssowmini 	return (DLADM_STATUS_OK);
28175903Ssowmini }
28185903Ssowmini 
28195903Ssowmini /* ARGSUSED */
28205903Ssowmini static dladm_status_t
28218453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
28228453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28238453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28245903Ssowmini {
28255903Ssowmini 	link_duplex_t   link_duplex;
28265903Ssowmini 	dladm_status_t  status;
28275903Ssowmini 
28288453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
28295903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
28305903Ssowmini 		return (status);
28315903Ssowmini 
28325903Ssowmini 	switch (link_duplex) {
28335903Ssowmini 	case LINK_DUPLEX_FULL:
28345903Ssowmini 		(void) strcpy(*prop_val, "full");
28355903Ssowmini 		break;
28365903Ssowmini 	case LINK_DUPLEX_HALF:
28375903Ssowmini 		(void) strcpy(*prop_val, "half");
28385903Ssowmini 		break;
28395903Ssowmini 	default:
28405903Ssowmini 		(void) strcpy(*prop_val, "unknown");
28415903Ssowmini 		break;
28425903Ssowmini 	}
28435903Ssowmini 	*val_cnt = 1;
28445903Ssowmini 	return (DLADM_STATUS_OK);
28455903Ssowmini }
28465903Ssowmini 
28475903Ssowmini /* ARGSUSED */
28485903Ssowmini static dladm_status_t
28498453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
28508275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
28515903Ssowmini {
28525903Ssowmini 	uint64_t	ifspeed = 0;
28535903Ssowmini 	dladm_status_t status;
28545903Ssowmini 
28558453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
28565903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
28575903Ssowmini 		return (status);
28586512Ssowmini 
28595960Ssowmini 	if ((ifspeed % 1000000) != 0) {
28605960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
28615960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
28625960Ssowmini 	} else {
28635960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
28645960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
28655960Ssowmini 	}
28665903Ssowmini 	*val_cnt = 1;
28678275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
28685903Ssowmini 	return (DLADM_STATUS_OK);
28695903Ssowmini }
28705903Ssowmini 
28715903Ssowmini /* ARGSUSED */
28725903Ssowmini static dladm_status_t
28738453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
28748453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28758453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28765903Ssowmini {
28778275SEric Cheng 	link_state_t		link_state;
28788275SEric Cheng 	dladm_status_t		status;
28798306SSowmini.Varadhan@Sun.COM 
28808453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
28816512Ssowmini 	if (status != DLADM_STATUS_OK)
28825903Ssowmini 		return (status);
28838275SEric Cheng 
28845903Ssowmini 	switch (link_state) {
28855903Ssowmini 	case LINK_STATE_UP:
28865903Ssowmini 		(void) strcpy(*prop_val, "up");
28875903Ssowmini 		break;
28885903Ssowmini 	case LINK_STATE_DOWN:
28895903Ssowmini 		(void) strcpy(*prop_val, "down");
28905903Ssowmini 		break;
28915903Ssowmini 	default:
28925903Ssowmini 		(void) strcpy(*prop_val, "unknown");
28935903Ssowmini 		break;
28945903Ssowmini 	}
28955903Ssowmini 	*val_cnt = 1;
28968306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
28975903Ssowmini 	return (DLADM_STATUS_OK);
28985903Ssowmini }
28995903Ssowmini 
29005903Ssowmini /* ARGSUSED */
29015903Ssowmini static dladm_status_t
29028453SAnurag.Maskey@Sun.COM i_dladm_binary_get(dladm_handle_t handle, prop_desc_t *pdp,
29038453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29048453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29055903Ssowmini {
29066789Sam223141 	dld_ioc_macprop_t *dip;
29075903Ssowmini 	dladm_status_t status;
29085903Ssowmini 
29098453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29108275SEric Cheng 	    &status, perm_flags);
29116512Ssowmini 	if (dip == NULL)
29125903Ssowmini 		return (status);
29138275SEric Cheng 
29145903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
29155903Ssowmini 	free(dip);
29165903Ssowmini 	*val_cnt = 1;
29175903Ssowmini 	return (DLADM_STATUS_OK);
29185903Ssowmini }
29195903Ssowmini 
29205960Ssowmini /* ARGSUSED */
29215903Ssowmini static dladm_status_t
29228453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
29238453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29248453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29255903Ssowmini {
29266789Sam223141 	dld_ioc_macprop_t *dip;
29278275SEric Cheng 	uint32_t v = 0;
29285903Ssowmini 	uchar_t *cp;
29295903Ssowmini 	dladm_status_t status;
29305903Ssowmini 
29318453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29328275SEric Cheng 	    &status, perm_flags);
29336512Ssowmini 	if (dip == NULL)
29345903Ssowmini 		return (status);
29358275SEric Cheng 
29365903Ssowmini 	cp = (uchar_t *)dip->pr_val;
29375903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
29386512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
29395903Ssowmini 	free(dip);
29405903Ssowmini 	*val_cnt = 1;
29415903Ssowmini 	return (DLADM_STATUS_OK);
29425903Ssowmini }
29435903Ssowmini 
29449514SGirish.Moodalbail@Sun.COM /*
29459514SGirish.Moodalbail@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
29469514SGirish.Moodalbail@Sun.COM  * for retrieving the property range values.
29479514SGirish.Moodalbail@Sun.COM  */
29489514SGirish.Moodalbail@Sun.COM static int
29499514SGirish.Moodalbail@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
29509514SGirish.Moodalbail@Sun.COM {
29519514SGirish.Moodalbail@Sun.COM 	uint_t count = r->mpr_count;
29529514SGirish.Moodalbail@Sun.COM 
29539514SGirish.Moodalbail@Sun.COM 	*sz = sizeof (mac_propval_range_t);
29549514SGirish.Moodalbail@Sun.COM 	--count;
29559514SGirish.Moodalbail@Sun.COM 
29569514SGirish.Moodalbail@Sun.COM 	switch (r->mpr_type) {
29579514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32:
29589514SGirish.Moodalbail@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
29599514SGirish.Moodalbail@Sun.COM 		return (0);
29609514SGirish.Moodalbail@Sun.COM 	default:
29619514SGirish.Moodalbail@Sun.COM 		break;
29629514SGirish.Moodalbail@Sun.COM 	}
29639514SGirish.Moodalbail@Sun.COM 	*sz = 0;
29649514SGirish.Moodalbail@Sun.COM 	return (EINVAL);
29659514SGirish.Moodalbail@Sun.COM }
29669514SGirish.Moodalbail@Sun.COM 
29679514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
29689514SGirish.Moodalbail@Sun.COM static dladm_status_t
29699514SGirish.Moodalbail@Sun.COM i_dladm_range_get(dladm_handle_t handle, prop_desc_t *pdp,
29709514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
29719514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
29729514SGirish.Moodalbail@Sun.COM {
29739514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
29749514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
29759514SGirish.Moodalbail@Sun.COM 	size_t	sz;
29769514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
29779514SGirish.Moodalbail@Sun.COM 
29789514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
29799514SGirish.Moodalbail@Sun.COM 
29809514SGirish.Moodalbail@Sun.COM 	/*
29819514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
29829514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
29839514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
29849514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
29859514SGirish.Moodalbail@Sun.COM 	 */
29869514SGirish.Moodalbail@Sun.COM retry:
29879514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
29889514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
29899514SGirish.Moodalbail@Sun.COM 		return (status);
29909514SGirish.Moodalbail@Sun.COM 
29919514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
29929514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
29939514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
29949514SGirish.Moodalbail@Sun.COM 			int err;
29959514SGirish.Moodalbail@Sun.COM 
29969514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
29979514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
29989514SGirish.Moodalbail@Sun.COM 				free(dip);
29999514SGirish.Moodalbail@Sun.COM 				goto retry;
30009514SGirish.Moodalbail@Sun.COM 			} else {
30019514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
30029514SGirish.Moodalbail@Sun.COM 			}
30039514SGirish.Moodalbail@Sun.COM 		}
30049514SGirish.Moodalbail@Sun.COM 		free(dip);
30059514SGirish.Moodalbail@Sun.COM 		return (status);
30069514SGirish.Moodalbail@Sun.COM 	}
30079514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
30089514SGirish.Moodalbail@Sun.COM 
30099514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
30109514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
30119514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
30129514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
30139514SGirish.Moodalbail@Sun.COM 
30149514SGirish.Moodalbail@Sun.COM 		ur = &rangep->range_uint32[0];
30159514SGirish.Moodalbail@Sun.COM 
30169514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
30179514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
30189514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
30199514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
30209514SGirish.Moodalbail@Sun.COM 			} else {
30219514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
30229514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
30239514SGirish.Moodalbail@Sun.COM 			}
30249514SGirish.Moodalbail@Sun.COM 		}
30259514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
30269514SGirish.Moodalbail@Sun.COM 		break;
30279514SGirish.Moodalbail@Sun.COM 	}
30289514SGirish.Moodalbail@Sun.COM 	default:
30299514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
30309514SGirish.Moodalbail@Sun.COM 		break;
30319514SGirish.Moodalbail@Sun.COM 	}
30329514SGirish.Moodalbail@Sun.COM 	free(dip);
30339514SGirish.Moodalbail@Sun.COM 	return (status);
30349514SGirish.Moodalbail@Sun.COM }
30359514SGirish.Moodalbail@Sun.COM 
30365960Ssowmini /* ARGSUSED */
30375903Ssowmini static dladm_status_t
30388874SSebastien.Roy@Sun.COM i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
30398874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30408874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30418874SSebastien.Roy@Sun.COM {
30428874SSebastien.Roy@Sun.COM 	dld_ioc_macprop_t	*dip;
30438874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
30448874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
30458874SSebastien.Roy@Sun.COM 
30468874SSebastien.Roy@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
30478874SSebastien.Roy@Sun.COM 	    &status, perm_flags);
30488874SSebastien.Roy@Sun.COM 	if (dip == NULL)
30498874SSebastien.Roy@Sun.COM 		return (status);
30508874SSebastien.Roy@Sun.COM 	(void) memcpy(&mode, dip->pr_val, sizeof (mode));
30518874SSebastien.Roy@Sun.COM 	free(dip);
30528874SSebastien.Roy@Sun.COM 
30538874SSebastien.Roy@Sun.COM 	switch (mode) {
30548874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
30558874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
30568874SSebastien.Roy@Sun.COM 		break;
30578874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
30588874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
30598874SSebastien.Roy@Sun.COM 		break;
30608874SSebastien.Roy@Sun.COM 	default:
30618874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
30628874SSebastien.Roy@Sun.COM 	}
30638874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
30648874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
30658874SSebastien.Roy@Sun.COM }
30668874SSebastien.Roy@Sun.COM 
30678874SSebastien.Roy@Sun.COM /* ARGSUSED */
30688874SSebastien.Roy@Sun.COM static dladm_status_t
30698453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
30708453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30718453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30725903Ssowmini {
30736789Sam223141 	dld_ioc_macprop_t *dip;
30745903Ssowmini 	link_flowctrl_t v;
30755903Ssowmini 	dladm_status_t status;
30765903Ssowmini 	uchar_t *cp;
30775903Ssowmini 
30788453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
30798275SEric Cheng 	    &status, perm_flags);
30806512Ssowmini 	if (dip == NULL)
30815903Ssowmini 		return (status);
30828275SEric Cheng 
30835903Ssowmini 	cp = (uchar_t *)dip->pr_val;
30845903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
30855903Ssowmini 	switch (v) {
30865903Ssowmini 	case LINK_FLOWCTRL_NONE:
30875903Ssowmini 		(void) sprintf(*prop_val, "no");
30885903Ssowmini 		break;
30895903Ssowmini 	case LINK_FLOWCTRL_RX:
30905903Ssowmini 		(void) sprintf(*prop_val, "rx");
30915903Ssowmini 		break;
30925903Ssowmini 	case LINK_FLOWCTRL_TX:
30935903Ssowmini 		(void) sprintf(*prop_val, "tx");
30945903Ssowmini 		break;
30955903Ssowmini 	case LINK_FLOWCTRL_BI:
30965903Ssowmini 		(void) sprintf(*prop_val, "bi");
30975903Ssowmini 		break;
30985903Ssowmini 	}
30995903Ssowmini 	free(dip);
31005903Ssowmini 	*val_cnt = 1;
31015903Ssowmini 	return (DLADM_STATUS_OK);
31025903Ssowmini }
31035903Ssowmini 
31045903Ssowmini 
31055903Ssowmini /* ARGSUSED */
31065903Ssowmini static dladm_status_t
31079692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
31088453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
31098453SAnurag.Maskey@Sun.COM 
31105903Ssowmini {
31117663SSowmini.Varadhan@Sun.COM 	int		i, slen;
31127408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
31136789Sam223141 	dld_ioc_macprop_t *dip = NULL;
31145903Ssowmini 	uchar_t 	*dp;
31157663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
31166512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
31175903Ssowmini 
31185903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
31195903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
31205903Ssowmini 		return (DLADM_STATUS_BADARG);
31215903Ssowmini 	p = dladm_name2prop(prop_name);
31226789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
31235903Ssowmini 		return (DLADM_STATUS_BADARG);
31245903Ssowmini 
31259692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
31269692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
31279692SRishi.Srivatsavai@Sun.COM 
31285903Ssowmini 	/*
31295903Ssowmini 	 * private properties: all parsing is done in the kernel.
31305903Ssowmini 	 * allocate a enough space for each property + its separator (',').
31315903Ssowmini 	 */
31325903Ssowmini 	for (i = 0; i < val_cnt; i++) {
31335903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
31345903Ssowmini 	}
31356512Ssowmini 
31366512Ssowmini 	if (prop_val == NULL) {
31376512Ssowmini 		/*
31386512Ssowmini 		 * getting default value. so use more buffer space.
31396512Ssowmini 		 */
31407663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
31416512Ssowmini 	}
31426512Ssowmini 
31437663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
31446789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
31455903Ssowmini 	if (dip == NULL)
31465903Ssowmini 		return (status);
31475903Ssowmini 
31485903Ssowmini 	dp = (uchar_t *)dip->pr_val;
31495903Ssowmini 	slen = 0;
31507663SSowmini.Varadhan@Sun.COM 
31516512Ssowmini 	if (prop_val == NULL) {
31528453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
31538460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
31546512Ssowmini 	} else {
31556512Ssowmini 		for (i = 0; i < val_cnt; i++) {
31566512Ssowmini 			int plen = 0;
31575903Ssowmini 
31586512Ssowmini 			plen = strlen(prop_val[i]);
31596512Ssowmini 			bcopy(prop_val[i], dp, plen);
31606512Ssowmini 			slen += plen;
31616512Ssowmini 			/*
31626512Ssowmini 			 * add a "," separator and update dp.
31636512Ssowmini 			 */
31646512Ssowmini 			if (i != (val_cnt -1))
31656512Ssowmini 				dp[slen++] = ',';
31666512Ssowmini 			dp += (plen + 1);
31676512Ssowmini 		}
31688460SArtem.Kachitchkin@Sun.COM 	}
31698460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
31708453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
31716512Ssowmini 
31725903Ssowmini 	free(dip);
31736512Ssowmini 	return (status);
31745903Ssowmini }
31755903Ssowmini 
31765903Ssowmini static dladm_status_t
31778460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
31788453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
31798453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
31805903Ssowmini {
31817663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
31826789Sam223141 	dld_ioc_macprop_t *dip = NULL;
31837663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
31845903Ssowmini 
31855903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
31865903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
31875903Ssowmini 		return (DLADM_STATUS_BADARG);
31885903Ssowmini 
31895903Ssowmini 	p = dladm_name2prop(prop_name);
31906789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
31915903Ssowmini 		return (DLADM_STATUS_BADARG);
31925903Ssowmini 
31935903Ssowmini 	/*
31945903Ssowmini 	 * private properties: all parsing is done in the kernel.
31955903Ssowmini 	 */
31967663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
31977663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
31985903Ssowmini 	if (dip == NULL)
31995903Ssowmini 		return (status);
32005903Ssowmini 
32018453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
32028453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
32038118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
32048275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
32058460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
32068460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
32078118SVasumathi.Sundaram@Sun.COM 		} else {
32088118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
32098118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
32108118SVasumathi.Sundaram@Sun.COM 		}
32115903Ssowmini 		*val_cnt = 1;
32128460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
32138460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
32148460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
32155903Ssowmini 	}
32166512Ssowmini 	free(dip);
32175903Ssowmini 	return (status);
32185903Ssowmini }
32196512Ssowmini 
32206512Ssowmini 
32216512Ssowmini static dladm_status_t
32228453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
32238453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
32246512Ssowmini {
32256512Ssowmini 	dladm_status_t status;
32266512Ssowmini 	char **prop_vals = NULL, *buf;
32276512Ssowmini 	size_t bufsize;
32286512Ssowmini 	uint_t cnt;
32296512Ssowmini 	int i;
32308118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
32316512Ssowmini 
32326512Ssowmini 	/*
32336512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
32346512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
32356512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
32366512Ssowmini 	 */
32376512Ssowmini 	bufsize =
32386512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
32396512Ssowmini 	buf = malloc(bufsize);
32406512Ssowmini 	prop_vals = (char **)(void *)buf;
32416512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
32426512Ssowmini 		prop_vals[i] = buf +
32436512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
32446512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
32456512Ssowmini 	}
32466768Sar224390 
32476768Sar224390 	/*
32487342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
32497342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
32507342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
32517342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
32527342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
32537342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
32547342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
32557342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
32566768Sar224390 	 */
32578453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
32588118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
32596512Ssowmini 	if (status == DLADM_STATUS_OK) {
32608118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
32618453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
32628453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
32638118SVasumathi.Sundaram@Sun.COM 		}
32648118SVasumathi.Sundaram@Sun.COM 		else
32658118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
32666512Ssowmini 	}
32676512Ssowmini 	free(buf);
32686512Ssowmini 	return (status);
32696512Ssowmini }
32707663SSowmini.Varadhan@Sun.COM 
327110491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
327210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
327310491SRishi.Srivatsavai@Sun.COM get_stp_prop(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
327410491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
327510491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
327610491SRishi.Srivatsavai@Sun.COM {
327710491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
327810491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
327910491SRishi.Srivatsavai@Sun.COM 	int val, i;
328010491SRishi.Srivatsavai@Sun.COM 
328110491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
328210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
328310491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
328410491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
328510491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
328610491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
328710491SRishi.Srivatsavai@Sun.COM 			break;
328810491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
328910491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
329010491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
329110491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
329210491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
329310491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
329410491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
329510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
329610491SRishi.Srivatsavai@Sun.COM 	}
329710491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
329810491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
329910491SRishi.Srivatsavai@Sun.COM 		return (retv);
330010491SRishi.Srivatsavai@Sun.COM 	}
330110491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
330210491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
330310491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
330410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
330510491SRishi.Srivatsavai@Sun.COM 	}
330610491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
330710491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
330810491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
330910491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
331010491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
331110491SRishi.Srivatsavai@Sun.COM 		}
331210491SRishi.Srivatsavai@Sun.COM 	}
331310491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
331410491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
331510491SRishi.Srivatsavai@Sun.COM }
331610491SRishi.Srivatsavai@Sun.COM 
331710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
331810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
331910491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
332010491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
332110491SRishi.Srivatsavai@Sun.COM {
332210491SRishi.Srivatsavai@Sun.COM 	/*
332310491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
332410491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
332510491SRishi.Srivatsavai@Sun.COM 	 */
332610491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
332710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
332810491SRishi.Srivatsavai@Sun.COM 
332910491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
333010491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
333110491SRishi.Srivatsavai@Sun.COM }
333210491SRishi.Srivatsavai@Sun.COM 
333310491SRishi.Srivatsavai@Sun.COM /*
333410491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
333510491SRishi.Srivatsavai@Sun.COM  */
333610491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
333710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
333810491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
333910491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
334010491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
334110491SRishi.Srivatsavai@Sun.COM {
334210491SRishi.Srivatsavai@Sun.COM 	char *cp;
334310491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
334410491SRishi.Srivatsavai@Sun.COM 
334510491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
334610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
334710491SRishi.Srivatsavai@Sun.COM 
334810491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
334910491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
335010491SRishi.Srivatsavai@Sun.COM 	} else {
335110491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
335210491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
335310491SRishi.Srivatsavai@Sun.COM 
335410491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
335510491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
335610491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
335710491SRishi.Srivatsavai@Sun.COM 		} else {
335810491SRishi.Srivatsavai@Sun.COM 			errno = 0;
335910491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
336010491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
336110491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
336210491SRishi.Srivatsavai@Sun.COM 		}
336310491SRishi.Srivatsavai@Sun.COM 	}
336410491SRishi.Srivatsavai@Sun.COM 
336510491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
336610491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
336710491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
336810491SRishi.Srivatsavai@Sun.COM 	} else {
336910491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
337010491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
337110491SRishi.Srivatsavai@Sun.COM 		/*
337210491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
337310491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
337410491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
337510491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
337610491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
337710491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
337810491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
337910491SRishi.Srivatsavai@Sun.COM 		 */
338010491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
338110491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
338210491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
338310491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
338410491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
338510491SRishi.Srivatsavai@Sun.COM 
338610491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
338710491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
338810491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
338910491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
339010491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
339110491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
339210491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
339310491SRishi.Srivatsavai@Sun.COM 		}
339410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
339510491SRishi.Srivatsavai@Sun.COM 	}
339610491SRishi.Srivatsavai@Sun.COM }
339710491SRishi.Srivatsavai@Sun.COM 
339810491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
339910491SRishi.Srivatsavai@Sun.COM static dladm_status_t
340010491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
340110491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
340210491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
340310491SRishi.Srivatsavai@Sun.COM {
340410491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
340510491SRishi.Srivatsavai@Sun.COM 	uint_t val;
340610491SRishi.Srivatsavai@Sun.COM 
340710491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
340810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
340910491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
341010491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
341110491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
341210491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
341310491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
341410491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
341510491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
341610491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
341710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
341810491SRishi.Srivatsavai@Sun.COM 	}
341910491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
342010491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
342110491SRishi.Srivatsavai@Sun.COM 	else
342210491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
342310491SRishi.Srivatsavai@Sun.COM 	return (retv);
342410491SRishi.Srivatsavai@Sun.COM }
342510491SRishi.Srivatsavai@Sun.COM 
342610491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
342710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
342810491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
342910491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
343010491SRishi.Srivatsavai@Sun.COM {
343110491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
343210491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
343310491SRishi.Srivatsavai@Sun.COM }
343410491SRishi.Srivatsavai@Sun.COM 
343510491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
343610491SRishi.Srivatsavai@Sun.COM static dladm_status_t
343710491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
343810491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
343910491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
344010491SRishi.Srivatsavai@Sun.COM {
344110491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
344210491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
344310491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
344410491SRishi.Srivatsavai@Sun.COM 
344510491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
344610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
344710491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
344810491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
344910491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
345010491SRishi.Srivatsavai@Sun.COM 	    0, &status);
345110491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
345210491SRishi.Srivatsavai@Sun.COM 		return (status);
345310491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
345410491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
345510491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
345610491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
345710491SRishi.Srivatsavai@Sun.COM 	} else {
345810491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
345910491SRishi.Srivatsavai@Sun.COM 	}
346010491SRishi.Srivatsavai@Sun.COM 	free(dip);
346110491SRishi.Srivatsavai@Sun.COM 	return (status);
346210491SRishi.Srivatsavai@Sun.COM }
346310491SRishi.Srivatsavai@Sun.COM 
346410491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
346510491SRishi.Srivatsavai@Sun.COM static dladm_status_t
346610491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
346710491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
346810491SRishi.Srivatsavai@Sun.COM {
346910491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
347010491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
347110491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
347210491SRishi.Srivatsavai@Sun.COM 
347310491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
347410491SRishi.Srivatsavai@Sun.COM 	    0, &status);
347510491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
347610491SRishi.Srivatsavai@Sun.COM 		return (status);
347710491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
347810491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
347910491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
348010491SRishi.Srivatsavai@Sun.COM 	free(dip);
348110491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
348210491SRishi.Srivatsavai@Sun.COM 		return (status);
348310491SRishi.Srivatsavai@Sun.COM 
348410491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
348510491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
348610491SRishi.Srivatsavai@Sun.COM }
348710491SRishi.Srivatsavai@Sun.COM 
348810491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
348910491SRishi.Srivatsavai@Sun.COM static dladm_status_t
349010491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
349110491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
349210491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
349310491SRishi.Srivatsavai@Sun.COM {
349410491SRishi.Srivatsavai@Sun.COM 	char *cp;
349510491SRishi.Srivatsavai@Sun.COM 
349610491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
349710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
349810491SRishi.Srivatsavai@Sun.COM 
349910491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
350010491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
350110491SRishi.Srivatsavai@Sun.COM 	} else {
350210491SRishi.Srivatsavai@Sun.COM 		errno = 0;
350310491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
350410491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
350510491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
350610491SRishi.Srivatsavai@Sun.COM 	}
350710491SRishi.Srivatsavai@Sun.COM 
350810491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
350910491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
351010491SRishi.Srivatsavai@Sun.COM }
351110491SRishi.Srivatsavai@Sun.COM 
35127663SSowmini.Varadhan@Sun.COM dladm_status_t
35138453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
35148453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
35157663SSowmini.Varadhan@Sun.COM {
35167663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
35177663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
35187663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
35197663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
35207663SSowmini.Varadhan@Sun.COM 	void			*dp;
35217663SSowmini.Varadhan@Sun.COM 
35228453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
35238453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
35247663SSowmini.Varadhan@Sun.COM 		return (status);
35257663SSowmini.Varadhan@Sun.COM 	}
35267663SSowmini.Varadhan@Sun.COM 
35277663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
35287663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
35297663SSowmini.Varadhan@Sun.COM 
35307663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
35317663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
35327663SSowmini.Varadhan@Sun.COM 
35337663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
35347663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
35357663SSowmini.Varadhan@Sun.COM 
35367663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
35377663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
35387663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
35397663SSowmini.Varadhan@Sun.COM 
35407663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
35417663SSowmini.Varadhan@Sun.COM 	if (set)
35427663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
35437663SSowmini.Varadhan@Sun.COM 
35448453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
354510191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
35467663SSowmini.Varadhan@Sun.COM 		if (!set)
35477663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
35487663SSowmini.Varadhan@Sun.COM 	}
35497663SSowmini.Varadhan@Sun.COM 
35507663SSowmini.Varadhan@Sun.COM 	free(dip);
35517663SSowmini.Varadhan@Sun.COM 	return (status);
35527663SSowmini.Varadhan@Sun.COM }
35537663SSowmini.Varadhan@Sun.COM 
35548275SEric Cheng dladm_status_t
35558275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
35568275SEric Cheng {
35578460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
35588275SEric Cheng }
35598275SEric Cheng 
35608275SEric Cheng /*
35618275SEric Cheng  * Retrieve the one link property from the database
35628275SEric Cheng  */
35638275SEric Cheng /*ARGSUSED*/
35648275SEric Cheng static int
35658453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
35668453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
35678275SEric Cheng {
35688275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
35698275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
35708275SEric Cheng 
35718275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
35728275SEric Cheng 	/*
35738275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
35748275SEric Cheng 	 * prop_table[n].pd_name.
35758275SEric Cheng 	 */
35768275SEric Cheng 	aip->ai_name = prop_name;
35778275SEric Cheng 
35788453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
35798453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
35808275SEric Cheng 
35818275SEric Cheng 	if (aip->ai_count != 0)
35828275SEric Cheng 		proplist->al_count++;
35838275SEric Cheng 
35848275SEric Cheng 	return (DLADM_WALK_CONTINUE);
35858275SEric Cheng }
35868275SEric Cheng 
35878275SEric Cheng 
35888275SEric Cheng /*
35898275SEric Cheng  * Retrieve all link properties for a link from the database and
35908275SEric Cheng  * return a property list.
35918275SEric Cheng  */
35928275SEric Cheng dladm_status_t
35938453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
35948453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
35958275SEric Cheng {
35968275SEric Cheng 	dladm_arg_list_t	*list;
35978275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
35988275SEric Cheng 
35998275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
36008275SEric Cheng 	if (list == NULL)
36018275SEric Cheng 		return (dladm_errno2status(errno));
36028275SEric Cheng 
36038453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
36048453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
36058275SEric Cheng 
36068275SEric Cheng 	*listp = list;
36078275SEric Cheng 	return (status);
36088275SEric Cheng }
36098275SEric Cheng 
36108275SEric Cheng /*
36118275SEric Cheng  * Retrieve the named property from a proplist, check the value and
36128275SEric Cheng  * convert to a kernel structure.
36138275SEric Cheng  */
36148275SEric Cheng static dladm_status_t
36158453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
361610734SEric Cheng     dladm_arg_list_t *proplist, const char *name, void *arg)
36178275SEric Cheng {
36188275SEric Cheng 	dladm_status_t		status;
36198275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
36208275SEric Cheng 	int			i, j;
36218275SEric Cheng 
36228275SEric Cheng 	/* Find named property in proplist */
36238275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
36248275SEric Cheng 		aip = &proplist->al_info[i];
36258275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
36268275SEric Cheng 			break;
36278275SEric Cheng 	}
36288275SEric Cheng 
36298275SEric Cheng 	/* Property not in list */
36308275SEric Cheng 	if (i == proplist->al_count)
36318275SEric Cheng 		return (DLADM_STATUS_OK);
36328275SEric Cheng 
36338275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
36348275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
36358275SEric Cheng 		val_desc_t	*vdp;
36368275SEric Cheng 
36378275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
36388275SEric Cheng 		if (vdp == NULL)
36398275SEric Cheng 			return (DLADM_STATUS_NOMEM);
36408275SEric Cheng 
36418275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
36428275SEric Cheng 			continue;
36438275SEric Cheng 
36448275SEric Cheng 		if (aip->ai_val == NULL)
36458275SEric Cheng 			return (DLADM_STATUS_BADARG);
36468275SEric Cheng 
36478275SEric Cheng 		/* Check property value */
36488275SEric Cheng 		if (pdp->pd_check != NULL) {
36498453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
36508275SEric Cheng 			    aip->ai_count, vdp, 0);
36518275SEric Cheng 		} else {
36528275SEric Cheng 			status = DLADM_STATUS_BADARG;
36538275SEric Cheng 		}
36548275SEric Cheng 
36558275SEric Cheng 		if (status != DLADM_STATUS_OK)
36568275SEric Cheng 			return (status);
36578275SEric Cheng 
36588275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
36598275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
36608275SEric Cheng 
36618275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
36628275SEric Cheng 				continue;
36638275SEric Cheng 
36648275SEric Cheng 			/* Extract kernel structure */
36658275SEric Cheng 			if (rpp->rp_extract != NULL) {
366610734SEric Cheng 				status = rpp->rp_extract(vdp,
366710734SEric Cheng 				    aip->ai_count, arg);
36688275SEric Cheng 			} else {
36698275SEric Cheng 				status = DLADM_STATUS_BADARG;
36708275SEric Cheng 			}
36718275SEric Cheng 			break;
36728275SEric Cheng 		}
36738275SEric Cheng 
36748275SEric Cheng 		if (status != DLADM_STATUS_OK)
36758275SEric Cheng 			return (status);
36768275SEric Cheng 
36778275SEric Cheng 		break;
36788275SEric Cheng 	}
36798275SEric Cheng 	return (status);
36808275SEric Cheng }
36818275SEric Cheng 
36828275SEric Cheng /*
36838275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
36848275SEric Cheng  */
36858275SEric Cheng dladm_status_t
36868453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
36878275SEric Cheng     mac_resource_props_t *mrp)
36888275SEric Cheng {
368910734SEric Cheng 	dladm_status_t	status;
369010734SEric Cheng 	int		i;
369110734SEric Cheng 
369210734SEric Cheng 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
369310734SEric Cheng 		status = i_dladm_link_proplist_extract_one(handle,
369410734SEric Cheng 		    proplist, rsrc_prop_table[i].rp_name, mrp);
369510734SEric Cheng 		if (status != DLADM_STATUS_OK)
369610734SEric Cheng 			return (status);
369710734SEric Cheng 	}
36988275SEric Cheng 	return (status);
36998275SEric Cheng }
37008275SEric Cheng 
37018275SEric Cheng static const char *
37028275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
37038275SEric Cheng {
37048275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
37058275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
37068275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
37078275SEric Cheng 	return (buf);
37088275SEric Cheng }
37098306SSowmini.Varadhan@Sun.COM 
37108306SSowmini.Varadhan@Sun.COM dladm_status_t
37118453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
37128453SAnurag.Maskey@Sun.COM     link_state_t *state)
37138306SSowmini.Varadhan@Sun.COM {
37148306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
37158306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
37168306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
37178306SSowmini.Varadhan@Sun.COM 
37188453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
37198453SAnurag.Maskey@Sun.COM 	    &perms);
37208306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
37218306SSowmini.Varadhan@Sun.COM 		return (status);
37228306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
37238306SSowmini.Varadhan@Sun.COM 	free(dip);
37248306SSowmini.Varadhan@Sun.COM 	return (status);
37258306SSowmini.Varadhan@Sun.COM }
37268460SArtem.Kachitchkin@Sun.COM 
37278460SArtem.Kachitchkin@Sun.COM boolean_t
37288460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
37298460SArtem.Kachitchkin@Sun.COM {
37308460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
37318460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
37328460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
37338460SArtem.Kachitchkin@Sun.COM 		"name",
37348460SArtem.Kachitchkin@Sun.COM 		"class",
37358460SArtem.Kachitchkin@Sun.COM 		"media",
37368460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
37378460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
37388460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
37398460SArtem.Kachitchkin@Sun.COM 
37408460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
37418460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
37428460SArtem.Kachitchkin@Sun.COM 	};
37438460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
37448460SArtem.Kachitchkin@Sun.COM 	int		i;
37458460SArtem.Kachitchkin@Sun.COM 
37468460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
37478460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
37488460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
37498460SArtem.Kachitchkin@Sun.COM 			break;
37508460SArtem.Kachitchkin@Sun.COM 		}
37518460SArtem.Kachitchkin@Sun.COM 	}
37528460SArtem.Kachitchkin@Sun.COM 
37538460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
37548460SArtem.Kachitchkin@Sun.COM }
3755