13147Sxc151355 /*
23147Sxc151355  * CDDL HEADER START
33147Sxc151355  *
43147Sxc151355  * The contents of this file are subject to the terms of the
53147Sxc151355  * Common Development and Distribution License (the "License").
63147Sxc151355  * You may not use this file except in compliance with the License.
73147Sxc151355  *
83147Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93147Sxc151355  * or http://www.opensolaris.org/os/licensing.
103147Sxc151355  * See the License for the specific language governing permissions
113147Sxc151355  * and limitations under the License.
123147Sxc151355  *
133147Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
143147Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153147Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
163147Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
173147Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
183147Sxc151355  *
193147Sxc151355  * CDDL HEADER END
203147Sxc151355  */
213147Sxc151355 /*
228874SSebastien.Roy@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233147Sxc151355  * Use is subject to license terms.
243147Sxc151355  */
253147Sxc151355 
263147Sxc151355 #include <stdlib.h>
273147Sxc151355 #include <strings.h>
283147Sxc151355 #include <errno.h>
293147Sxc151355 #include <ctype.h>
305895Syz147064 #include <stddef.h>
313448Sdh155122 #include <sys/types.h>
323147Sxc151355 #include <sys/stat.h>
333448Sdh155122 #include <sys/dld.h>
343448Sdh155122 #include <sys/zone.h>
353448Sdh155122 #include <fcntl.h>
363448Sdh155122 #include <unistd.h>
373448Sdh155122 #include <libdevinfo.h>
383448Sdh155122 #include <zone.h>
393871Syz147064 #include <libdllink.h>
403147Sxc151355 #include <libdladm_impl.h>
415895Syz147064 #include <libdlwlan_impl.h>
423871Syz147064 #include <libdlwlan.h>
435895Syz147064 #include <libdlvlan.h>
448275SEric Cheng #include <libdlvnic.h>
458275SEric Cheng #include <libintl.h>
463448Sdh155122 #include <dlfcn.h>
473448Sdh155122 #include <link.h>
485895Syz147064 #include <inet/wifi_ioctl.h>
495903Ssowmini #include <libdladm.h>
508275SEric Cheng #include <libdlstat.h>
515903Ssowmini #include <sys/param.h>
528275SEric Cheng #include <sys/debug.h>
538275SEric Cheng #include <sys/dld.h>
548275SEric Cheng #include <sys/mac_flow.h>
555903Ssowmini #include <inttypes.h>
565903Ssowmini #include <sys/ethernet.h>
57*10616SSebastien.Roy@Sun.COM #include <inet/iptun.h>
587663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
597663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
6010491SRishi.Srivatsavai@Sun.COM #include <sys/vlan.h>
6110491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
6210491SRishi.Srivatsavai@Sun.COM #include <stp_in.h>
633448Sdh155122 
645895Syz147064 /*
655895Syz147064  * The linkprop get() callback.
668275SEric Cheng  * - pd: 	pointer to the prop_desc_t
675895Syz147064  * - propstrp:	a property string array to keep the returned property.
685895Syz147064  *		Caller allocated.
695895Syz147064  * - cntp:	number of returned properties.
705895Syz147064  *		Caller also uses it to indicate how many it expects.
715895Syz147064  */
725903Ssowmini struct prop_desc;
738275SEric Cheng typedef struct prop_desc prop_desc_t;
748275SEric Cheng 
758453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
765960Ssowmini 			datalink_id_t, char **propstp, uint_t *cntp,
778118SVasumathi.Sundaram@Sun.COM 			datalink_media_t, uint_t, uint_t *);
785895Syz147064 
795895Syz147064 /*
805895Syz147064  * The linkprop set() callback.
815895Syz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
825895Syz147064  * - cnt:	number of properties to be set.
835903Ssowmini  * - flags: 	additional flags passed down the system call.
845903Ssowmini  *
855903Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
865903Ssowmini  * a format suitable for kernel consumption. This may require allocation
875903Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
885903Ssowmini  * by all other pd_sets) which invokes the ioctl.
895895Syz147064  */
908453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
918275SEric Cheng 			    val_desc_t *propval, uint_t cnt, uint_t flags,
928275SEric Cheng 			    datalink_media_t);
933448Sdh155122 
945895Syz147064 /*
955895Syz147064  * The linkprop check() callback.
965895Syz147064  * - propstrp:	property string array which keeps the property to be checked.
975895Syz147064  * - cnt:	number of properties.
985895Syz147064  * - propval:	return value; the property values of the given property strings.
995903Ssowmini  *
1005903Ssowmini  * pd_check checks that the input values are valid. It does so by
1015903Ssowmini  * iteraring through the pd_modval list for the property. If
1025903Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
1035903Ssowmini  * specific to this property can be used. If the input values are
1045903Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
1055903Ssowmini  * with either a val_desc_t found on the pd_modval list or something
1065903Ssowmini  * generated on the fly.
1075895Syz147064  */
1088453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
1098453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **propstrp, uint_t cnt,
1108453SAnurag.Maskey@Sun.COM 			    val_desc_t *propval, datalink_media_t);
1113448Sdh155122 
1127663SSowmini.Varadhan@Sun.COM typedef struct link_attr_s {
1136789Sam223141 	mac_prop_id_t	pp_id;
1145903Ssowmini 	size_t		pp_valsize;
1155903Ssowmini 	char		*pp_name;
1167663SSowmini.Varadhan@Sun.COM } link_attr_t;
1175903Ssowmini 
1187663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
1198275SEric Cheng 			    const char *, uint_t, dladm_status_t *);
1207663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
1218275SEric Cheng 			    mac_prop_id_t, uint_t, dladm_status_t *);
1228453SAnurag.Maskey@Sun.COM static dld_ioc_macprop_t *i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
1238453SAnurag.Maskey@Sun.COM 			    char *, uint_t, dladm_status_t *, uint_t *);
1248453SAnurag.Maskey@Sun.COM 
1259692SRishi.Srivatsavai@Sun.COM static dladm_status_t i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
1268453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
1278460SArtem.Kachitchkin@Sun.COM static dladm_status_t i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
1288453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *, dladm_prop_type_t,
1298453SAnurag.Maskey@Sun.COM 			    uint_t);
1307663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_name2prop(const char *);
1317663SSowmini.Varadhan@Sun.COM static link_attr_t *dladm_id2prop(mac_prop_id_t);
1328275SEric Cheng 
1335895Syz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
1345895Syz147064 			do_get_rate_prop, do_get_channel_prop,
1355903Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
1367342SAruna.Ramakrishna@Sun.COM 			i_dladm_duplex_get, i_dladm_status_get,
1377342SAruna.Ramakrishna@Sun.COM 			i_dladm_binary_get, i_dladm_uint32_get,
1388460SArtem.Kachitchkin@Sun.COM 			i_dladm_flowctl_get, i_dladm_maxbw_get,
1398874SSebastien.Roy@Sun.COM 			i_dladm_cpus_get, i_dladm_priority_get,
14010491SRishi.Srivatsavai@Sun.COM 			i_dladm_tagmode_get, i_dladm_range_get,
14110491SRishi.Srivatsavai@Sun.COM 			get_stp_prop, get_bridge_forward,
14210491SRishi.Srivatsavai@Sun.COM 			get_bridge_pvid;
1438275SEric Cheng 
1447342SAruna.Ramakrishna@Sun.COM static pd_setf_t	do_set_zone, do_set_rate_prop,
1455903Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
14610491SRishi.Srivatsavai@Sun.COM 			i_dladm_set_public_prop, do_set_res, do_set_cpus,
14710491SRishi.Srivatsavai@Sun.COM 			set_stp_prop, set_bridge_forward, set_bridge_pvid;
1488275SEric Cheng 
1495903Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
150*10616SSebastien.Roy@Sun.COM 			do_check_hoplimit, do_check_encaplim,
15110491SRishi.Srivatsavai@Sun.COM 			i_dladm_uint32_check, do_check_maxbw, do_check_cpus,
15210491SRishi.Srivatsavai@Sun.COM 			do_check_priority, check_stp_prop, check_bridge_pvid;
1538275SEric Cheng 
1548453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_speed_get(dladm_handle_t, prop_desc_t *,
1558453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **, uint_t *, uint_t, uint_t *);
1568453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1578275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
1588275SEric Cheng 
1598275SEric Cheng struct prop_desc {
1605895Syz147064 	/*
1615895Syz147064 	 * link property name
1625895Syz147064 	 */
1635895Syz147064 	char			*pd_name;
1645895Syz147064 
1655895Syz147064 	/*
1665895Syz147064 	 * default property value, can be set to { "", NULL }
1675895Syz147064 	 */
1685895Syz147064 	val_desc_t		pd_defval;
1695895Syz147064 
1705895Syz147064 	/*
1715895Syz147064 	 * list of optional property values, can be NULL.
1725895Syz147064 	 *
1735895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1745895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1755895Syz147064 	 */
1765895Syz147064 	val_desc_t		*pd_optval;
1775895Syz147064 
1785895Syz147064 	/*
1795895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1805895Syz147064 	 */
1815895Syz147064 	uint_t			pd_noptval;
1825895Syz147064 
1835895Syz147064 	/*
18410491SRishi.Srivatsavai@Sun.COM 	 * callback to set link property; set to NULL if this property is
18510491SRishi.Srivatsavai@Sun.COM 	 * read-only and may be called before or after permanent update; see
18610491SRishi.Srivatsavai@Sun.COM 	 * flags.
1875895Syz147064 	 */
1885895Syz147064 	pd_setf_t		*pd_set;
1895895Syz147064 
1905895Syz147064 	/*
1915895Syz147064 	 * callback to get modifiable link property
1925895Syz147064 	 */
1935895Syz147064 	pd_getf_t		*pd_getmod;
1945895Syz147064 
1955895Syz147064 	/*
1965895Syz147064 	 * callback to get current link property
1975895Syz147064 	 */
1985895Syz147064 	pd_getf_t		*pd_get;
1995895Syz147064 
2005895Syz147064 	/*
2015895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
2025895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
2035895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
2045895Syz147064 	 * valid.
2055895Syz147064 	 */
2065895Syz147064 	pd_checkf_t		*pd_check;
2075895Syz147064 
2085895Syz147064 	uint_t			pd_flags;
2095903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2105903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
21110491SRishi.Srivatsavai@Sun.COM #define	PD_AFTER_PERM	0x4	/* pd_set after db update; no temporary */
2125895Syz147064 	/*
2135895Syz147064 	 * indicate link classes this property applies to.
2145895Syz147064 	 */
2155895Syz147064 	datalink_class_t	pd_class;
2165895Syz147064 
2175895Syz147064 	/*
2185895Syz147064 	 * indicate link media type this property applies to.
2195895Syz147064 	 */
2205895Syz147064 	datalink_media_t	pd_dmedia;
2218275SEric Cheng };
2223448Sdh155122 
2236789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2245903Ssowmini 
2257663SSowmini.Varadhan@Sun.COM /*
2267663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2277663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2287663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2297663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2307663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2317663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2327663SSowmini.Varadhan@Sun.COM  */
2337663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2347663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2355903Ssowmini 
2367663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2377663SSowmini.Varadhan@Sun.COM 
2387663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2397663SSowmini.Varadhan@Sun.COM 
2407663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2415903Ssowmini 
2427663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2435903Ssowmini 
2447663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2457663SSowmini.Varadhan@Sun.COM 
2467663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2475903Ssowmini 
2487663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2497663SSowmini.Varadhan@Sun.COM 
2509449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),	"adv_10gfdx_cap"},
2519449Sxiuyan.wang@Sun.COM 
2529449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),	"en_10gfdx_cap"},
2539449Sxiuyan.wang@Sun.COM 
2547663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2557663SSowmini.Varadhan@Sun.COM 
2567663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2575903Ssowmini 
2587663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2595903Ssowmini 
2607663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2617663SSowmini.Varadhan@Sun.COM 
2627663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2637342SAruna.Ramakrishna@Sun.COM 
2647663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2657663SSowmini.Varadhan@Sun.COM 
2667663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2677663SSowmini.Varadhan@Sun.COM 
2687663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2697342SAruna.Ramakrishna@Sun.COM 
2707663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2717663SSowmini.Varadhan@Sun.COM 
2727663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2735903Ssowmini 
2747663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2757663SSowmini.Varadhan@Sun.COM 
2767663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2775903Ssowmini 
2787663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2797663SSowmini.Varadhan@Sun.COM 
2807663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2815903Ssowmini 
2827663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2837663SSowmini.Varadhan@Sun.COM 
2847663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2857663SSowmini.Varadhan@Sun.COM 
2867663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2877663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2885903Ssowmini 
2897663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2907663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2917663SSowmini.Varadhan@Sun.COM 
2927663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2935903Ssowmini 
2947663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
2957663SSowmini.Varadhan@Sun.COM 
2967663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
2975903Ssowmini 
2987663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
2997663SSowmini.Varadhan@Sun.COM 
3007663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
3015903Ssowmini 
3027663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
3037663SSowmini.Varadhan@Sun.COM 
3047663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
3057663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
3065903Ssowmini 
3077663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
3087663SSowmini.Varadhan@Sun.COM 
3097663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
3105903Ssowmini 
3117663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3127663SSowmini.Varadhan@Sun.COM 
3137663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3145903Ssowmini 
3157663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3167663SSowmini.Varadhan@Sun.COM 
3177663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3187663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3195903Ssowmini 
3207663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3217663SSowmini.Varadhan@Sun.COM 
3227663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3235903Ssowmini 
3247663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3257663SSowmini.Varadhan@Sun.COM 
3268275SEric Cheng 	{ MAC_PROP_MAXBW,	sizeof (mac_resource_props_t),	"maxbw"},
3278275SEric Cheng 
3288275SEric Cheng 	{ MAC_PROP_PRIO,	sizeof (mac_resource_props_t),	"priority"},
3298275SEric Cheng 
3308275SEric Cheng 	{ MAC_PROP_BIND_CPU,	sizeof (mac_resource_props_t),	"cpus"},
3318275SEric Cheng 
3328874SSebastien.Roy@Sun.COM 	{ MAC_PROP_TAGMODE,	sizeof (link_tagmode_t),	"tagmode"},
3338874SSebastien.Roy@Sun.COM 
334*10616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t),	"hoplimit"},
335*10616SSebastien.Roy@Sun.COM 
336*10616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t),	"encaplimit"},
337*10616SSebastien.Roy@Sun.COM 
33810491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_PVID,	sizeof (uint16_t),	"default_tag"},
33910491SRishi.Srivatsavai@Sun.COM 
34010491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LLIMIT,	sizeof (uint32_t),	"learn_limit"},
34110491SRishi.Srivatsavai@Sun.COM 
34210491SRishi.Srivatsavai@Sun.COM 	{ MAC_PROP_LDECAY,	sizeof (uint32_t),	"learn_decay"},
34310491SRishi.Srivatsavai@Sun.COM 
3447663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3458275SEric Cheng 
3465903Ssowmini };
3475903Ssowmini 
34810491SRishi.Srivatsavai@Sun.COM typedef struct bridge_public_prop_s {
34910491SRishi.Srivatsavai@Sun.COM 	const char	*bpp_name;
35010491SRishi.Srivatsavai@Sun.COM 	int		bpp_code;
35110491SRishi.Srivatsavai@Sun.COM } bridge_public_prop_t;
35210491SRishi.Srivatsavai@Sun.COM 
35310491SRishi.Srivatsavai@Sun.COM static const bridge_public_prop_t bridge_prop[] = {
35410491SRishi.Srivatsavai@Sun.COM 	{ "stp", PT_CFG_NON_STP },
35510491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", PT_CFG_PRIO },
35610491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", PT_CFG_COST },
35710491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", PT_CFG_EDGE },
35810491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", PT_CFG_P2P },
35910491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", PT_CFG_MCHECK },
36010491SRishi.Srivatsavai@Sun.COM 	{ NULL, 0 }
36110491SRishi.Srivatsavai@Sun.COM };
36210491SRishi.Srivatsavai@Sun.COM 
3635903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3645903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3655903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3665903Ssowmini };
3675903Ssowmini static  val_desc_t	link_status_vals[] = {
3685903Ssowmini 	{ "up",		LINK_STATE_UP		},
3695903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3705903Ssowmini };
3715903Ssowmini static  val_desc_t	link_01_vals[] = {
3725903Ssowmini 	{ "1",		1			},
3735903Ssowmini 	{ "0",		0			}
3745903Ssowmini };
3755903Ssowmini static  val_desc_t	link_flow_vals[] = {
3765903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3775903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3785903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3795903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3805903Ssowmini };
3818275SEric Cheng static  val_desc_t	link_priority_vals[] = {
3828275SEric Cheng 	{ "low",	MPL_LOW	},
3838275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
3848275SEric Cheng 	{ "high",	MPL_HIGH	}
3858275SEric Cheng };
3865903Ssowmini 
3878874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
3888874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
3898874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
3908874SSebastien.Roy@Sun.COM };
3918874SSebastien.Roy@Sun.COM 
3925895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
3935895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
3945895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
3955895Syz147064 };
3965895Syz147064 
3975895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
3985895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
3995895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
4005895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
4015895Syz147064 };
4025895Syz147064 
40310491SRishi.Srivatsavai@Sun.COM static  val_desc_t	stp_p2p_vals[] = {
40410491SRishi.Srivatsavai@Sun.COM 	{ "true",	P2P_FORCE_TRUE		},
40510491SRishi.Srivatsavai@Sun.COM 	{ "false",	P2P_FORCE_FALSE		},
40610491SRishi.Srivatsavai@Sun.COM 	{ "auto",	P2P_AUTO		}
40710491SRishi.Srivatsavai@Sun.COM };
40810491SRishi.Srivatsavai@Sun.COM 
4098275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
4108275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
4118275SEric Cheng 
4123448Sdh155122 static prop_desc_t	prop_table[] = {
4135903Ssowmini 	{ "channel",	{ NULL, 0 },
4145903Ssowmini 	    NULL, 0, NULL, NULL,
4155895Syz147064 	    do_get_channel_prop, NULL, 0,
4165903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4175895Syz147064 
4185895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
4195895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
4205895Syz147064 	    do_set_powermode_prop, NULL,
4215895Syz147064 	    do_get_powermode_prop, NULL, 0,
4225903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4235895Syz147064 
4245895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
4255895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
4265895Syz147064 	    do_set_radio_prop, NULL,
4275895Syz147064 	    do_get_radio_prop, NULL, 0,
4285903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4295895Syz147064 
4305895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
4315895Syz147064 	    do_set_rate_prop, do_get_rate_mod,
4325895Syz147064 	    do_get_rate_prop, do_check_rate, 0,
4335960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
4345895Syz147064 
4356512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
4367342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL,
4377342SAruna.Ramakrishna@Sun.COM 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
4385903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4395895Syz147064 
4406512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
4413448Sdh155122 	    do_set_zone, NULL,
4427342SAruna.Ramakrishna@Sun.COM 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4435903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4445903Ssowmini 
4458275SEric Cheng 	{ "duplex",	{ "", 0 },
4465903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
4477342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_duplex_get, NULL,
4485903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4495903Ssowmini 
4508275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4515903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
4527342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_status_get, NULL,
4536512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4545903Ssowmini 
45510191SSowmini.Varadhan@Sun.COM 	{ "adv_autoneg_cap", { "", 0 },
4565903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4577342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4585903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4595903Ssowmini 
4606512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
4619514SGirish.Moodalbail@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get,
46210491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_get, i_dladm_uint32_check, 0, DATALINK_CLASS_ALL,
4637342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4645903Ssowmini 
4656512Ssowmini 	{ "flowctrl", { "", 0 },
4665903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
4677342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
4685903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4695903Ssowmini 
4709449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
4719449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4729449Sxiuyan.wang@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4739449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4749449Sxiuyan.wang@Sun.COM 
4759449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
4769449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
4779449Sxiuyan.wang@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4789449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4799449Sxiuyan.wang@Sun.COM 
4806512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
4816512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4827342SAruna.Ramakrishna@Sun.COM 	    NULL, NULL, i_dladm_binary_get, NULL,
4835903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4845903Ssowmini 
4856512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
4865903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
4877342SAruna.Ramakrishna@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
4885903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4895903Ssowmini 
4906512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
4915903Ssowmini 	    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_1000hdx_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_100fdx_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_100fdx_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_100hdx_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_100hdx_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_10fdx_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_10fdx_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_10hdx_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_10hdx_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,
5388275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5398275SEric Cheng 
5408275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
5418275SEric Cheng 	    do_set_res, NULL,
5428460SArtem.Kachitchkin@Sun.COM 	    i_dladm_maxbw_get, do_check_maxbw, PD_CHECK_ALLOC,
5438275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5448275SEric Cheng 
5458275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
5468275SEric Cheng 	    do_set_cpus, NULL,
5478460SArtem.Kachitchkin@Sun.COM 	    i_dladm_cpus_get, do_check_cpus, 0,
5488275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5498275SEric Cheng 
5508275SEric Cheng 	{ "priority", { "high", RESET_VAL },
5518275SEric Cheng 	    link_priority_vals, VALCNT(link_priority_vals), do_set_res, NULL,
5528460SArtem.Kachitchkin@Sun.COM 	    i_dladm_priority_get, do_check_priority, PD_CHECK_ALLOC,
5538275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5548874SSebastien.Roy@Sun.COM 
5558874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
5568874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
5578874SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_tagmode_get,
5588874SSebastien.Roy@Sun.COM 	    NULL, 0,
5598874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
56010491SRishi.Srivatsavai@Sun.COM 	    DL_ETHER },
56110491SRishi.Srivatsavai@Sun.COM 
562*10616SSebastien.Roy@Sun.COM 	{ "hoplimit", { "", 0 }, NULL, 0,
563*10616SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get,
564*10616SSebastien.Roy@Sun.COM 	    do_check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
565*10616SSebastien.Roy@Sun.COM 
566*10616SSebastien.Roy@Sun.COM 	{ "encaplimit", { "", 0 }, NULL, 0,
567*10616SSebastien.Roy@Sun.COM 	    i_dladm_set_public_prop, i_dladm_range_get, i_dladm_uint32_get,
568*10616SSebastien.Roy@Sun.COM 	    do_check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
569*10616SSebastien.Roy@Sun.COM 
57010491SRishi.Srivatsavai@Sun.COM 	{ "forward", { "1", 1 },
57110491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
57210491SRishi.Srivatsavai@Sun.COM 	    set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
57310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
57410491SRishi.Srivatsavai@Sun.COM 
57510491SRishi.Srivatsavai@Sun.COM 	{ "default_tag", { "1", 1 }, NULL, 0,
57610491SRishi.Srivatsavai@Sun.COM 	    set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
57710491SRishi.Srivatsavai@Sun.COM 	    0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
57810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
57910491SRishi.Srivatsavai@Sun.COM 
58010491SRishi.Srivatsavai@Sun.COM 	{ "learn_limit", { "1000", 1000 }, NULL, 0,
58110491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
58210491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
58310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
58410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
58510491SRishi.Srivatsavai@Sun.COM 
58610491SRishi.Srivatsavai@Sun.COM 	{ "learn_decay", { "200", 200 }, NULL, 0,
58710491SRishi.Srivatsavai@Sun.COM 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
58810491SRishi.Srivatsavai@Sun.COM 	    i_dladm_uint32_check, 0,
58910491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
59010491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
59110491SRishi.Srivatsavai@Sun.COM 
59210491SRishi.Srivatsavai@Sun.COM 	{ "stp", { "1", 1 },
59310491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
59410491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
59510491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
59610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
59710491SRishi.Srivatsavai@Sun.COM 
59810491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", { "128", 128 }, NULL, 0,
59910491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
60010491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
60110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
60210491SRishi.Srivatsavai@Sun.COM 
60310491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", { "auto", 0 }, NULL, 0,
60410491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, 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_edge", { "1", 1 },
60910491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
61010491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
61110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
61210491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
61310491SRishi.Srivatsavai@Sun.COM 
61410491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", { "auto", P2P_AUTO },
61510491SRishi.Srivatsavai@Sun.COM 	    stp_p2p_vals, VALCNT(stp_p2p_vals),
61610491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, NULL, PD_AFTER_PERM,
61710491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
61810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
61910491SRishi.Srivatsavai@Sun.COM 
62010491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", { "0", 0 },
62110491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
62210491SRishi.Srivatsavai@Sun.COM 	    set_stp_prop, NULL, get_stp_prop, check_stp_prop, PD_AFTER_PERM,
62310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
62410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
6253448Sdh155122 };
6263448Sdh155122 
6275895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
6285895Syz147064 
6298275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
6308275SEric Cheng 	{"maxbw",	do_extract_maxbw},
6318275SEric Cheng 	{"priority",	do_extract_priority},
6328275SEric Cheng 	{"cpus",	do_extract_cpus}
6338275SEric Cheng };
6348275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
6358275SEric Cheng 	sizeof (resource_prop_t))
6368275SEric Cheng 
6377663SSowmini.Varadhan@Sun.COM /*
6387663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
6397663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
6407663SSowmini.Varadhan@Sun.COM  */
6417663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
6427663SSowmini.Varadhan@Sun.COM 
6438453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
6448453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
6458453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
6468453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
6478460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
6488460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
6498460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
6508453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
6518453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
6528453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
6538453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
6548453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
6558453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
6568453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
6578275SEric Cheng 
6585895Syz147064 /*
6595895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
6605895Syz147064  * rates to be retrieved. However, we cannot increase it at this
6615895Syz147064  * time because it will break binary compatibility with unbundled
6625895Syz147064  * WiFi drivers and utilities. So for now we define an additional
6635895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
6645895Syz147064  */
6655895Syz147064 #define	MAX_SUPPORT_RATES	64
6665895Syz147064 
6675895Syz147064 #define	AP_ANCHOR	"[anchor]"
6685895Syz147064 #define	AP_DELIMITER	'.'
6695895Syz147064 
6705895Syz147064 static dladm_status_t
6715895Syz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
6725895Syz147064     val_desc_t *vdp)
6735895Syz147064 {
6745895Syz147064 	int		i, j;
6755895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6763147Sxc151355 
6775895Syz147064 	for (j = 0; j < val_cnt; j++) {
6785895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
6795895Syz147064 			if (strcasecmp(*prop_val,
6805895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
6815895Syz147064 				break;
6825895Syz147064 			}
6835895Syz147064 		}
6845895Syz147064 		if (i == pdp->pd_noptval) {
6855895Syz147064 			status = DLADM_STATUS_BADVAL;
6865895Syz147064 			goto done;
6875895Syz147064 		}
6885895Syz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
6895895Syz147064 	}
6905895Syz147064 
6915895Syz147064 done:
6925895Syz147064 	return (status);
6935895Syz147064 }
6945895Syz147064 
6955895Syz147064 static dladm_status_t
6968453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
6978453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
6988453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
6993147Sxc151355 {
7005895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
7015895Syz147064 	val_desc_t	*vdp = NULL;
7025895Syz147064 	boolean_t	needfree = B_FALSE;
7035895Syz147064 	uint_t		cnt, i;
7043147Sxc151355 
7055895Syz147064 	if (!(pdp->pd_class & class))
7065895Syz147064 		return (DLADM_STATUS_BADARG);
7075895Syz147064 
7085895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
7093147Sxc151355 		return (DLADM_STATUS_BADARG);
7103147Sxc151355 
7115895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
7125895Syz147064 		return (DLADM_STATUS_TEMPONLY);
7135895Syz147064 
7145895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
7155895Syz147064 		return (DLADM_STATUS_OK);
7165895Syz147064 
7175895Syz147064 	if (pdp->pd_set == NULL)
7185895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
7193448Sdh155122 
7205895Syz147064 	if (prop_val != NULL) {
7215895Syz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
7225895Syz147064 		if (vdp == NULL)
7235895Syz147064 			return (DLADM_STATUS_NOMEM);
7245895Syz147064 
7255895Syz147064 		if (pdp->pd_check != NULL) {
7268275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
7278453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
7288453SAnurag.Maskey@Sun.COM 			    val_cnt, vdp, media);
7295895Syz147064 		} else if (pdp->pd_optval != NULL) {
7305895Syz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
7315895Syz147064 		} else {
7323448Sdh155122 			status = DLADM_STATUS_BADARG;
7333147Sxc151355 		}
7345895Syz147064 
7353147Sxc151355 		if (status != DLADM_STATUS_OK)
7365895Syz147064 			goto done;
7375895Syz147064 
7385895Syz147064 		cnt = val_cnt;
7395895Syz147064 	} else {
7408275SEric Cheng 		boolean_t	defval = B_FALSE;
7418275SEric Cheng 
7425895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
7435895Syz147064 			return (DLADM_STATUS_NOTSUP);
7445895Syz147064 
7457342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
7468275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
7478275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
7486512Ssowmini 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
7496512Ssowmini 				return (DLADM_STATUS_NOMEM);
7507342SAruna.Ramakrishna@Sun.COM 
7518275SEric Cheng 			if (defval) {
7528275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
7538275SEric Cheng 				    sizeof (val_desc_t));
7548275SEric Cheng 			} else if (pdp->pd_check != NULL) {
7558453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
7568453SAnurag.Maskey@Sun.COM 				    prop_val, cnt, vdp, media);
7577342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
7587342SAruna.Ramakrishna@Sun.COM 					goto done;
7597342SAruna.Ramakrishna@Sun.COM 			}
7606512Ssowmini 		} else {
7618453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
7626512Ssowmini 			    media, flags);
7636512Ssowmini 			return (status);
7646512Ssowmini 		}
7655895Syz147064 	}
76610491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_AFTER_PERM)
76710491SRishi.Srivatsavai@Sun.COM 		status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
76810491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_PERMONLY;
76910491SRishi.Srivatsavai@Sun.COM 	else
77010491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
77110491SRishi.Srivatsavai@Sun.COM 		    media);
7725895Syz147064 	if (needfree) {
7735895Syz147064 		for (i = 0; i < cnt; i++)
7745903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
7753147Sxc151355 	}
7765895Syz147064 done:
7775895Syz147064 	free(vdp);
7785895Syz147064 	return (status);
7795895Syz147064 }
7805895Syz147064 
7815895Syz147064 static dladm_status_t
7828453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
7838453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
7845895Syz147064 {
7855895Syz147064 	int			i;
7865895Syz147064 	boolean_t		found = B_FALSE;
7875895Syz147064 	datalink_class_t	class;
7885895Syz147064 	uint32_t		media;
7895895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
7905895Syz147064 
7918453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
7928453SAnurag.Maskey@Sun.COM 	    NULL, 0);
7935895Syz147064 	if (status != DLADM_STATUS_OK)
7945895Syz147064 		return (status);
7955895Syz147064 
7965895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
7975895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
7985895Syz147064 		dladm_status_t	s;
7995895Syz147064 
8005895Syz147064 		if (prop_name != NULL &&
8015895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
8025895Syz147064 			continue;
8035895Syz147064 		found = B_TRUE;
8048453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
8058453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
8063448Sdh155122 
8075895Syz147064 		if (prop_name != NULL) {
8085895Syz147064 			status = s;
8095895Syz147064 			break;
8105895Syz147064 		} else {
8115895Syz147064 			if (s != DLADM_STATUS_OK &&
8125895Syz147064 			    s != DLADM_STATUS_NOTSUP)
8135895Syz147064 				status = s;
8145895Syz147064 		}
8155895Syz147064 	}
8165903Ssowmini 	if (!found) {
8175903Ssowmini 		if (prop_name[0] == '_') {
8185903Ssowmini 			/* other private properties */
8199692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
8209692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
8215903Ssowmini 		} else  {
8225903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
8235903Ssowmini 		}
8245903Ssowmini 	}
8255895Syz147064 
8265895Syz147064 	return (status);
8275895Syz147064 }
8285895Syz147064 
8295895Syz147064 /*
8305895Syz147064  * Set/reset link property for specific link
8315895Syz147064  */
8325895Syz147064 dladm_status_t
8338453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8348453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8355895Syz147064 {
8365895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
8375895Syz147064 
8385895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
8395895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
8405895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
8415895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
8425895Syz147064 		return (DLADM_STATUS_BADARG);
8435895Syz147064 	}
8445895Syz147064 
8459692SRishi.Srivatsavai@Sun.COM 	/*
8469692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
8479692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
8489692SRishi.Srivatsavai@Sun.COM 	 */
8498453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
8505895Syz147064 	    val_cnt, flags);
8515895Syz147064 	if (status != DLADM_STATUS_OK)
8525895Syz147064 		return (status);
8535895Syz147064 
8545895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
8558453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
8563147Sxc151355 		    prop_val, val_cnt);
85710491SRishi.Srivatsavai@Sun.COM 
85810491SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
85910491SRishi.Srivatsavai@Sun.COM 			prop_desc_t *pdp = prop_table;
86010491SRishi.Srivatsavai@Sun.COM 			int i;
86110491SRishi.Srivatsavai@Sun.COM 
86210491SRishi.Srivatsavai@Sun.COM 			for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
86310491SRishi.Srivatsavai@Sun.COM 				if (!(pdp->pd_flags & PD_AFTER_PERM))
86410491SRishi.Srivatsavai@Sun.COM 					continue;
86510491SRishi.Srivatsavai@Sun.COM 				if (prop_name != NULL &&
86610491SRishi.Srivatsavai@Sun.COM 				    strcasecmp(prop_name, pdp->pd_name) != 0)
86710491SRishi.Srivatsavai@Sun.COM 					continue;
86810491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_set(handle, pdp, linkid, NULL,
86910491SRishi.Srivatsavai@Sun.COM 				    0, flags, 0);
87010491SRishi.Srivatsavai@Sun.COM 			}
87110491SRishi.Srivatsavai@Sun.COM 		}
8723147Sxc151355 	}
8733147Sxc151355 	return (status);
8743147Sxc151355 }
8753147Sxc151355 
8765895Syz147064 /*
8778460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
8788460SArtem.Kachitchkin@Sun.COM  *
8798460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
8808460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
8818460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
8828460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
8835895Syz147064  */
8843147Sxc151355 dladm_status_t
8858453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
8868453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
8873147Sxc151355 {
8885895Syz147064 	dladm_status_t		status;
8895895Syz147064 	datalink_class_t	class;
8905895Syz147064 	uint_t			media;
8915895Syz147064 	int			i;
8925895Syz147064 
8935895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
8945895Syz147064 		return (DLADM_STATUS_BADARG);
8955895Syz147064 
8968453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
8978453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8985895Syz147064 	if (status != DLADM_STATUS_OK)
8995895Syz147064 		return (status);
9005895Syz147064 
9018460SArtem.Kachitchkin@Sun.COM 	/* public */
9025895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
9035895Syz147064 		if (!(prop_table[i].pd_class & class))
9045895Syz147064 			continue;
9055895Syz147064 
9065895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
9075895Syz147064 			continue;
9085895Syz147064 
9098453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
9105895Syz147064 		    DLADM_WALK_TERMINATE) {
9115895Syz147064 			break;
9125895Syz147064 		}
9135895Syz147064 	}
9145895Syz147064 
9158460SArtem.Kachitchkin@Sun.COM 	/* private */
9168460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
9178460SArtem.Kachitchkin@Sun.COM 
9188460SArtem.Kachitchkin@Sun.COM 	return (status);
9195895Syz147064 }
9203448Sdh155122 
9215895Syz147064 /*
9225895Syz147064  * Get linkprop of the given specific link.
9235895Syz147064  */
9245895Syz147064 dladm_status_t
9258453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9268453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
9278453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
9285895Syz147064 {
9295895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
9305895Syz147064 	datalink_class_t	class;
9315895Syz147064 	uint_t			media;
9325895Syz147064 	prop_desc_t		*pdp;
9336512Ssowmini 	uint_t			cnt, dld_flags = 0;
9345895Syz147064 	int			i;
9358118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
9365895Syz147064 
9376512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
9389514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_DEFAULT;
9399514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
9409514SGirish.Moodalbail@Sun.COM 		dld_flags |= MAC_PROP_POSSIBLE;
9416512Ssowmini 
9425895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
9435895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
9445895Syz147064 		return (DLADM_STATUS_BADARG);
9455895Syz147064 
9465895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
9475895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
9485895Syz147064 			break;
9495895Syz147064 
9505903Ssowmini 	if (i == DLADM_MAX_PROPS) {
9515903Ssowmini 		if (prop_name[0] == '_') {
9525903Ssowmini 			/*
9535903Ssowmini 			 * private property.
9545903Ssowmini 			 */
9558460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
9568460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
9578460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
9588460SArtem.Kachitchkin@Sun.COM 			else
9598460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
9608460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
9618460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
9625903Ssowmini 		} else {
9635903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
9645903Ssowmini 		}
9655903Ssowmini 	}
9665895Syz147064 
9675895Syz147064 	pdp = &prop_table[i];
9685895Syz147064 
9698453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9708453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9715895Syz147064 	if (status != DLADM_STATUS_OK)
9725895Syz147064 		return (status);
9735895Syz147064 
9745895Syz147064 	if (!(pdp->pd_class & class))
9755895Syz147064 		return (DLADM_STATUS_BADARG);
9765895Syz147064 
9775895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
9783147Sxc151355 		return (DLADM_STATUS_BADARG);
9793147Sxc151355 
9805895Syz147064 	switch (type) {
9815895Syz147064 	case DLADM_PROP_VAL_CURRENT:
9828453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
9838453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
9848118SVasumathi.Sundaram@Sun.COM 		break;
9858118SVasumathi.Sundaram@Sun.COM 
9868118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
9878118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
9888118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
9898118SVasumathi.Sundaram@Sun.COM 		} else {
9908453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
9918453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
9928118SVasumathi.Sundaram@Sun.COM 		}
9938118SVasumathi.Sundaram@Sun.COM 
9948118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
9959055SMichael.Lim@Sun.COM 		*val_cntp = 1;
9968275SEric Cheng 		if (status == DLADM_STATUS_OK)
9978275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
9985895Syz147064 		break;
9995895Syz147064 
10005895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
10016768Sar224390 		/*
10026768Sar224390 		 * If defaults are not defined for the property,
10036768Sar224390 		 * pd_defval.vd_name should be null. If the driver
10046768Sar224390 		 * has to be contacted for the value, vd_name should
10056768Sar224390 		 * be the empty string (""). Otherwise, dladm will
10066768Sar224390 		 * just print whatever is in the table.
10076768Sar224390 		 */
10085895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
10095895Syz147064 			status = DLADM_STATUS_NOTSUP;
10105895Syz147064 			break;
10115895Syz147064 		}
10126512Ssowmini 
10136512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
10148453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
10158453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10166512Ssowmini 		} else {
10176512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
10186512Ssowmini 		}
10195895Syz147064 		*val_cntp = 1;
10205895Syz147064 		break;
10213448Sdh155122 
10225895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
10235895Syz147064 		if (pdp->pd_getmod != NULL) {
10248453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
10258118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10265895Syz147064 			break;
10275895Syz147064 		}
10285895Syz147064 		cnt = pdp->pd_noptval;
10295895Syz147064 		if (cnt == 0) {
10305895Syz147064 			status = DLADM_STATUS_NOTSUP;
10315895Syz147064 		} else if (cnt > *val_cntp) {
10325895Syz147064 			status = DLADM_STATUS_TOOSMALL;
10335895Syz147064 		} else {
10345895Syz147064 			for (i = 0; i < cnt; i++) {
10355895Syz147064 				(void) strcpy(prop_val[i],
10365895Syz147064 				    pdp->pd_optval[i].vd_name);
10375895Syz147064 			}
10385895Syz147064 			*val_cntp = cnt;
10395895Syz147064 		}
10405895Syz147064 		break;
10415895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
10425895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
10435895Syz147064 			return (DLADM_STATUS_TEMPONLY);
10448453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
10455895Syz147064 		    prop_val, val_cntp);
10465895Syz147064 		break;
10475895Syz147064 	default:
10485895Syz147064 		status = DLADM_STATUS_BADARG;
10495895Syz147064 		break;
10503147Sxc151355 	}
10513448Sdh155122 
10525895Syz147064 	return (status);
10535895Syz147064 }
10545895Syz147064 
105510491SRishi.Srivatsavai@Sun.COM /*
105610491SRishi.Srivatsavai@Sun.COM  * Get linkprop of the given specific link and run any possible conversion
105710491SRishi.Srivatsavai@Sun.COM  * of the values using the check function for the property. Fails if the
105810491SRishi.Srivatsavai@Sun.COM  * check function doesn't succeed for the property value.
105910491SRishi.Srivatsavai@Sun.COM  */
106010491SRishi.Srivatsavai@Sun.COM dladm_status_t
106110491SRishi.Srivatsavai@Sun.COM dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
106210491SRishi.Srivatsavai@Sun.COM     dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
106310491SRishi.Srivatsavai@Sun.COM     uint_t *val_cntp)
106410491SRishi.Srivatsavai@Sun.COM {
106510491SRishi.Srivatsavai@Sun.COM 	dladm_status_t		status;
106610491SRishi.Srivatsavai@Sun.COM 	datalink_class_t	class;
106710491SRishi.Srivatsavai@Sun.COM 	uint_t			media;
106810491SRishi.Srivatsavai@Sun.COM 	prop_desc_t		*pdp;
106910491SRishi.Srivatsavai@Sun.COM 	uint_t			dld_flags;
107010491SRishi.Srivatsavai@Sun.COM 	int			valc, i;
107110491SRishi.Srivatsavai@Sun.COM 	char			**prop_val;
107210491SRishi.Srivatsavai@Sun.COM 	uint_t			perm_flags;
107310491SRishi.Srivatsavai@Sun.COM 
107410491SRishi.Srivatsavai@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
107510491SRishi.Srivatsavai@Sun.COM 	    ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
107610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
107710491SRishi.Srivatsavai@Sun.COM 
107810491SRishi.Srivatsavai@Sun.COM 	for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
107910491SRishi.Srivatsavai@Sun.COM 		if (strcasecmp(prop_name, pdp->pd_name) == 0)
108010491SRishi.Srivatsavai@Sun.COM 			break;
108110491SRishi.Srivatsavai@Sun.COM 
108210491SRishi.Srivatsavai@Sun.COM 	if (pdp == prop_table + DLADM_MAX_PROPS)
108310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
108410491SRishi.Srivatsavai@Sun.COM 
108510491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_CHECK_ALLOC)
108610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
108710491SRishi.Srivatsavai@Sun.COM 
108810491SRishi.Srivatsavai@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
108910491SRishi.Srivatsavai@Sun.COM 	    NULL, 0);
109010491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
109110491SRishi.Srivatsavai@Sun.COM 		return (status);
109210491SRishi.Srivatsavai@Sun.COM 
109310491SRishi.Srivatsavai@Sun.COM 	if (!(pdp->pd_class & class))
109410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
109510491SRishi.Srivatsavai@Sun.COM 
109610491SRishi.Srivatsavai@Sun.COM 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
109710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
109810491SRishi.Srivatsavai@Sun.COM 
109910491SRishi.Srivatsavai@Sun.COM 	prop_val = malloc(*val_cntp * sizeof (*prop_val) +
110010491SRishi.Srivatsavai@Sun.COM 	    *val_cntp * DLADM_PROP_VAL_MAX);
110110491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL)
110210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOMEM);
110310491SRishi.Srivatsavai@Sun.COM 	for (valc = 0; valc < *val_cntp; valc++)
110410491SRishi.Srivatsavai@Sun.COM 		prop_val[valc] = (char *)(prop_val + *val_cntp) +
110510491SRishi.Srivatsavai@Sun.COM 		    valc * DLADM_PROP_VAL_MAX;
110610491SRishi.Srivatsavai@Sun.COM 
110710491SRishi.Srivatsavai@Sun.COM 	dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? MAC_PROP_DEFAULT : 0;
110810491SRishi.Srivatsavai@Sun.COM 
110910491SRishi.Srivatsavai@Sun.COM 	switch (type) {
111010491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_CURRENT:
111110491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
111210491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
111310491SRishi.Srivatsavai@Sun.COM 		break;
111410491SRishi.Srivatsavai@Sun.COM 
111510491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_DEFAULT:
111610491SRishi.Srivatsavai@Sun.COM 		/*
111710491SRishi.Srivatsavai@Sun.COM 		 * If defaults are not defined for the property,
111810491SRishi.Srivatsavai@Sun.COM 		 * pd_defval.vd_name should be null. If the driver
111910491SRishi.Srivatsavai@Sun.COM 		 * has to be contacted for the value, vd_name should
112010491SRishi.Srivatsavai@Sun.COM 		 * be the empty string (""). Otherwise, dladm will
112110491SRishi.Srivatsavai@Sun.COM 		 * just print whatever is in the table.
112210491SRishi.Srivatsavai@Sun.COM 		 */
112310491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name == NULL) {
112410491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_NOTSUP;
112510491SRishi.Srivatsavai@Sun.COM 			break;
112610491SRishi.Srivatsavai@Sun.COM 		}
112710491SRishi.Srivatsavai@Sun.COM 
112810491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name[0] != '\0') {
112910491SRishi.Srivatsavai@Sun.COM 			*val_cntp = 1;
113010491SRishi.Srivatsavai@Sun.COM 			*ret_val = pdp->pd_defval.vd_val;
113110491SRishi.Srivatsavai@Sun.COM 			free(prop_val);
113210491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
113310491SRishi.Srivatsavai@Sun.COM 		}
113410491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
113510491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
113610491SRishi.Srivatsavai@Sun.COM 		break;
113710491SRishi.Srivatsavai@Sun.COM 
113810491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_PERSISTENT:
113910491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_flags & PD_TEMPONLY)
114010491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_TEMPONLY;
114110491SRishi.Srivatsavai@Sun.COM 		else
114210491SRishi.Srivatsavai@Sun.COM 			status = i_dladm_get_linkprop_db(handle, linkid,
114310491SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cntp);
114410491SRishi.Srivatsavai@Sun.COM 		break;
114510491SRishi.Srivatsavai@Sun.COM 
114610491SRishi.Srivatsavai@Sun.COM 	default:
114710491SRishi.Srivatsavai@Sun.COM 		status = DLADM_STATUS_BADARG;
114810491SRishi.Srivatsavai@Sun.COM 		break;
114910491SRishi.Srivatsavai@Sun.COM 	}
115010491SRishi.Srivatsavai@Sun.COM 
115110491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
115210491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_check != NULL) {
115310491SRishi.Srivatsavai@Sun.COM 			val_desc_t *vdp;
115410491SRishi.Srivatsavai@Sun.COM 
115510491SRishi.Srivatsavai@Sun.COM 			vdp = malloc(sizeof (val_desc_t) * *val_cntp);
115610491SRishi.Srivatsavai@Sun.COM 			if (vdp == NULL)
115710491SRishi.Srivatsavai@Sun.COM 				status = DLADM_STATUS_NOMEM;
115810491SRishi.Srivatsavai@Sun.COM 			else
115910491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
116010491SRishi.Srivatsavai@Sun.COM 				    prop_val, *val_cntp, vdp, media);
116110491SRishi.Srivatsavai@Sun.COM 			if (status == DLADM_STATUS_OK) {
116210491SRishi.Srivatsavai@Sun.COM 				for (valc = 0; valc < *val_cntp; valc++)
116310491SRishi.Srivatsavai@Sun.COM 					ret_val[valc] = vdp[valc].vd_val;
116410491SRishi.Srivatsavai@Sun.COM 			}
116510491SRishi.Srivatsavai@Sun.COM 			free(vdp);
116610491SRishi.Srivatsavai@Sun.COM 		} else {
116710491SRishi.Srivatsavai@Sun.COM 			for (valc = 0; valc < *val_cntp; valc++) {
116810491SRishi.Srivatsavai@Sun.COM 				for (i = 0; i < pdp->pd_noptval; i++) {
116910491SRishi.Srivatsavai@Sun.COM 					if (strcmp(pdp->pd_optval[i].vd_name,
117010491SRishi.Srivatsavai@Sun.COM 					    prop_val[valc]) == 0) {
117110491SRishi.Srivatsavai@Sun.COM 						ret_val[valc] =
117210491SRishi.Srivatsavai@Sun.COM 						    pdp->pd_optval[i].vd_val;
117310491SRishi.Srivatsavai@Sun.COM 						break;
117410491SRishi.Srivatsavai@Sun.COM 					}
117510491SRishi.Srivatsavai@Sun.COM 				}
117610491SRishi.Srivatsavai@Sun.COM 				if (i == pdp->pd_noptval) {
117710491SRishi.Srivatsavai@Sun.COM 					status = DLADM_STATUS_FAILED;
117810491SRishi.Srivatsavai@Sun.COM 					break;
117910491SRishi.Srivatsavai@Sun.COM 				}
118010491SRishi.Srivatsavai@Sun.COM 			}
118110491SRishi.Srivatsavai@Sun.COM 		}
118210491SRishi.Srivatsavai@Sun.COM 	}
118310491SRishi.Srivatsavai@Sun.COM 
118410491SRishi.Srivatsavai@Sun.COM 	free(prop_val);
118510491SRishi.Srivatsavai@Sun.COM 
118610491SRishi.Srivatsavai@Sun.COM 	return (status);
118710491SRishi.Srivatsavai@Sun.COM }
118810491SRishi.Srivatsavai@Sun.COM 
11895895Syz147064 /*ARGSUSED*/
11905895Syz147064 static int
11918453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
11928453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
11935895Syz147064 {
11945895Syz147064 	char	*buf, **propvals;
11955895Syz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
11965895Syz147064 
11975895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
11985895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
11995895Syz147064 		return (DLADM_WALK_CONTINUE);
12005895Syz147064 	}
12015895Syz147064 
12025895Syz147064 	propvals = (char **)(void *)buf;
12035895Syz147064 	for (i = 0; i < valcnt; i++) {
12045895Syz147064 		propvals[i] = buf +
12055895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
12065895Syz147064 		    i * DLADM_PROP_VAL_MAX;
12075895Syz147064 	}
12085895Syz147064 
12098453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
12108453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
12115895Syz147064 		goto done;
12125895Syz147064 	}
12135895Syz147064 
12148453SAnurag.Maskey@Sun.COM 	(void) dladm_set_linkprop(handle, linkid, prop_name, propvals, valcnt,
12155895Syz147064 	    DLADM_OPT_ACTIVE);
12165895Syz147064 
12175895Syz147064 done:
12185895Syz147064 	if (buf != NULL)
12195895Syz147064 		free(buf);
12205895Syz147064 
12215895Syz147064 	return (DLADM_WALK_CONTINUE);
12225895Syz147064 }
12235895Syz147064 
12245895Syz147064 /*ARGSUSED*/
12255895Syz147064 static int
12268453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
12275895Syz147064 {
12288275SEric Cheng 	datalink_class_t	class;
12298275SEric Cheng 	dladm_status_t		status;
12308275SEric Cheng 
12318453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
12328453SAnurag.Maskey@Sun.COM 	    NULL, 0);
12338275SEric Cheng 	if (status != DLADM_STATUS_OK)
12348275SEric Cheng 		return (DLADM_WALK_TERMINATE);
12358275SEric Cheng 
12368275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
12378453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
12388275SEric Cheng 
12395895Syz147064 	return (DLADM_WALK_CONTINUE);
12405895Syz147064 }
12415895Syz147064 
12425895Syz147064 dladm_status_t
12438453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
12448453SAnurag.Maskey@Sun.COM     boolean_t any_media)
12455895Syz147064 {
12466916Sartem 	datalink_media_t	dmedia;
12476916Sartem 	uint32_t		media;
12486916Sartem 
12496916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
12506916Sartem 
12515895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
12528453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
12538453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
12548453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
12558453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
12568453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
12576916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
12588453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, NULL,
12598453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
12603448Sdh155122 	}
12613448Sdh155122 	return (DLADM_STATUS_OK);
12623147Sxc151355 }
12633147Sxc151355 
12645903Ssowmini /* ARGSUSED */
12655895Syz147064 static dladm_status_t
12668453SAnurag.Maskey@Sun.COM do_get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
12678275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
12688275SEric Cheng     uint_t flags, uint_t *perm_flags)
12693147Sxc151355 {
12708275SEric Cheng 	char			zone_name[ZONENAME_MAX];
12718275SEric Cheng 	zoneid_t		zid;
12728275SEric Cheng 	dladm_status_t		status;
12738275SEric Cheng 	char			*cp;
12747342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
12753147Sxc151355 
12766512Ssowmini 	if (flags != 0)
12776512Ssowmini 		return (DLADM_STATUS_NOTSUP);
12786512Ssowmini 
12798453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
12808275SEric Cheng 	    &status, perm_flags);
12815895Syz147064 	if (status != DLADM_STATUS_OK)
12823448Sdh155122 		return (status);
12833448Sdh155122 
12847342SAruna.Ramakrishna@Sun.COM 	cp = dip->pr_val;
12857342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&zid, cp, sizeof (zid));
12867342SAruna.Ramakrishna@Sun.COM 	free(dip);
12877342SAruna.Ramakrishna@Sun.COM 
12885895Syz147064 	*val_cnt = 1;
12895895Syz147064 	if (zid != GLOBAL_ZONEID) {
12908118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
12915895Syz147064 			return (dladm_errno2status(errno));
12928118SVasumathi.Sundaram@Sun.COM 		}
12933147Sxc151355 
12945895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
12953147Sxc151355 	} else {
12965895Syz147064 		*prop_val[0] = '\0';
12973147Sxc151355 	}
12983147Sxc151355 
12993448Sdh155122 	return (DLADM_STATUS_OK);
13003448Sdh155122 }
13013448Sdh155122 
13023448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
13033448Sdh155122 
13043448Sdh155122 static int
13053448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
13063448Sdh155122 {
13073448Sdh155122 	char			root[MAXPATHLEN];
13083448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
13093448Sdh155122 	void			*dlhandle;
13103448Sdh155122 	void			*sym;
13113448Sdh155122 	int			ret;
13123448Sdh155122 
13133448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
13143448Sdh155122 		return (-1);
13153448Sdh155122 
13163448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
13173448Sdh155122 		(void) dlclose(dlhandle);
13183448Sdh155122 		return (-1);
13193448Sdh155122 	}
13203448Sdh155122 
13213448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
13223448Sdh155122 
13233448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
13243448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
13253448Sdh155122 	(void) dlclose(dlhandle);
13263448Sdh155122 	return (ret);
13273448Sdh155122 }
13283448Sdh155122 
13293448Sdh155122 static dladm_status_t
13308453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
13318453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
13323448Sdh155122 {
13333448Sdh155122 	char		path[MAXPATHLEN];
13345895Syz147064 	char		name[MAXLINKNAMELEN];
13353448Sdh155122 	di_prof_t	prof = NULL;
13363448Sdh155122 	char		zone_name[ZONENAME_MAX];
13373448Sdh155122 	dladm_status_t	status;
13385895Syz147064 	int		ret;
13393448Sdh155122 
13403448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
13413448Sdh155122 		return (dladm_errno2status(errno));
13423448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
13433448Sdh155122 		return (dladm_errno2status(errno));
13443448Sdh155122 	if (di_prof_init(path, &prof) != 0)
13453448Sdh155122 		return (dladm_errno2status(errno));
13463448Sdh155122 
13478453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
13485895Syz147064 	if (status != DLADM_STATUS_OK)
13495895Syz147064 		goto cleanup;
13505895Syz147064 
13515895Syz147064 	if (add)
13525895Syz147064 		ret = di_prof_add_dev(prof, name);
13535895Syz147064 	else
13545895Syz147064 		ret = di_prof_add_exclude(prof, name);
13555895Syz147064 
13565895Syz147064 	if (ret != 0) {
13573448Sdh155122 		status = dladm_errno2status(errno);
13583448Sdh155122 		goto cleanup;
13593448Sdh155122 	}
13603448Sdh155122 
13613448Sdh155122 	if (di_prof_commit(prof) != 0)
13623448Sdh155122 		status = dladm_errno2status(errno);
13633448Sdh155122 cleanup:
13643448Sdh155122 	if (prof)
13653448Sdh155122 		di_prof_fini(prof);
13663448Sdh155122 
13673448Sdh155122 	return (status);
13683448Sdh155122 }
13693448Sdh155122 
13705903Ssowmini /* ARGSUSED */
13713448Sdh155122 static dladm_status_t
13728453SAnurag.Maskey@Sun.COM do_set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13738453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
13743448Sdh155122 {
13758275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
13768275SEric Cheng 	zoneid_t		zid_old, zid_new;
13778275SEric Cheng 	char			*cp;
13787342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
13797342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
13803448Sdh155122 
13813448Sdh155122 	if (val_cnt != 1)
13823448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
13833448Sdh155122 
13847342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
13857342SAruna.Ramakrishna@Sun.COM 
13868453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
13878275SEric Cheng 	    &status, NULL);
13888275SEric Cheng 	if (status != DLADM_STATUS_OK)
13898275SEric Cheng 		return (status);
13908275SEric Cheng 
13918275SEric Cheng 	cp = dip->pr_val;
13928275SEric Cheng 	(void) memcpy(&zid_old, cp, sizeof (zid_old));
13938275SEric Cheng 	free(dip);
13947342SAruna.Ramakrishna@Sun.COM 
13957342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
13963448Sdh155122 	if (zid_new == zid_old)
1397*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_OK);
1398*10616SSebastien.Roy@Sun.COM 
1399*10616SSebastien.Roy@Sun.COM 	if ((status = i_dladm_set_public_prop(handle, pdp, linkid, vdp, val_cnt,
1400*10616SSebastien.Roy@Sun.COM 	    flags, media)) != DLADM_STATUS_OK)
14015895Syz147064 		return (status);
14025895Syz147064 
1403*10616SSebastien.Roy@Sun.COM 	/*
1404*10616SSebastien.Roy@Sun.COM 	 * It is okay to fail to update the /dev entry (some vanity-named
1405*10616SSebastien.Roy@Sun.COM 	 * links do not have a /dev entry).
1406*10616SSebastien.Roy@Sun.COM 	 */
14073448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
14088453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
14098453SAnurag.Maskey@Sun.COM 		    B_FALSE);
14105895Syz147064 	}
1411*10616SSebastien.Roy@Sun.COM 	if (zid_new != GLOBAL_ZONEID)
14128453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
14133448Sdh155122 
14143448Sdh155122 	return (DLADM_STATUS_OK);
14153448Sdh155122 }
14163448Sdh155122 
14173448Sdh155122 /* ARGSUSED */
14183448Sdh155122 static dladm_status_t
14198453SAnurag.Maskey@Sun.COM do_check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14208453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14213448Sdh155122 {
14227342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
14237342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
14247342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
14257342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
14263448Sdh155122 
14273448Sdh155122 	if (val_cnt != 1)
14283448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14293448Sdh155122 
14307342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
14317342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
14327342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
14333448Sdh155122 
14348275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
14357342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
14367342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
14377342SAruna.Ramakrishna@Sun.COM 		goto done;
14387342SAruna.Ramakrishna@Sun.COM 	}
14397342SAruna.Ramakrishna@Sun.COM 
14407342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
14413448Sdh155122 		ushort_t	flags;
14423448Sdh155122 
14437342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
14443448Sdh155122 		    sizeof (flags)) < 0) {
14457342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
14467342SAruna.Ramakrishna@Sun.COM 			goto done;
14473448Sdh155122 		}
14483448Sdh155122 
14493448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
14507342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
14517342SAruna.Ramakrishna@Sun.COM 			goto done;
14523448Sdh155122 		}
14533448Sdh155122 	}
14543448Sdh155122 
14557342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
14567342SAruna.Ramakrishna@Sun.COM 
14577342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
1458*10616SSebastien.Roy@Sun.COM 	dzp->diz_linkid = linkid;
14597342SAruna.Ramakrishna@Sun.COM 
14607342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
14615895Syz147064 	return (DLADM_STATUS_OK);
14627342SAruna.Ramakrishna@Sun.COM done:
14637342SAruna.Ramakrishna@Sun.COM 	free(dzp);
14647342SAruna.Ramakrishna@Sun.COM 	return (status);
14655895Syz147064 }
14665895Syz147064 
14675903Ssowmini /* ARGSUSED */
14685895Syz147064 static dladm_status_t
14698460SArtem.Kachitchkin@Sun.COM i_dladm_maxbw_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14708275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
14718275SEric Cheng     uint_t flags, uint_t *perm_flags)
14728275SEric Cheng {
14738275SEric Cheng 	dld_ioc_macprop_t	*dip;
14748275SEric Cheng 	mac_resource_props_t	mrp;
14758275SEric Cheng 	dladm_status_t		status;
14768275SEric Cheng 
14778453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
14788275SEric Cheng 	    &status, perm_flags);
14798275SEric Cheng 	if (dip == NULL)
14808275SEric Cheng 		return (status);
14818275SEric Cheng 
14828275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
14838275SEric Cheng 	free(dip);
14848275SEric Cheng 
14858275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
14868275SEric Cheng 		(*prop_val)[0] = '\0';
14878275SEric Cheng 	} else {
14888275SEric Cheng 		(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
14898275SEric Cheng 	}
14908275SEric Cheng 	*val_cnt = 1;
14918275SEric Cheng 	return (DLADM_STATUS_OK);
14928275SEric Cheng }
14938275SEric Cheng 
14948275SEric Cheng /* ARGSUSED */
14958275SEric Cheng static dladm_status_t
14968453SAnurag.Maskey@Sun.COM do_check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14978453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
14988275SEric Cheng {
14998275SEric Cheng 	uint64_t	*maxbw;
15008275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
15018275SEric Cheng 
15028275SEric Cheng 	if (val_cnt != 1)
15038275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
15048275SEric Cheng 
15058275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
15068275SEric Cheng 	if (maxbw == NULL)
15078275SEric Cheng 		return (DLADM_STATUS_NOMEM);
15088275SEric Cheng 
15098275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
15108275SEric Cheng 	if (status != DLADM_STATUS_OK) {
15118275SEric Cheng 		free(maxbw);
15128275SEric Cheng 		return (status);
15138275SEric Cheng 	}
15148275SEric Cheng 
15158275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
15168275SEric Cheng 		free(maxbw);
15178275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
15188275SEric Cheng 	}
15198275SEric Cheng 
15208275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
15218275SEric Cheng 	return (DLADM_STATUS_OK);
15228275SEric Cheng }
15238275SEric Cheng 
15248275SEric Cheng /* ARGSUSED */
15258275SEric Cheng dladm_status_t
15268275SEric Cheng do_extract_maxbw(val_desc_t *vdp, void *arg, uint_t cnt)
15278275SEric Cheng {
15288275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
15298275SEric Cheng 
15308275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
15318275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
15328275SEric Cheng 
15338275SEric Cheng 	return (DLADM_STATUS_OK);
15348275SEric Cheng }
15358275SEric Cheng 
15368275SEric Cheng /* ARGSUSED */
15378275SEric Cheng static dladm_status_t
15388460SArtem.Kachitchkin@Sun.COM i_dladm_cpus_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15398275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15408275SEric Cheng     uint_t flags, uint_t *perm_flags)
15418275SEric Cheng {
15428275SEric Cheng 	dld_ioc_macprop_t	*dip;
15438275SEric Cheng 	mac_resource_props_t	mrp;
15448275SEric Cheng 	int			i;
15458275SEric Cheng 	uint32_t		ncpus;
15468275SEric Cheng 	uchar_t			*cp;
15478275SEric Cheng 	dladm_status_t		status;
15488275SEric Cheng 
15498453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
15508275SEric Cheng 	    &status, perm_flags);
15518275SEric Cheng 	if (dip == NULL)
15528275SEric Cheng 		return (status);
15538275SEric Cheng 
15548275SEric Cheng 	cp = (uchar_t *)dip->pr_val;
15558275SEric Cheng 	(void) memcpy(&mrp, cp, sizeof (mac_resource_props_t));
15568275SEric Cheng 	free(dip);
15578275SEric Cheng 
15588275SEric Cheng 	ncpus = mrp.mrp_ncpus;
15598275SEric Cheng 
15608275SEric Cheng 	if (ncpus > *val_cnt)
15618275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
15628275SEric Cheng 
15638275SEric Cheng 	if (ncpus == 0) {
15648275SEric Cheng 		(*prop_val)[0] = '\0';
15658275SEric Cheng 		*val_cnt = 1;
15668275SEric Cheng 		return (DLADM_STATUS_OK);
15678275SEric Cheng 	}
15688275SEric Cheng 
15698275SEric Cheng 	*val_cnt = ncpus;
15708275SEric Cheng 	for (i = 0; i < ncpus; i++) {
15718275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
15728275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
15738275SEric Cheng 	}
15748275SEric Cheng 	return (DLADM_STATUS_OK);
15758275SEric Cheng }
15768275SEric Cheng 
15778275SEric Cheng /* ARGSUSED */
15788275SEric Cheng static dladm_status_t
15798453SAnurag.Maskey@Sun.COM do_set_res(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15808453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
15818275SEric Cheng {
15828275SEric Cheng 	mac_resource_props_t	mrp;
15838275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
15848275SEric Cheng 	dld_ioc_macprop_t	*dip;
15858275SEric Cheng 
15868275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
15878275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
15888275SEric Cheng 	    flags, &status);
15898275SEric Cheng 
15908275SEric Cheng 	if (dip == NULL)
15918275SEric Cheng 		return (status);
15928275SEric Cheng 
15938275SEric Cheng 	if (vdp->vd_val == RESET_VAL) {
15948275SEric Cheng 		switch (dip->pr_num) {
15958275SEric Cheng 		case MAC_PROP_MAXBW:
15968275SEric Cheng 			mrp.mrp_maxbw = MRP_MAXBW_RESETVAL;
15978275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
15988275SEric Cheng 			break;
15998275SEric Cheng 		case MAC_PROP_PRIO:
16008275SEric Cheng 			mrp.mrp_priority = MPL_RESET;
16018275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16028275SEric Cheng 			break;
16038275SEric Cheng 		default:
16048275SEric Cheng 			free(dip);
16058275SEric Cheng 			return (DLADM_STATUS_BADARG);
16068275SEric Cheng 		}
16078275SEric Cheng 	} else {
16088275SEric Cheng 		switch (dip->pr_num) {
16098275SEric Cheng 		case MAC_PROP_MAXBW:
16108275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_maxbw,
16118275SEric Cheng 			    sizeof (uint64_t));
16128275SEric Cheng 			mrp.mrp_mask = MRP_MAXBW;
16138275SEric Cheng 			break;
16148275SEric Cheng 		case MAC_PROP_PRIO:
16158275SEric Cheng 			bcopy((void *)vdp->vd_val, &mrp.mrp_priority,
16168275SEric Cheng 			    sizeof (mac_priority_level_t));
16178275SEric Cheng 			mrp.mrp_mask = MRP_PRIORITY;
16188275SEric Cheng 			break;
16198275SEric Cheng 		default:
16208275SEric Cheng 			free(dip);
16218275SEric Cheng 			return (DLADM_STATUS_BADARG);
16228275SEric Cheng 		}
16238275SEric Cheng 	}
16248275SEric Cheng 
16258275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16268453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16278275SEric Cheng 	free(dip);
16288275SEric Cheng 	return (status);
16298275SEric Cheng }
16308275SEric Cheng 
16318275SEric Cheng /* ARGSUSED */
16328275SEric Cheng static dladm_status_t
16338453SAnurag.Maskey@Sun.COM do_set_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16348453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
16358275SEric Cheng {
16368275SEric Cheng 	mac_resource_props_t	mrp;
16378275SEric Cheng 	dladm_status_t		status;
16388275SEric Cheng 	dld_ioc_macprop_t	*dip;
16398275SEric Cheng 	datalink_class_t	class;
16408275SEric Cheng 
16418275SEric Cheng 	/*
16428275SEric Cheng 	 * CPU bindings can be set on VNIC and regular physical links.
16438275SEric Cheng 	 * However VNICs fails the dladm_phys_info test(). So apply
16448275SEric Cheng 	 * the phys_info test only on physical links.
16458275SEric Cheng 	 */
16468453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, NULL, &class,
16478275SEric Cheng 	    NULL, NULL, 0)) != DLADM_STATUS_OK) {
16488275SEric Cheng 		return (status);
16498275SEric Cheng 	}
16508275SEric Cheng 
16518275SEric Cheng 	/*
16528275SEric Cheng 	 * We set intr_cpu to -1. The interrupt will be retargetted,
16538275SEric Cheng 	 * if possible when the setup is complete in MAC.
16548275SEric Cheng 	 */
16558275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
16568275SEric Cheng 	mrp.mrp_mask = MRP_CPUS;
16578275SEric Cheng 	if (vdp != NULL && vdp->vd_val != RESET_VAL) {
16588275SEric Cheng 		mac_resource_props_t	*vmrp;
16598275SEric Cheng 
16608275SEric Cheng 		vmrp = (mac_resource_props_t *)vdp->vd_val;
16618275SEric Cheng 		if (vmrp->mrp_ncpus > 0) {
16628275SEric Cheng 			bcopy(vmrp, &mrp, sizeof (mac_resource_props_t));
16638275SEric Cheng 			mrp.mrp_mask = MRP_CPUS;
16648275SEric Cheng 		}
16658275SEric Cheng 		mrp.mrp_mask |= MRP_CPUS_USERSPEC;
16668275SEric Cheng 		mrp.mrp_fanout_mode = MCM_CPUS;
16678275SEric Cheng 		mrp.mrp_intr_cpu = -1;
16688275SEric Cheng 	}
16698275SEric Cheng 
16708275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name,
16718275SEric Cheng 	    flags, &status);
16728275SEric Cheng 	if (dip == NULL)
16738275SEric Cheng 		return (status);
16748275SEric Cheng 
16758275SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
16768453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
16778275SEric Cheng 	free(dip);
16788275SEric Cheng 	return (status);
16798275SEric Cheng }
16808275SEric Cheng 
16818275SEric Cheng /* ARGSUSED */
16828275SEric Cheng static dladm_status_t
16838453SAnurag.Maskey@Sun.COM do_check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16848453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
16858275SEric Cheng {
16868275SEric Cheng 	uint32_t		cpuid;
16878275SEric Cheng 	int			i, j, rc;
16888275SEric Cheng 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
16898275SEric Cheng 	mac_resource_props_t	*mrp;
16908275SEric Cheng 
16918275SEric Cheng 	mrp = malloc(sizeof (mac_resource_props_t));
16928275SEric Cheng 	if (mrp == NULL)
16938275SEric Cheng 		return (DLADM_STATUS_NOMEM);
16948275SEric Cheng 
16958275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
16968275SEric Cheng 		errno = 0;
16978275SEric Cheng 		cpuid = strtol(prop_val[i], (char **)NULL, 10);
16988275SEric Cheng 		if (errno != 0 || cpuid >= nproc) {
16998275SEric Cheng 			free(mrp);
17008275SEric Cheng 			return (DLADM_STATUS_CPUMAX);
17018275SEric Cheng 		}
17028275SEric Cheng 		rc = p_online(cpuid, P_STATUS);
17038275SEric Cheng 		if (rc < 1) {
17048275SEric Cheng 			free(mrp);
17058275SEric Cheng 			return (DLADM_STATUS_CPUERR);
17068275SEric Cheng 		}
17078275SEric Cheng 		if (rc != P_ONLINE) {
17088275SEric Cheng 			free(mrp);
17098275SEric Cheng 			return (DLADM_STATUS_CPUNOTONLINE);
17108275SEric Cheng 		}
17118275SEric Cheng 		mrp->mrp_cpu[i] = cpuid;
17128275SEric Cheng 	}
17138275SEric Cheng 	mrp->mrp_ncpus = (uint32_t)val_cnt;
17148275SEric Cheng 
17158275SEric Cheng 	/* Check for duplicates */
17168275SEric Cheng 	for (i = 0; i < val_cnt; i++) {
17178275SEric Cheng 		for (j = 0; j < val_cnt; j++) {
17188275SEric Cheng 			if (i != j && mrp->mrp_cpu[i] == mrp->mrp_cpu[j]) {
17198275SEric Cheng 				free(mrp);
17208275SEric Cheng 				return (DLADM_STATUS_BADARG);
17218275SEric Cheng 			}
17228275SEric Cheng 		}
17238275SEric Cheng 	}
17248275SEric Cheng 	vdp->vd_val = (uintptr_t)mrp;
17258275SEric Cheng 
17268275SEric Cheng 	return (DLADM_STATUS_OK);
17278275SEric Cheng }
17288275SEric Cheng 
17298275SEric Cheng /* ARGSUSED */
17308275SEric Cheng dladm_status_t
17318275SEric Cheng do_extract_cpus(val_desc_t *vdp, void *arg, uint_t cnt)
17328275SEric Cheng {
17338275SEric Cheng 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
17348275SEric Cheng 	mac_resource_props_t	*vmrp = (mac_resource_props_t *)vdp->vd_val;
17358275SEric Cheng 	int			i;
17368275SEric Cheng 
17378275SEric Cheng 	for (i = 0; i < vmrp->mrp_ncpus; i++) {
17388275SEric Cheng 		mrp->mrp_cpu[i] = vmrp->mrp_cpu[i];
17398275SEric Cheng 	}
17408275SEric Cheng 	mrp->mrp_ncpus = vmrp->mrp_ncpus;
17418275SEric Cheng 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
17428275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
17439055SMichael.Lim@Sun.COM 	mrp->mrp_intr_cpu = -1;
17448275SEric Cheng 
17458275SEric Cheng 	return (DLADM_STATUS_OK);
17468275SEric Cheng }
17478275SEric Cheng 
17488275SEric Cheng /* ARGSUSED */
17498275SEric Cheng static dladm_status_t
17508460SArtem.Kachitchkin@Sun.COM i_dladm_priority_get(dladm_handle_t handle, prop_desc_t *pdp,
17518460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
17528460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
17538275SEric Cheng {
17548275SEric Cheng 	dld_ioc_macprop_t	*dip;
17558275SEric Cheng 	mac_resource_props_t	mrp;
17568275SEric Cheng 	mac_priority_level_t	pri;
17578275SEric Cheng 	dladm_status_t		status;
17588275SEric Cheng 
17598453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
17608275SEric Cheng 	    &status, perm_flags);
17618275SEric Cheng 	if (dip == NULL)
17628275SEric Cheng 		return (status);
17638275SEric Cheng 
17648275SEric Cheng 	bcopy(dip->pr_val, &mrp, sizeof (mac_resource_props_t));
17658275SEric Cheng 	free(dip);
17668275SEric Cheng 
17678275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
17688275SEric Cheng 	    mrp.mrp_priority;
17698275SEric Cheng 
17708275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
17718275SEric Cheng 	*val_cnt = 1;
17728275SEric Cheng 	return (DLADM_STATUS_OK);
17738275SEric Cheng }
17748275SEric Cheng 
17758275SEric Cheng /* ARGSUSED */
17768275SEric Cheng static dladm_status_t
17778453SAnurag.Maskey@Sun.COM do_check_priority(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
17788453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
17798275SEric Cheng {
17808275SEric Cheng 	mac_priority_level_t	*pri;
17818275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
17828275SEric Cheng 
17838275SEric Cheng 	if (val_cnt != 1)
17848275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
17858275SEric Cheng 
17868275SEric Cheng 	pri = malloc(sizeof (mac_priority_level_t));
17878275SEric Cheng 	if (pri == NULL)
17888275SEric Cheng 		return (DLADM_STATUS_NOMEM);
17898275SEric Cheng 
17908275SEric Cheng 	status = dladm_str2pri(*prop_val, pri);
17918275SEric Cheng 	if (status != DLADM_STATUS_OK) {
17928275SEric Cheng 		free(pri);
17938275SEric Cheng 		return (status);
17948275SEric Cheng 	}
17958275SEric Cheng 
17968275SEric Cheng 	if (*pri < MPL_LOW || *pri > MPL_HIGH) {
17978275SEric Cheng 		free(pri);
17988275SEric Cheng 		return (DLADM_STATUS_BADVAL);
17998275SEric Cheng 	}
18008275SEric Cheng 
18018275SEric Cheng 	vdp->vd_val = (uintptr_t)pri;
18028275SEric Cheng 	return (DLADM_STATUS_OK);
18038275SEric Cheng }
18048275SEric Cheng 
18058275SEric Cheng /* ARGSUSED */
18068275SEric Cheng dladm_status_t
18078275SEric Cheng do_extract_priority(val_desc_t *vdp, void *arg, uint_t cnt)
18088275SEric Cheng {
18098275SEric Cheng 	mac_resource_props_t *mrp = (mac_resource_props_t *)arg;
18108275SEric Cheng 
18118275SEric Cheng 	bcopy((char *)vdp->vd_val, &mrp->mrp_priority,
18128275SEric Cheng 	    sizeof (mac_priority_level_t));
18138275SEric Cheng 	mrp->mrp_mask |= MRP_PRIORITY;
18148275SEric Cheng 
18158275SEric Cheng 	return (DLADM_STATUS_OK);
18168275SEric Cheng }
18178275SEric Cheng 
18188275SEric Cheng /* ARGSUSED */
18198275SEric Cheng static dladm_status_t
18208453SAnurag.Maskey@Sun.COM do_get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
18218275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
18228275SEric Cheng     uint_t flags, uint_t *perm_flags)
18235895Syz147064 {
18247342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
18257342SAruna.Ramakrishna@Sun.COM 	int		i, len;
18267342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
18277342SAruna.Ramakrishna@Sun.COM 	dld_ioc_macprop_t	*dip;
18285895Syz147064 
18296789Sam223141 	if (flags & MAC_PROP_DEFAULT)
18307776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
18316512Ssowmini 
18325895Syz147064 	*val_cnt = 1;
18338453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
18348275SEric Cheng 	    &status, perm_flags);
18357342SAruna.Ramakrishna@Sun.COM 	if (dip == NULL) {
18365895Syz147064 		(*prop_val)[0] = '\0';
18378275SEric Cheng 		return (DLADM_STATUS_OK);
18385895Syz147064 	}
18397342SAruna.Ramakrishna@Sun.COM 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
18405895Syz147064 
18417342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
18425895Syz147064 		if (i != 0) {
18435895Syz147064 			(void) snprintf(*prop_val + len,
18445895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
18455895Syz147064 			len += 1;
18465895Syz147064 		}
18475895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
18487342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
18497342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
18507342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
18515895Syz147064 			(void) snprintf(*prop_val + len,
18525895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
18535895Syz147064 			    AP_ANCHOR);
18545895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
18555895Syz147064 		}
18565895Syz147064 	}
18577342SAruna.Ramakrishna@Sun.COM 	free(dip);
18585895Syz147064 done:
18595895Syz147064 	return (DLADM_STATUS_OK);
18605895Syz147064 }
18615895Syz147064 
18625895Syz147064 /*
18635895Syz147064  * Add the specified module to the dlautopush structure; returns a
18645895Syz147064  * DLADM_STATUS_* code.
18655895Syz147064  */
18665895Syz147064 dladm_status_t
18675895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
18685895Syz147064 {
18695895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
18705895Syz147064 		return (DLADM_STATUS_BADVAL);
18715895Syz147064 
18725895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
18735895Syz147064 		/*
18745895Syz147064 		 * We don't allow multiple anchors, and the anchor must
18755895Syz147064 		 * be after at least one module.
18765895Syz147064 		 */
18775895Syz147064 		if (dlap->dap_anchor != 0)
18785895Syz147064 			return (DLADM_STATUS_BADVAL);
18795895Syz147064 		if (dlap->dap_npush == 0)
18805895Syz147064 			return (DLADM_STATUS_BADVAL);
18815895Syz147064 
18825895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
18835895Syz147064 		return (DLADM_STATUS_OK);
18845895Syz147064 	}
18858957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
18865895Syz147064 		return (DLADM_STATUS_BADVALCNT);
18875895Syz147064 
18885895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
18895895Syz147064 	    FMNAMESZ + 1);
18905895Syz147064 
18915895Syz147064 	return (DLADM_STATUS_OK);
18925895Syz147064 }
18935895Syz147064 
18945895Syz147064 /*
18955895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
18965895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
18975895Syz147064  * latter is used in the autopush(1M) file.
18985895Syz147064  */
18995895Syz147064 /* ARGSUSED */
19005895Syz147064 static dladm_status_t
19018453SAnurag.Maskey@Sun.COM do_check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19028453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
19035895Syz147064 {
19045895Syz147064 	char			*module;
19055895Syz147064 	struct dlautopush	*dlap;
19065895Syz147064 	dladm_status_t		status;
19075895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
19085895Syz147064 	char			delimiters[4];
19095895Syz147064 
19105895Syz147064 	if (val_cnt != 1)
19115895Syz147064 		return (DLADM_STATUS_BADVALCNT);
19125895Syz147064 
19137342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
19147342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
19157342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
19167342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
19173448Sdh155122 
19187342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
19197342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
19207342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
19217342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
19227342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
19237342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
19247342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
19257342SAruna.Ramakrishna@Sun.COM 				return (status);
19267342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
19277342SAruna.Ramakrishna@Sun.COM 		}
19287342SAruna.Ramakrishna@Sun.COM 
19297342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
19307342SAruna.Ramakrishna@Sun.COM 	} else {
19317342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
19325895Syz147064 	}
19333448Sdh155122 	return (DLADM_STATUS_OK);
19343448Sdh155122 }
19353448Sdh155122 
19367663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
19377663SSowmini.Varadhan@Sun.COM 
19385903Ssowmini /* ARGSUSED */
19393448Sdh155122 static dladm_status_t
19408453SAnurag.Maskey@Sun.COM do_get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
19418453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
19428453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
19433448Sdh155122 {
19445895Syz147064 	wl_rates_t	*wrp;
19455895Syz147064 	uint_t		i;
19465895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
19475895Syz147064 
19487663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
19497663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
19507663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
19515895Syz147064 
19528453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
19538453SAnurag.Maskey@Sun.COM 	    B_FALSE);
19545895Syz147064 	if (status != DLADM_STATUS_OK)
19555895Syz147064 		goto done;
19565895Syz147064 
19575895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
19585895Syz147064 		status = DLADM_STATUS_TOOSMALL;
19595895Syz147064 		goto done;
19605895Syz147064 	}
19615895Syz147064 
19625895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
19635895Syz147064 		prop_val[0][0] = '\0';
19645895Syz147064 		*val_cnt = 1;
19655895Syz147064 		goto done;
19665895Syz147064 	}
19675895Syz147064 
19685895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
19695895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
19705895Syz147064 		    wrp->wl_rates_rates[i] % 2,
19715895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
19725895Syz147064 	}
19735895Syz147064 	*val_cnt = wrp->wl_rates_num;
19748275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
19753448Sdh155122 
19765895Syz147064 done:
19777663SSowmini.Varadhan@Sun.COM 	free(wrp);
19785895Syz147064 	return (status);
19795895Syz147064 }
19805895Syz147064 
19815895Syz147064 static dladm_status_t
19828453SAnurag.Maskey@Sun.COM do_get_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19838275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
19848275SEric Cheng     uint_t flags, uint_t *perm_flags)
19855895Syz147064 {
19868118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
19878453SAnurag.Maskey@Sun.COM 		return (i_dladm_speed_get(handle, pdp, linkid, prop_val,
19888275SEric Cheng 		    val_cnt, flags, perm_flags));
19898118SVasumathi.Sundaram@Sun.COM 	}
19905960Ssowmini 
19918453SAnurag.Maskey@Sun.COM 	return (do_get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
19928275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
19935895Syz147064 }
19945895Syz147064 
19956512Ssowmini /* ARGSUSED */
19965895Syz147064 static dladm_status_t
19978453SAnurag.Maskey@Sun.COM do_get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
19988275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
19998275SEric Cheng     uint_t flags, uint_t *perm_flags)
20005895Syz147064 {
20015960Ssowmini 	switch (media) {
20025960Ssowmini 	case DL_ETHER:
20036512Ssowmini 		/*
20046512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
20056512Ssowmini 		 * links can have a speed of 5.5 Gbps.
20066512Ssowmini 		 */
20076512Ssowmini 		return (DLADM_STATUS_NOTSUP);
20085960Ssowmini 
20095960Ssowmini 	case DL_WIFI:
20108453SAnurag.Maskey@Sun.COM 		return (do_get_rate_common(handle, pdp, linkid, prop_val,
20118453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
20125960Ssowmini 	default:
20135960Ssowmini 		return (DLADM_STATUS_BADARG);
20145960Ssowmini 	}
20155895Syz147064 }
20165895Syz147064 
20175895Syz147064 static dladm_status_t
20188453SAnurag.Maskey@Sun.COM do_set_rate(dladm_handle_t handle, datalink_id_t linkid,
20198453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
20205895Syz147064 {
20215895Syz147064 	int		i;
20225895Syz147064 	uint_t		len;
20235895Syz147064 	wl_rates_t	*wrp;
20245895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
20255895Syz147064 
20267663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
20277663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
20285895Syz147064 		return (DLADM_STATUS_NOMEM);
20295895Syz147064 
20307663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
20315895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
20325895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
20335895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
20345895Syz147064 
20355895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
20365895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
20378453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
20388453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
20395895Syz147064 
20407663SSowmini.Varadhan@Sun.COM 	free(wrp);
20415895Syz147064 	return (status);
20425895Syz147064 }
20433448Sdh155122 
20445903Ssowmini /* ARGSUSED */
20455895Syz147064 static dladm_status_t
20468453SAnurag.Maskey@Sun.COM do_set_rate_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20475960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
20485895Syz147064 {
20495895Syz147064 	dladm_wlan_rates_t	rates;
20505895Syz147064 	dladm_status_t		status;
20515895Syz147064 
20525960Ssowmini 	/*
20535960Ssowmini 	 * can currently set rate on WIFI links only.
20545960Ssowmini 	 */
20555960Ssowmini 	if (media != DL_WIFI)
20565960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
20575960Ssowmini 
20585895Syz147064 	if (val_cnt != 1)
20595895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20605895Syz147064 
20615895Syz147064 	rates.wr_cnt = 1;
20625895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
20635895Syz147064 
20648453SAnurag.Maskey@Sun.COM 	status = do_set_rate(handle, linkid, &rates);
20655895Syz147064 
20665895Syz147064 done:
20675895Syz147064 	return (status);
20685895Syz147064 }
20693448Sdh155122 
20705895Syz147064 /* ARGSUSED */
20715895Syz147064 static dladm_status_t
20728453SAnurag.Maskey@Sun.COM do_check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
20738453SAnurag.Maskey@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
20745895Syz147064 {
20755895Syz147064 	int		i;
20765895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
20775895Syz147064 	char		*buf, **modval;
20785895Syz147064 	dladm_status_t	status;
20798118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
20805895Syz147064 
20815895Syz147064 	if (val_cnt != 1)
20825895Syz147064 		return (DLADM_STATUS_BADVALCNT);
20835895Syz147064 
20845895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
20855895Syz147064 	    MAX_SUPPORT_RATES);
20865895Syz147064 	if (buf == NULL) {
20875895Syz147064 		status = DLADM_STATUS_NOMEM;
20885895Syz147064 		goto done;
20895895Syz147064 	}
20903448Sdh155122 
20915895Syz147064 	modval = (char **)(void *)buf;
20925895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
20935895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
20945895Syz147064 		    i * DLADM_STRSIZE;
20955895Syz147064 	}
20965895Syz147064 
20978453SAnurag.Maskey@Sun.COM 	status = do_get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
20988453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
20995895Syz147064 	if (status != DLADM_STATUS_OK)
21005895Syz147064 		goto done;
21015895Syz147064 
21025895Syz147064 	for (i = 0; i < modval_cnt; i++) {
21035895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
21045903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
21055903Ssowmini 			    (atof(*prop_val) * 2);
21065895Syz147064 			status = DLADM_STATUS_OK;
21073448Sdh155122 			break;
21083448Sdh155122 		}
21095895Syz147064 	}
21105895Syz147064 	if (i == modval_cnt)
21115895Syz147064 		status = DLADM_STATUS_BADVAL;
21125895Syz147064 done:
21135895Syz147064 	free(buf);
21145895Syz147064 	return (status);
21155895Syz147064 }
21165895Syz147064 
21175895Syz147064 static dladm_status_t
21188453SAnurag.Maskey@Sun.COM do_get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
21198453SAnurag.Maskey@Sun.COM     int buflen)
21205895Syz147064 {
21218453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
21227663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
21235895Syz147064 }
21245895Syz147064 
21255903Ssowmini /* ARGSUSED */
21265895Syz147064 static dladm_status_t
21278453SAnurag.Maskey@Sun.COM do_get_channel_prop(dladm_handle_t handle, prop_desc_t *pdp,
21288453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
21298453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
21305895Syz147064 {
21315895Syz147064 	uint32_t	channel;
21327663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
21335895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21347663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
21355895Syz147064 
21368453SAnurag.Maskey@Sun.COM 	if ((status = do_get_phyconf(handle, linkid, buf, sizeof (buf)))
21377663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
21385895Syz147064 		goto done;
21395895Syz147064 
21407663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
21417663SSowmini.Varadhan@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) {
21425895Syz147064 		status = DLADM_STATUS_NOTFOUND;
21435895Syz147064 		goto done;
21445895Syz147064 	}
21455895Syz147064 
21465895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
21475895Syz147064 	*val_cnt = 1;
21488275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
21495895Syz147064 done:
21505895Syz147064 	return (status);
21515895Syz147064 }
21525895Syz147064 
21535895Syz147064 static dladm_status_t
21548453SAnurag.Maskey@Sun.COM do_get_powermode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
21558453SAnurag.Maskey@Sun.COM     int buflen)
21565895Syz147064 {
21578453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_POWER_MODE,
21587663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
21595895Syz147064 }
21605895Syz147064 
21615903Ssowmini /* ARGSUSED */
21625895Syz147064 static dladm_status_t
21638453SAnurag.Maskey@Sun.COM do_get_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
21648453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
21658453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
21665895Syz147064 {
21677663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
21685895Syz147064 	const char	*s;
21697663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
21705895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
21715895Syz147064 
21728453SAnurag.Maskey@Sun.COM 	if ((status = do_get_powermode(handle, linkid, buf, sizeof (buf)))
21737663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
21745895Syz147064 		goto done;
21755895Syz147064 
21767663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
21777663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
21785895Syz147064 	case WL_PM_AM:
21795895Syz147064 		s = "off";
21805895Syz147064 		break;
21815895Syz147064 	case WL_PM_MPS:
21825895Syz147064 		s = "max";
21835895Syz147064 		break;
21845895Syz147064 	case WL_PM_FAST:
21855895Syz147064 		s = "fast";
21863448Sdh155122 		break;
21873448Sdh155122 	default:
21885895Syz147064 		status = DLADM_STATUS_NOTFOUND;
21895895Syz147064 		goto done;
21905895Syz147064 	}
21915895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
21925895Syz147064 	*val_cnt = 1;
21938275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
21945895Syz147064 done:
21955895Syz147064 	return (status);
21965895Syz147064 }
21975895Syz147064 
21985895Syz147064 static dladm_status_t
21998453SAnurag.Maskey@Sun.COM do_set_powermode(dladm_handle_t handle, datalink_id_t linkid,
22008453SAnurag.Maskey@Sun.COM     dladm_wlan_powermode_t *pm)
22015895Syz147064 {
22025895Syz147064 	wl_ps_mode_t    ps_mode;
22035895Syz147064 
22045895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
22055895Syz147064 
22065895Syz147064 	switch (*pm) {
22075895Syz147064 	case DLADM_WLAN_PM_OFF:
22085895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
22093448Sdh155122 		break;
22105895Syz147064 	case DLADM_WLAN_PM_MAX:
22115895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
22125895Syz147064 		break;
22135895Syz147064 	case DLADM_WLAN_PM_FAST:
22145895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
22155895Syz147064 		break;
22165895Syz147064 	default:
22175895Syz147064 		return (DLADM_STATUS_NOTSUP);
22183448Sdh155122 	}
22198453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
22208453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
22215895Syz147064 }
22225895Syz147064 
22235895Syz147064 /* ARGSUSED */
22245895Syz147064 static dladm_status_t
22258453SAnurag.Maskey@Sun.COM do_set_powermode_prop(dladm_handle_t handle, prop_desc_t *pdp,
22268453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
22278453SAnurag.Maskey@Sun.COM     datalink_media_t media)
22285895Syz147064 {
22295895Syz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
22305895Syz147064 	dladm_status_t status;
22315895Syz147064 
22325895Syz147064 	if (val_cnt != 1)
22335895Syz147064 		return (DLADM_STATUS_BADVALCNT);
22345895Syz147064 
22358453SAnurag.Maskey@Sun.COM 	status = do_set_powermode(handle, linkid, &powermode);
22363448Sdh155122 
22373448Sdh155122 	return (status);
22383448Sdh155122 }
22393448Sdh155122 
22403448Sdh155122 static dladm_status_t
22418453SAnurag.Maskey@Sun.COM do_get_radio(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
22423448Sdh155122 {
22438453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RADIO,
22448453SAnurag.Maskey@Sun.COM 	    buflen, B_FALSE));
22455895Syz147064 }
22463448Sdh155122 
22475903Ssowmini /* ARGSUSED */
22485895Syz147064 static dladm_status_t
22498453SAnurag.Maskey@Sun.COM do_get_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
22508275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
22518275SEric Cheng     uint_t flags, uint_t *perm_flags)
22525895Syz147064 {
22535895Syz147064 	wl_radio_t	radio;
22545895Syz147064 	const char	*s;
22557663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
22565895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
22573448Sdh155122 
22588453SAnurag.Maskey@Sun.COM 	if ((status = do_get_radio(handle, linkid, buf, sizeof (buf)))
22597663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
22605895Syz147064 		goto done;
22613448Sdh155122 
22627663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
22635895Syz147064 	switch (radio) {
22645895Syz147064 	case B_TRUE:
22655895Syz147064 		s = "on";
22665895Syz147064 		break;
22675895Syz147064 	case B_FALSE:
22685895Syz147064 		s = "off";
22695895Syz147064 		break;
22705895Syz147064 	default:
22715895Syz147064 		status = DLADM_STATUS_NOTFOUND;
22725895Syz147064 		goto done;
22735895Syz147064 	}
22745895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
22755895Syz147064 	*val_cnt = 1;
22768275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
22775895Syz147064 done:
22783448Sdh155122 	return (status);
22793448Sdh155122 }
22803448Sdh155122 
22813448Sdh155122 static dladm_status_t
22828453SAnurag.Maskey@Sun.COM do_set_radio(dladm_handle_t handle, datalink_id_t linkid,
22838453SAnurag.Maskey@Sun.COM     dladm_wlan_radio_t *radio)
22843448Sdh155122 {
22855895Syz147064 	wl_radio_t r;
22863448Sdh155122 
22875895Syz147064 	switch (*radio) {
22885895Syz147064 	case DLADM_WLAN_RADIO_ON:
22895895Syz147064 		r = B_TRUE;
22905895Syz147064 		break;
22915895Syz147064 	case DLADM_WLAN_RADIO_OFF:
22925895Syz147064 		r = B_FALSE;
22935895Syz147064 		break;
22945895Syz147064 	default:
22955895Syz147064 		return (DLADM_STATUS_NOTSUP);
22965895Syz147064 	}
22978453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
22987663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
22995895Syz147064 }
23003448Sdh155122 
23015895Syz147064 /* ARGSUSED */
23025895Syz147064 static dladm_status_t
23038453SAnurag.Maskey@Sun.COM do_set_radio_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2304*10616SSebastien.Roy@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
23055895Syz147064 {
23065895Syz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
23075895Syz147064 	dladm_status_t status;
23083448Sdh155122 
23095895Syz147064 	if (val_cnt != 1)
23105895Syz147064 		return (DLADM_STATUS_BADVALCNT);
23115895Syz147064 
23128453SAnurag.Maskey@Sun.COM 	status = do_set_radio(handle, linkid, &radio);
23133448Sdh155122 
23143448Sdh155122 	return (status);
23153448Sdh155122 }
23163448Sdh155122 
2317*10616SSebastien.Roy@Sun.COM /* ARGSUSED */
2318*10616SSebastien.Roy@Sun.COM static dladm_status_t
2319*10616SSebastien.Roy@Sun.COM do_check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
2320*10616SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
2321*10616SSebastien.Roy@Sun.COM     datalink_media_t media)
2322*10616SSebastien.Roy@Sun.COM {
2323*10616SSebastien.Roy@Sun.COM 	int32_t	hlim;
2324*10616SSebastien.Roy@Sun.COM 	char	*ep;
2325*10616SSebastien.Roy@Sun.COM 
2326*10616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
2327*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2328*10616SSebastien.Roy@Sun.COM 
2329*10616SSebastien.Roy@Sun.COM 	errno = 0;
2330*10616SSebastien.Roy@Sun.COM 	hlim = strtol(*prop_val, &ep, 10);
2331*10616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || hlim < 1 ||
2332*10616SSebastien.Roy@Sun.COM 	    hlim > (int32_t)UINT8_MAX)
2333*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
2334*10616SSebastien.Roy@Sun.COM 	vdp->vd_val = hlim;
2335*10616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
2336*10616SSebastien.Roy@Sun.COM }
2337*10616SSebastien.Roy@Sun.COM 
2338*10616SSebastien.Roy@Sun.COM /* ARGSUSED */
2339*10616SSebastien.Roy@Sun.COM static dladm_status_t
2340*10616SSebastien.Roy@Sun.COM do_check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2341*10616SSebastien.Roy@Sun.COM     char **prop_val, uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
2342*10616SSebastien.Roy@Sun.COM {
2343*10616SSebastien.Roy@Sun.COM 	int32_t	elim;
2344*10616SSebastien.Roy@Sun.COM 	char	*ep;
2345*10616SSebastien.Roy@Sun.COM 
2346*10616SSebastien.Roy@Sun.COM 	if (media != DL_IPV6)
2347*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADARG);
2348*10616SSebastien.Roy@Sun.COM 
2349*10616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
2350*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2351*10616SSebastien.Roy@Sun.COM 
2352*10616SSebastien.Roy@Sun.COM 	errno = 0;
2353*10616SSebastien.Roy@Sun.COM 	elim = strtol(*prop_val, &ep, 10);
2354*10616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || elim < 0 ||
2355*10616SSebastien.Roy@Sun.COM 	    elim > (int32_t)UINT8_MAX)
2356*10616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
2357*10616SSebastien.Roy@Sun.COM 	vdp->vd_val = elim;
2358*10616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
2359*10616SSebastien.Roy@Sun.COM }
2360*10616SSebastien.Roy@Sun.COM 
23615895Syz147064 static dladm_status_t
23628453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
23638453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
23643448Sdh155122 {
23655895Syz147064 	char		buf[MAXLINELEN];
23665895Syz147064 	int		i;
23675895Syz147064 	dladm_conf_t	conf;
23685895Syz147064 	dladm_status_t	status;
23693448Sdh155122 
23708453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
23715895Syz147064 	if (status != DLADM_STATUS_OK)
23725895Syz147064 		return (status);
23733448Sdh155122 
23745895Syz147064 	/*
23755895Syz147064 	 * reset case.
23765895Syz147064 	 */
23775895Syz147064 	if (val_cnt == 0) {
23788453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
23795895Syz147064 		if (status == DLADM_STATUS_OK)
23808453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
23815895Syz147064 		goto done;
23825895Syz147064 	}
23833448Sdh155122 
23845895Syz147064 	buf[0] = '\0';
23855895Syz147064 	for (i = 0; i < val_cnt; i++) {
23865895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
23875895Syz147064 		if (i != val_cnt - 1)
23885895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
23893448Sdh155122 	}
23903448Sdh155122 
23918453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
23928453SAnurag.Maskey@Sun.COM 	    buf);
23935895Syz147064 	if (status == DLADM_STATUS_OK)
23948453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
23955895Syz147064 
23965895Syz147064 done:
23978453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
23985895Syz147064 	return (status);
23993448Sdh155122 }
24005895Syz147064 
24015895Syz147064 static dladm_status_t
24028453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
24038453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
24045895Syz147064 {
24055895Syz147064 	char		buf[MAXLINELEN], *str;
24065895Syz147064 	uint_t		cnt = 0;
24075895Syz147064 	dladm_conf_t	conf;
24085895Syz147064 	dladm_status_t	status;
24095895Syz147064 
24108453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
24115895Syz147064 	if (status != DLADM_STATUS_OK)
24125895Syz147064 		return (status);
24135895Syz147064 
24148453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
24155895Syz147064 	if (status != DLADM_STATUS_OK)
24165895Syz147064 		goto done;
24175895Syz147064 
24185895Syz147064 	str = strtok(buf, ",");
24195895Syz147064 	while (str != NULL) {
24205895Syz147064 		if (cnt == *val_cntp) {
24215895Syz147064 			status = DLADM_STATUS_TOOSMALL;
24225895Syz147064 			goto done;
24235895Syz147064 		}
24245895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
24255895Syz147064 		str = strtok(NULL, ",");
24265895Syz147064 	}
24275895Syz147064 
24285895Syz147064 	*val_cntp = cnt;
24295895Syz147064 
24305895Syz147064 done:
24318453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
24325895Syz147064 	return (status);
24335895Syz147064 }
24345903Ssowmini 
24358460SArtem.Kachitchkin@Sun.COM /*
24368460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
24378460SArtem.Kachitchkin@Sun.COM  */
24388460SArtem.Kachitchkin@Sun.COM static dladm_status_t
24398460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
24408460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
24418460SArtem.Kachitchkin@Sun.COM {
24428460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
24438460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
24448460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
24458460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
24468460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
24478460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
24488460SArtem.Kachitchkin@Sun.COM 
24498460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
24508460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
24518460SArtem.Kachitchkin@Sun.COM 
24528460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
24538460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
24548460SArtem.Kachitchkin@Sun.COM 		return (status);
24558460SArtem.Kachitchkin@Sun.COM 
24568460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
24578460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
24588460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
24598460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
24608460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
24618460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
24628460SArtem.Kachitchkin@Sun.COM 				break;
24638460SArtem.Kachitchkin@Sun.COM 		}
24648460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
24658460SArtem.Kachitchkin@Sun.COM 	}
24668460SArtem.Kachitchkin@Sun.COM 
24678460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
24688460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
24698460SArtem.Kachitchkin@Sun.COM }
24708460SArtem.Kachitchkin@Sun.COM 
24717663SSowmini.Varadhan@Sun.COM static link_attr_t *
24725903Ssowmini dladm_name2prop(const char *prop_name)
24735903Ssowmini {
24747663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
24755903Ssowmini 
24767663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
24775903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
24785903Ssowmini 			break;
24795903Ssowmini 	}
24805903Ssowmini 	return (p);
24815903Ssowmini }
24825903Ssowmini 
24837663SSowmini.Varadhan@Sun.COM static link_attr_t *
24847663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
24857663SSowmini.Varadhan@Sun.COM {
24867663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
24877663SSowmini.Varadhan@Sun.COM 
24887663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
24897663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
24907663SSowmini.Varadhan@Sun.COM 			break;
24917663SSowmini.Varadhan@Sun.COM 	}
24927663SSowmini.Varadhan@Sun.COM 	return (p);
24937663SSowmini.Varadhan@Sun.COM }
24945903Ssowmini 
24956789Sam223141 static dld_ioc_macprop_t *
24967663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
24977663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
24987663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
24995903Ssowmini {
25005903Ssowmini 	int dsize;
25016789Sam223141 	dld_ioc_macprop_t *dip;
25025903Ssowmini 
25035903Ssowmini 	*status = DLADM_STATUS_OK;
25046789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
25055903Ssowmini 	dip = malloc(dsize);
25065903Ssowmini 	if (dip == NULL) {
25075903Ssowmini 		*status = DLADM_STATUS_NOMEM;
25085903Ssowmini 		return (NULL);
25095903Ssowmini 	}
25105903Ssowmini 	bzero(dip, dsize);
25115903Ssowmini 	dip->pr_valsize = valsize;
25126512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
25136789Sam223141 	dip->pr_version = MAC_PROP_VERSION;
25145960Ssowmini 	dip->pr_linkid = linkid;
25157663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
25166512Ssowmini 	dip->pr_flags = flags;
25175903Ssowmini 	return (dip);
25185903Ssowmini }
25195903Ssowmini 
25207663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
25217663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
25227663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
25237663SSowmini.Varadhan@Sun.COM {
25247663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
25257663SSowmini.Varadhan@Sun.COM 
25267663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
25277663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
25287663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
25297663SSowmini.Varadhan@Sun.COM 	    flags, status));
25307663SSowmini.Varadhan@Sun.COM }
25317663SSowmini.Varadhan@Sun.COM 
25327663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
25337663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
25347663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
25357663SSowmini.Varadhan@Sun.COM {
25367663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
25377663SSowmini.Varadhan@Sun.COM 
25387663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
25397663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
25407663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
25417663SSowmini.Varadhan@Sun.COM 	    flags, status));
25427663SSowmini.Varadhan@Sun.COM }
25437663SSowmini.Varadhan@Sun.COM 
25445903Ssowmini /* ARGSUSED */
25455903Ssowmini static dladm_status_t
25468453SAnurag.Maskey@Sun.COM i_dladm_set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
25478453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
25488453SAnurag.Maskey@Sun.COM     datalink_media_t media)
25495903Ssowmini {
25506789Sam223141 	dld_ioc_macprop_t	*dip;
25515903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
25525903Ssowmini 	uint8_t		u8;
25535903Ssowmini 	uint16_t	u16;
25545903Ssowmini 	uint32_t	u32;
25555903Ssowmini 	void		*val;
25565903Ssowmini 
25578275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
25585903Ssowmini 	if (dip == NULL)
25595903Ssowmini 		return (status);
25605903Ssowmini 
25618275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
25625903Ssowmini 		val = (void *)vdp->vd_val;
25635903Ssowmini 	else {
25645903Ssowmini 		/*
25655903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
25665903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
25675903Ssowmini 		 */
25685903Ssowmini 		switch (dip->pr_valsize) {
25695903Ssowmini 		case 1:
25705903Ssowmini 			u8 = vdp->vd_val;
25715903Ssowmini 			val = &u8;
25725903Ssowmini 			break;
25735903Ssowmini 		case 2:
25745903Ssowmini 			u16 = vdp->vd_val;
25755903Ssowmini 			val = &u16;
25765903Ssowmini 			break;
25775903Ssowmini 		case 4:
25785903Ssowmini 			u32 = vdp->vd_val;
25795903Ssowmini 			val = &u32;
25805903Ssowmini 			break;
25815903Ssowmini 		default:
25825903Ssowmini 			val = &vdp->vd_val;
25835903Ssowmini 			break;
25845903Ssowmini 		}
25855903Ssowmini 	}
25865903Ssowmini 
25877342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
25887342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
25897342SAruna.Ramakrishna@Sun.COM 	else
25907342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
25917342SAruna.Ramakrishna@Sun.COM 
25928453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
25937663SSowmini.Varadhan@Sun.COM 
25947663SSowmini.Varadhan@Sun.COM done:
25957663SSowmini.Varadhan@Sun.COM 	free(dip);
25967663SSowmini.Varadhan@Sun.COM 	return (status);
25977663SSowmini.Varadhan@Sun.COM }
25987663SSowmini.Varadhan@Sun.COM 
25997663SSowmini.Varadhan@Sun.COM dladm_status_t
26008453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
26017663SSowmini.Varadhan@Sun.COM {
26027663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
26037663SSowmini.Varadhan@Sun.COM 
26048453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
26058453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
26065903Ssowmini 		status = dladm_errno2status(errno);
26078453SAnurag.Maskey@Sun.COM 
26085903Ssowmini 	return (status);
26095903Ssowmini }
26105903Ssowmini 
26116789Sam223141 static dld_ioc_macprop_t *
26128453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
26138453SAnurag.Maskey@Sun.COM     char *prop_name, uint_t flags, dladm_status_t *status, uint_t *perm_flags)
26145903Ssowmini {
26156789Sam223141 	dld_ioc_macprop_t *dip = NULL;
26166512Ssowmini 
26177663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status);
26186512Ssowmini 	if (dip == NULL)
26196512Ssowmini 		return (NULL);
26205903Ssowmini 
26218453SAnurag.Maskey@Sun.COM 	*status = i_dladm_macprop(handle, dip, B_FALSE);
26226512Ssowmini 	if (*status != DLADM_STATUS_OK) {
26236512Ssowmini 		free(dip);
26246512Ssowmini 		return (NULL);
26256512Ssowmini 	}
26268275SEric Cheng 	if (perm_flags != NULL)
26278275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
26288275SEric Cheng 
26296512Ssowmini 	return (dip);
26305903Ssowmini }
26315903Ssowmini 
26325903Ssowmini /* ARGSUSED */
26335903Ssowmini static dladm_status_t
263410491SRishi.Srivatsavai@Sun.COM i_dladm_uint32_check(dladm_handle_t handle, prop_desc_t *pdp,
26358453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *v,
26368453SAnurag.Maskey@Sun.COM     datalink_media_t media)
26375903Ssowmini {
26385903Ssowmini 	if (val_cnt != 1)
26395903Ssowmini 		return (DLADM_STATUS_BADVAL);
264010491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
26415903Ssowmini 	return (DLADM_STATUS_OK);
26425903Ssowmini }
26435903Ssowmini 
26445903Ssowmini /* ARGSUSED */
26455903Ssowmini static dladm_status_t
26468453SAnurag.Maskey@Sun.COM i_dladm_duplex_get(dladm_handle_t handle, prop_desc_t *pdp,
26478453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
26488453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
26495903Ssowmini {
26505903Ssowmini 	link_duplex_t   link_duplex;
26515903Ssowmini 	dladm_status_t  status;
26525903Ssowmini 
26538453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
26545903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
26555903Ssowmini 		return (status);
26565903Ssowmini 
26575903Ssowmini 	switch (link_duplex) {
26585903Ssowmini 	case LINK_DUPLEX_FULL:
26595903Ssowmini 		(void) strcpy(*prop_val, "full");
26605903Ssowmini 		break;
26615903Ssowmini 	case LINK_DUPLEX_HALF:
26625903Ssowmini 		(void) strcpy(*prop_val, "half");
26635903Ssowmini 		break;
26645903Ssowmini 	default:
26655903Ssowmini 		(void) strcpy(*prop_val, "unknown");
26665903Ssowmini 		break;
26675903Ssowmini 	}
26685903Ssowmini 	*val_cnt = 1;
26695903Ssowmini 	return (DLADM_STATUS_OK);
26705903Ssowmini }
26715903Ssowmini 
26725903Ssowmini /* ARGSUSED */
26735903Ssowmini static dladm_status_t
26748453SAnurag.Maskey@Sun.COM i_dladm_speed_get(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
26758275SEric Cheng     char **prop_val, uint_t *val_cnt, uint_t flags, uint_t *perm_flags)
26765903Ssowmini {
26775903Ssowmini 	uint64_t	ifspeed = 0;
26785903Ssowmini 	dladm_status_t status;
26795903Ssowmini 
26808453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
26815903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
26825903Ssowmini 		return (status);
26836512Ssowmini 
26845960Ssowmini 	if ((ifspeed % 1000000) != 0) {
26855960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
26865960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
26875960Ssowmini 	} else {
26885960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
26895960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
26905960Ssowmini 	}
26915903Ssowmini 	*val_cnt = 1;
26928275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
26935903Ssowmini 	return (DLADM_STATUS_OK);
26945903Ssowmini }
26955903Ssowmini 
26965903Ssowmini /* ARGSUSED */
26975903Ssowmini static dladm_status_t
26988453SAnurag.Maskey@Sun.COM i_dladm_status_get(dladm_handle_t handle, prop_desc_t *pdp,
26998453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27008453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27015903Ssowmini {
27028275SEric Cheng 	link_state_t		link_state;
27038275SEric Cheng 	dladm_status_t		status;
27048306SSowmini.Varadhan@Sun.COM 
27058453SAnurag.Maskey@Sun.COM 	status = i_dladm_get_state(handle, linkid, &link_state);
27066512Ssowmini 	if (status != DLADM_STATUS_OK)
27075903Ssowmini 		return (status);
27088275SEric Cheng 
27095903Ssowmini 	switch (link_state) {
27105903Ssowmini 	case LINK_STATE_UP:
27115903Ssowmini 		(void) strcpy(*prop_val, "up");
27125903Ssowmini 		break;
27135903Ssowmini 	case LINK_STATE_DOWN:
27145903Ssowmini 		(void) strcpy(*prop_val, "down");
27155903Ssowmini 		break;
27165903Ssowmini 	default:
27175903Ssowmini 		(void) strcpy(*prop_val, "unknown");
27185903Ssowmini 		break;
27195903Ssowmini 	}
27205903Ssowmini 	*val_cnt = 1;
27218306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
27225903Ssowmini 	return (DLADM_STATUS_OK);
27235903Ssowmini }
27245903Ssowmini 
27255903Ssowmini /* ARGSUSED */
27265903Ssowmini static dladm_status_t
27278453SAnurag.Maskey@Sun.COM i_dladm_binary_get(dladm_handle_t handle, prop_desc_t *pdp,
27288453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27298453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27305903Ssowmini {
27316789Sam223141 	dld_ioc_macprop_t *dip;
27325903Ssowmini 	dladm_status_t status;
27335903Ssowmini 
27348453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
27358275SEric Cheng 	    &status, perm_flags);
27366512Ssowmini 	if (dip == NULL)
27375903Ssowmini 		return (status);
27388275SEric Cheng 
27395903Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
27405903Ssowmini 	free(dip);
27415903Ssowmini 	*val_cnt = 1;
27425903Ssowmini 	return (DLADM_STATUS_OK);
27435903Ssowmini }
27445903Ssowmini 
27455960Ssowmini /* ARGSUSED */
27465903Ssowmini static dladm_status_t
27478453SAnurag.Maskey@Sun.COM i_dladm_uint32_get(dladm_handle_t handle, prop_desc_t *pdp,
27488453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27498453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27505903Ssowmini {
27516789Sam223141 	dld_ioc_macprop_t *dip;
27528275SEric Cheng 	uint32_t v = 0;
27535903Ssowmini 	uchar_t *cp;
27545903Ssowmini 	dladm_status_t status;
27555903Ssowmini 
27568453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
27578275SEric Cheng 	    &status, perm_flags);
27586512Ssowmini 	if (dip == NULL)
27595903Ssowmini 		return (status);
27608275SEric Cheng 
27615903Ssowmini 	cp = (uchar_t *)dip->pr_val;
27625903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
27636512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
27645903Ssowmini 	free(dip);
27655903Ssowmini 	*val_cnt = 1;
27665903Ssowmini 	return (DLADM_STATUS_OK);
27675903Ssowmini }
27685903Ssowmini 
27699514SGirish.Moodalbail@Sun.COM /*
27709514SGirish.Moodalbail@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
27719514SGirish.Moodalbail@Sun.COM  * for retrieving the property range values.
27729514SGirish.Moodalbail@Sun.COM  */
27739514SGirish.Moodalbail@Sun.COM static int
27749514SGirish.Moodalbail@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
27759514SGirish.Moodalbail@Sun.COM {
27769514SGirish.Moodalbail@Sun.COM 	uint_t count = r->mpr_count;
27779514SGirish.Moodalbail@Sun.COM 
27789514SGirish.Moodalbail@Sun.COM 	*sz = sizeof (mac_propval_range_t);
27799514SGirish.Moodalbail@Sun.COM 	--count;
27809514SGirish.Moodalbail@Sun.COM 
27819514SGirish.Moodalbail@Sun.COM 	switch (r->mpr_type) {
27829514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32:
27839514SGirish.Moodalbail@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
27849514SGirish.Moodalbail@Sun.COM 		return (0);
27859514SGirish.Moodalbail@Sun.COM 	default:
27869514SGirish.Moodalbail@Sun.COM 		break;
27879514SGirish.Moodalbail@Sun.COM 	}
27889514SGirish.Moodalbail@Sun.COM 	*sz = 0;
27899514SGirish.Moodalbail@Sun.COM 	return (EINVAL);
27909514SGirish.Moodalbail@Sun.COM }
27919514SGirish.Moodalbail@Sun.COM 
27929514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
27939514SGirish.Moodalbail@Sun.COM static dladm_status_t
27949514SGirish.Moodalbail@Sun.COM i_dladm_range_get(dladm_handle_t handle, prop_desc_t *pdp,
27959514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
27969514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
27979514SGirish.Moodalbail@Sun.COM {
27989514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
27999514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
28009514SGirish.Moodalbail@Sun.COM 	size_t	sz;
28019514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
28029514SGirish.Moodalbail@Sun.COM 
28039514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
28049514SGirish.Moodalbail@Sun.COM 
28059514SGirish.Moodalbail@Sun.COM 	/*
28069514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
28079514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
28089514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
28099514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
28109514SGirish.Moodalbail@Sun.COM 	 */
28119514SGirish.Moodalbail@Sun.COM retry:
28129514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
28139514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
28149514SGirish.Moodalbail@Sun.COM 		return (status);
28159514SGirish.Moodalbail@Sun.COM 
28169514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
28179514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
28189514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
28199514SGirish.Moodalbail@Sun.COM 			int err;
28209514SGirish.Moodalbail@Sun.COM 
28219514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
28229514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
28239514SGirish.Moodalbail@Sun.COM 				free(dip);
28249514SGirish.Moodalbail@Sun.COM 				goto retry;
28259514SGirish.Moodalbail@Sun.COM 			} else {
28269514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
28279514SGirish.Moodalbail@Sun.COM 			}
28289514SGirish.Moodalbail@Sun.COM 		}
28299514SGirish.Moodalbail@Sun.COM 		free(dip);
28309514SGirish.Moodalbail@Sun.COM 		return (status);
28319514SGirish.Moodalbail@Sun.COM 	}
28329514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
28339514SGirish.Moodalbail@Sun.COM 
28349514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
28359514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
28369514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
28379514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
28389514SGirish.Moodalbail@Sun.COM 
28399514SGirish.Moodalbail@Sun.COM 		ur = &rangep->range_uint32[0];
28409514SGirish.Moodalbail@Sun.COM 
28419514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
28429514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
28439514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
28449514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
28459514SGirish.Moodalbail@Sun.COM 			} else {
28469514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
28479514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
28489514SGirish.Moodalbail@Sun.COM 			}
28499514SGirish.Moodalbail@Sun.COM 		}
28509514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
28519514SGirish.Moodalbail@Sun.COM 		break;
28529514SGirish.Moodalbail@Sun.COM 	}
28539514SGirish.Moodalbail@Sun.COM 	default:
28549514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
28559514SGirish.Moodalbail@Sun.COM 		break;
28569514SGirish.Moodalbail@Sun.COM 	}
28579514SGirish.Moodalbail@Sun.COM 	free(dip);
28589514SGirish.Moodalbail@Sun.COM 	return (status);
28599514SGirish.Moodalbail@Sun.COM }
28609514SGirish.Moodalbail@Sun.COM 
28615960Ssowmini /* ARGSUSED */
28625903Ssowmini static dladm_status_t
28638874SSebastien.Roy@Sun.COM i_dladm_tagmode_get(dladm_handle_t handle, prop_desc_t *pdp,
28648874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28658874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28668874SSebastien.Roy@Sun.COM {
28678874SSebastien.Roy@Sun.COM 	dld_ioc_macprop_t	*dip;
28688874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
28698874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
28708874SSebastien.Roy@Sun.COM 
28718874SSebastien.Roy@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
28728874SSebastien.Roy@Sun.COM 	    &status, perm_flags);
28738874SSebastien.Roy@Sun.COM 	if (dip == NULL)
28748874SSebastien.Roy@Sun.COM 		return (status);
28758874SSebastien.Roy@Sun.COM 	(void) memcpy(&mode, dip->pr_val, sizeof (mode));
28768874SSebastien.Roy@Sun.COM 	free(dip);
28778874SSebastien.Roy@Sun.COM 
28788874SSebastien.Roy@Sun.COM 	switch (mode) {
28798874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
28808874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
28818874SSebastien.Roy@Sun.COM 		break;
28828874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
28838874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
28848874SSebastien.Roy@Sun.COM 		break;
28858874SSebastien.Roy@Sun.COM 	default:
28868874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
28878874SSebastien.Roy@Sun.COM 	}
28888874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
28898874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
28908874SSebastien.Roy@Sun.COM }
28918874SSebastien.Roy@Sun.COM 
28928874SSebastien.Roy@Sun.COM /* ARGSUSED */
28938874SSebastien.Roy@Sun.COM static dladm_status_t
28948453SAnurag.Maskey@Sun.COM i_dladm_flowctl_get(dladm_handle_t handle, prop_desc_t *pdp,
28958453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
28968453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
28975903Ssowmini {
28986789Sam223141 	dld_ioc_macprop_t *dip;
28995903Ssowmini 	link_flowctrl_t v;
29005903Ssowmini 	dladm_status_t status;
29015903Ssowmini 	uchar_t *cp;
29025903Ssowmini 
29038453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
29048275SEric Cheng 	    &status, perm_flags);
29056512Ssowmini 	if (dip == NULL)
29065903Ssowmini 		return (status);
29078275SEric Cheng 
29085903Ssowmini 	cp = (uchar_t *)dip->pr_val;
29095903Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
29105903Ssowmini 	switch (v) {
29115903Ssowmini 	case LINK_FLOWCTRL_NONE:
29125903Ssowmini 		(void) sprintf(*prop_val, "no");
29135903Ssowmini 		break;
29145903Ssowmini 	case LINK_FLOWCTRL_RX:
29155903Ssowmini 		(void) sprintf(*prop_val, "rx");
29165903Ssowmini 		break;
29175903Ssowmini 	case LINK_FLOWCTRL_TX:
29185903Ssowmini 		(void) sprintf(*prop_val, "tx");
29195903Ssowmini 		break;
29205903Ssowmini 	case LINK_FLOWCTRL_BI:
29215903Ssowmini 		(void) sprintf(*prop_val, "bi");
29225903Ssowmini 		break;
29235903Ssowmini 	}
29245903Ssowmini 	free(dip);
29255903Ssowmini 	*val_cnt = 1;
29265903Ssowmini 	return (DLADM_STATUS_OK);
29275903Ssowmini }
29285903Ssowmini 
29295903Ssowmini 
29305903Ssowmini /* ARGSUSED */
29315903Ssowmini static dladm_status_t
29329692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
29338453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
29348453SAnurag.Maskey@Sun.COM 
29355903Ssowmini {
29367663SSowmini.Varadhan@Sun.COM 	int		i, slen;
29377408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
29386789Sam223141 	dld_ioc_macprop_t *dip = NULL;
29395903Ssowmini 	uchar_t 	*dp;
29407663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
29416512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
29425903Ssowmini 
29435903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
29445903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
29455903Ssowmini 		return (DLADM_STATUS_BADARG);
29465903Ssowmini 	p = dladm_name2prop(prop_name);
29476789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
29485903Ssowmini 		return (DLADM_STATUS_BADARG);
29495903Ssowmini 
29509692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
29519692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
29529692SRishi.Srivatsavai@Sun.COM 
29535903Ssowmini 	/*
29545903Ssowmini 	 * private properties: all parsing is done in the kernel.
29555903Ssowmini 	 * allocate a enough space for each property + its separator (',').
29565903Ssowmini 	 */
29575903Ssowmini 	for (i = 0; i < val_cnt; i++) {
29585903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
29595903Ssowmini 	}
29606512Ssowmini 
29616512Ssowmini 	if (prop_val == NULL) {
29626512Ssowmini 		/*
29636512Ssowmini 		 * getting default value. so use more buffer space.
29646512Ssowmini 		 */
29657663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
29666512Ssowmini 	}
29676512Ssowmini 
29687663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
29696789Sam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
29705903Ssowmini 	if (dip == NULL)
29715903Ssowmini 		return (status);
29725903Ssowmini 
29735903Ssowmini 	dp = (uchar_t *)dip->pr_val;
29745903Ssowmini 	slen = 0;
29757663SSowmini.Varadhan@Sun.COM 
29766512Ssowmini 	if (prop_val == NULL) {
29778453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
29788460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
29796512Ssowmini 	} else {
29806512Ssowmini 		for (i = 0; i < val_cnt; i++) {
29816512Ssowmini 			int plen = 0;
29825903Ssowmini 
29836512Ssowmini 			plen = strlen(prop_val[i]);
29846512Ssowmini 			bcopy(prop_val[i], dp, plen);
29856512Ssowmini 			slen += plen;
29866512Ssowmini 			/*
29876512Ssowmini 			 * add a "," separator and update dp.
29886512Ssowmini 			 */
29896512Ssowmini 			if (i != (val_cnt -1))
29906512Ssowmini 				dp[slen++] = ',';
29916512Ssowmini 			dp += (plen + 1);
29926512Ssowmini 		}
29938460SArtem.Kachitchkin@Sun.COM 	}
29948460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
29958453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
29966512Ssowmini 
29975903Ssowmini 	free(dip);
29986512Ssowmini 	return (status);
29995903Ssowmini }
30005903Ssowmini 
30015903Ssowmini static dladm_status_t
30028460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
30038453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
30048453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
30055903Ssowmini {
30067663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
30076789Sam223141 	dld_ioc_macprop_t *dip = NULL;
30087663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
30095903Ssowmini 
30105903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
30115903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
30125903Ssowmini 		return (DLADM_STATUS_BADARG);
30135903Ssowmini 
30145903Ssowmini 	p = dladm_name2prop(prop_name);
30156789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
30165903Ssowmini 		return (DLADM_STATUS_BADARG);
30175903Ssowmini 
30185903Ssowmini 	/*
30195903Ssowmini 	 * private properties: all parsing is done in the kernel.
30205903Ssowmini 	 */
30217663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
30227663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
30235903Ssowmini 	if (dip == NULL)
30245903Ssowmini 		return (status);
30255903Ssowmini 
30268453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
30278453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
30288118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
30298275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
30308460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
30318460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
30328118SVasumathi.Sundaram@Sun.COM 		} else {
30338118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
30348118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
30358118SVasumathi.Sundaram@Sun.COM 		}
30365903Ssowmini 		*val_cnt = 1;
30378460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
30388460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
30398460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
30405903Ssowmini 	}
30416512Ssowmini 	free(dip);
30425903Ssowmini 	return (status);
30435903Ssowmini }
30446512Ssowmini 
30456512Ssowmini 
30466512Ssowmini static dladm_status_t
30478453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
30488453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
30496512Ssowmini {
30506512Ssowmini 	dladm_status_t status;
30516512Ssowmini 	char **prop_vals = NULL, *buf;
30526512Ssowmini 	size_t bufsize;
30536512Ssowmini 	uint_t cnt;
30546512Ssowmini 	int i;
30558118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
30566512Ssowmini 
30576512Ssowmini 	/*
30586512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
30596512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
30606512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
30616512Ssowmini 	 */
30626512Ssowmini 	bufsize =
30636512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
30646512Ssowmini 	buf = malloc(bufsize);
30656512Ssowmini 	prop_vals = (char **)(void *)buf;
30666512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
30676512Ssowmini 		prop_vals[i] = buf +
30686512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
30696512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
30706512Ssowmini 	}
30716768Sar224390 
30726768Sar224390 	/*
30737342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
30747342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
30757342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
30767342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
30777342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
30787342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
30797342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
30807342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
30816768Sar224390 	 */
30828453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
30838118SVasumathi.Sundaram@Sun.COM 	    MAC_PROP_DEFAULT, &perm_flags);
30846512Ssowmini 	if (status == DLADM_STATUS_OK) {
30858118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
30868453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
30878453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
30888118SVasumathi.Sundaram@Sun.COM 		}
30898118SVasumathi.Sundaram@Sun.COM 		else
30908118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
30916512Ssowmini 	}
30926512Ssowmini 	free(buf);
30936512Ssowmini 	return (status);
30946512Ssowmini }
30957663SSowmini.Varadhan@Sun.COM 
309610491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
309710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
309810491SRishi.Srivatsavai@Sun.COM get_stp_prop(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
309910491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
310010491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
310110491SRishi.Srivatsavai@Sun.COM {
310210491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
310310491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
310410491SRishi.Srivatsavai@Sun.COM 	int val, i;
310510491SRishi.Srivatsavai@Sun.COM 
310610491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
310710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
310810491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
310910491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
311010491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
311110491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
311210491SRishi.Srivatsavai@Sun.COM 			break;
311310491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
311410491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
311510491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
311610491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
311710491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
311810491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
311910491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
312010491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
312110491SRishi.Srivatsavai@Sun.COM 	}
312210491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
312310491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
312410491SRishi.Srivatsavai@Sun.COM 		return (retv);
312510491SRishi.Srivatsavai@Sun.COM 	}
312610491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
312710491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
312810491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
312910491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
313010491SRishi.Srivatsavai@Sun.COM 	}
313110491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
313210491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
313310491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
313410491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
313510491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
313610491SRishi.Srivatsavai@Sun.COM 		}
313710491SRishi.Srivatsavai@Sun.COM 	}
313810491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
313910491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
314010491SRishi.Srivatsavai@Sun.COM }
314110491SRishi.Srivatsavai@Sun.COM 
314210491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
314310491SRishi.Srivatsavai@Sun.COM static dladm_status_t
314410491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
314510491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
314610491SRishi.Srivatsavai@Sun.COM {
314710491SRishi.Srivatsavai@Sun.COM 	/*
314810491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
314910491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
315010491SRishi.Srivatsavai@Sun.COM 	 */
315110491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
315210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
315310491SRishi.Srivatsavai@Sun.COM 
315410491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
315510491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
315610491SRishi.Srivatsavai@Sun.COM }
315710491SRishi.Srivatsavai@Sun.COM 
315810491SRishi.Srivatsavai@Sun.COM /*
315910491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
316010491SRishi.Srivatsavai@Sun.COM  */
316110491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
316210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
316310491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
316410491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
316510491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
316610491SRishi.Srivatsavai@Sun.COM {
316710491SRishi.Srivatsavai@Sun.COM 	char *cp;
316810491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
316910491SRishi.Srivatsavai@Sun.COM 
317010491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
317110491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
317210491SRishi.Srivatsavai@Sun.COM 
317310491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
317410491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
317510491SRishi.Srivatsavai@Sun.COM 	} else {
317610491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
317710491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
317810491SRishi.Srivatsavai@Sun.COM 
317910491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
318010491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
318110491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
318210491SRishi.Srivatsavai@Sun.COM 		} else {
318310491SRishi.Srivatsavai@Sun.COM 			errno = 0;
318410491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
318510491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
318610491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
318710491SRishi.Srivatsavai@Sun.COM 		}
318810491SRishi.Srivatsavai@Sun.COM 	}
318910491SRishi.Srivatsavai@Sun.COM 
319010491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
319110491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
319210491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
319310491SRishi.Srivatsavai@Sun.COM 	} else {
319410491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
319510491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
319610491SRishi.Srivatsavai@Sun.COM 		/*
319710491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
319810491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
319910491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
320010491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
320110491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
320210491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
320310491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
320410491SRishi.Srivatsavai@Sun.COM 		 */
320510491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
320610491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
320710491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
320810491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
320910491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
321010491SRishi.Srivatsavai@Sun.COM 
321110491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
321210491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
321310491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
321410491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
321510491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
321610491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
321710491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
321810491SRishi.Srivatsavai@Sun.COM 		}
321910491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
322010491SRishi.Srivatsavai@Sun.COM 	}
322110491SRishi.Srivatsavai@Sun.COM }
322210491SRishi.Srivatsavai@Sun.COM 
322310491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
322410491SRishi.Srivatsavai@Sun.COM static dladm_status_t
322510491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
322610491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
322710491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
322810491SRishi.Srivatsavai@Sun.COM {
322910491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
323010491SRishi.Srivatsavai@Sun.COM 	uint_t val;
323110491SRishi.Srivatsavai@Sun.COM 
323210491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
323310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
323410491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
323510491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
323610491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
323710491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
323810491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
323910491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
324010491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
324110491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
324210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
324310491SRishi.Srivatsavai@Sun.COM 	}
324410491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
324510491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
324610491SRishi.Srivatsavai@Sun.COM 	else
324710491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
324810491SRishi.Srivatsavai@Sun.COM 	return (retv);
324910491SRishi.Srivatsavai@Sun.COM }
325010491SRishi.Srivatsavai@Sun.COM 
325110491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
325210491SRishi.Srivatsavai@Sun.COM static dladm_status_t
325310491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
325410491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
325510491SRishi.Srivatsavai@Sun.COM {
325610491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
325710491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
325810491SRishi.Srivatsavai@Sun.COM }
325910491SRishi.Srivatsavai@Sun.COM 
326010491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
326110491SRishi.Srivatsavai@Sun.COM static dladm_status_t
326210491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
326310491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
326410491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
326510491SRishi.Srivatsavai@Sun.COM {
326610491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
326710491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
326810491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
326910491SRishi.Srivatsavai@Sun.COM 
327010491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
327110491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
327210491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
327310491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
327410491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
327510491SRishi.Srivatsavai@Sun.COM 	    0, &status);
327610491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
327710491SRishi.Srivatsavai@Sun.COM 		return (status);
327810491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
327910491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
328010491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
328110491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
328210491SRishi.Srivatsavai@Sun.COM 	} else {
328310491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
328410491SRishi.Srivatsavai@Sun.COM 	}
328510491SRishi.Srivatsavai@Sun.COM 	free(dip);
328610491SRishi.Srivatsavai@Sun.COM 	return (status);
328710491SRishi.Srivatsavai@Sun.COM }
328810491SRishi.Srivatsavai@Sun.COM 
328910491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
329010491SRishi.Srivatsavai@Sun.COM static dladm_status_t
329110491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
329210491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
329310491SRishi.Srivatsavai@Sun.COM {
329410491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
329510491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
329610491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
329710491SRishi.Srivatsavai@Sun.COM 
329810491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
329910491SRishi.Srivatsavai@Sun.COM 	    0, &status);
330010491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
330110491SRishi.Srivatsavai@Sun.COM 		return (status);
330210491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
330310491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
330410491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
330510491SRishi.Srivatsavai@Sun.COM 	free(dip);
330610491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
330710491SRishi.Srivatsavai@Sun.COM 		return (status);
330810491SRishi.Srivatsavai@Sun.COM 
330910491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
331010491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
331110491SRishi.Srivatsavai@Sun.COM }
331210491SRishi.Srivatsavai@Sun.COM 
331310491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
331410491SRishi.Srivatsavai@Sun.COM static dladm_status_t
331510491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
331610491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, val_desc_t *vdp,
331710491SRishi.Srivatsavai@Sun.COM     datalink_media_t media)
331810491SRishi.Srivatsavai@Sun.COM {
331910491SRishi.Srivatsavai@Sun.COM 	char *cp;
332010491SRishi.Srivatsavai@Sun.COM 
332110491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
332210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
332310491SRishi.Srivatsavai@Sun.COM 
332410491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
332510491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
332610491SRishi.Srivatsavai@Sun.COM 	} else {
332710491SRishi.Srivatsavai@Sun.COM 		errno = 0;
332810491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
332910491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
333010491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
333110491SRishi.Srivatsavai@Sun.COM 	}
333210491SRishi.Srivatsavai@Sun.COM 
333310491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
333410491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
333510491SRishi.Srivatsavai@Sun.COM }
333610491SRishi.Srivatsavai@Sun.COM 
33377663SSowmini.Varadhan@Sun.COM dladm_status_t
33388453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
33398453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
33407663SSowmini.Varadhan@Sun.COM {
33417663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
33427663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
33437663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
33447663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
33457663SSowmini.Varadhan@Sun.COM 	void			*dp;
33467663SSowmini.Varadhan@Sun.COM 
33478453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
33488453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
33497663SSowmini.Varadhan@Sun.COM 		return (status);
33507663SSowmini.Varadhan@Sun.COM 	}
33517663SSowmini.Varadhan@Sun.COM 
33527663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
33537663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
33547663SSowmini.Varadhan@Sun.COM 
33557663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
33567663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
33577663SSowmini.Varadhan@Sun.COM 
33587663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
33597663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
33607663SSowmini.Varadhan@Sun.COM 
33617663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
33627663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
33637663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
33647663SSowmini.Varadhan@Sun.COM 
33657663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
33667663SSowmini.Varadhan@Sun.COM 	if (set)
33677663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
33687663SSowmini.Varadhan@Sun.COM 
33698453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
337010191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
33717663SSowmini.Varadhan@Sun.COM 		if (!set)
33727663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
33737663SSowmini.Varadhan@Sun.COM 	}
33747663SSowmini.Varadhan@Sun.COM 
33757663SSowmini.Varadhan@Sun.COM 	free(dip);
33767663SSowmini.Varadhan@Sun.COM 	return (status);
33777663SSowmini.Varadhan@Sun.COM }
33787663SSowmini.Varadhan@Sun.COM 
33798275SEric Cheng dladm_status_t
33808275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
33818275SEric Cheng {
33828460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
33838275SEric Cheng }
33848275SEric Cheng 
33858275SEric Cheng /*
33868275SEric Cheng  * Retrieve the one link property from the database
33878275SEric Cheng  */
33888275SEric Cheng /*ARGSUSED*/
33898275SEric Cheng static int
33908453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
33918453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
33928275SEric Cheng {
33938275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
33948275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
33958275SEric Cheng 
33968275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
33978275SEric Cheng 	/*
33988275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
33998275SEric Cheng 	 * prop_table[n].pd_name.
34008275SEric Cheng 	 */
34018275SEric Cheng 	aip->ai_name = prop_name;
34028275SEric Cheng 
34038453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
34048453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
34058275SEric Cheng 
34068275SEric Cheng 	if (aip->ai_count != 0)
34078275SEric Cheng 		proplist->al_count++;
34088275SEric Cheng 
34098275SEric Cheng 	return (DLADM_WALK_CONTINUE);
34108275SEric Cheng }
34118275SEric Cheng 
34128275SEric Cheng 
34138275SEric Cheng /*
34148275SEric Cheng  * Retrieve all link properties for a link from the database and
34158275SEric Cheng  * return a property list.
34168275SEric Cheng  */
34178275SEric Cheng dladm_status_t
34188453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
34198453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
34208275SEric Cheng {
34218275SEric Cheng 	dladm_arg_list_t	*list;
34228275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
34238275SEric Cheng 
34248275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
34258275SEric Cheng 	if (list == NULL)
34268275SEric Cheng 		return (dladm_errno2status(errno));
34278275SEric Cheng 
34288453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
34298453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
34308275SEric Cheng 
34318275SEric Cheng 	*listp = list;
34328275SEric Cheng 	return (status);
34338275SEric Cheng }
34348275SEric Cheng 
34358275SEric Cheng /*
34368275SEric Cheng  * Retrieve the named property from a proplist, check the value and
34378275SEric Cheng  * convert to a kernel structure.
34388275SEric Cheng  */
34398275SEric Cheng static dladm_status_t
34408453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
34418453SAnurag.Maskey@Sun.COM     dladm_arg_list_t *proplist, const char *name, void *val)
34428275SEric Cheng {
34438275SEric Cheng 	dladm_status_t		status;
34448275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
34458275SEric Cheng 	int			i, j;
34468275SEric Cheng 
34478275SEric Cheng 	/* Find named property in proplist */
34488275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
34498275SEric Cheng 		aip = &proplist->al_info[i];
34508275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
34518275SEric Cheng 			break;
34528275SEric Cheng 	}
34538275SEric Cheng 
34548275SEric Cheng 	/* Property not in list */
34558275SEric Cheng 	if (i == proplist->al_count)
34568275SEric Cheng 		return (DLADM_STATUS_OK);
34578275SEric Cheng 
34588275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
34598275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
34608275SEric Cheng 		val_desc_t	*vdp;
34618275SEric Cheng 
34628275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
34638275SEric Cheng 		if (vdp == NULL)
34648275SEric Cheng 			return (DLADM_STATUS_NOMEM);
34658275SEric Cheng 
34668275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
34678275SEric Cheng 			continue;
34688275SEric Cheng 
34698275SEric Cheng 		if (aip->ai_val == NULL)
34708275SEric Cheng 			return (DLADM_STATUS_BADARG);
34718275SEric Cheng 
34728275SEric Cheng 		/* Check property value */
34738275SEric Cheng 		if (pdp->pd_check != NULL) {
34748453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
34758275SEric Cheng 			    aip->ai_count, vdp, 0);
34768275SEric Cheng 		} else {
34778275SEric Cheng 			status = DLADM_STATUS_BADARG;
34788275SEric Cheng 		}
34798275SEric Cheng 
34808275SEric Cheng 		if (status != DLADM_STATUS_OK)
34818275SEric Cheng 			return (status);
34828275SEric Cheng 
34838275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
34848275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
34858275SEric Cheng 
34868275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
34878275SEric Cheng 				continue;
34888275SEric Cheng 
34898275SEric Cheng 			/* Extract kernel structure */
34908275SEric Cheng 			if (rpp->rp_extract != NULL) {
34918275SEric Cheng 				status = rpp->rp_extract(vdp, val,
34928275SEric Cheng 				    aip->ai_count);
34938275SEric Cheng 			} else {
34948275SEric Cheng 				status = DLADM_STATUS_BADARG;
34958275SEric Cheng 			}
34968275SEric Cheng 			break;
34978275SEric Cheng 		}
34988275SEric Cheng 
34998275SEric Cheng 		if (status != DLADM_STATUS_OK)
35008275SEric Cheng 			return (status);
35018275SEric Cheng 
35028275SEric Cheng 		break;
35038275SEric Cheng 	}
35048275SEric Cheng 	return (status);
35058275SEric Cheng }
35068275SEric Cheng 
35078275SEric Cheng /*
35088275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
35098275SEric Cheng  */
35108275SEric Cheng dladm_status_t
35118453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
35128275SEric Cheng     mac_resource_props_t *mrp)
35138275SEric Cheng {
35148275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
35158275SEric Cheng 
35168453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "maxbw",
35178453SAnurag.Maskey@Sun.COM 	    mrp);
35188275SEric Cheng 	if (status != DLADM_STATUS_OK)
35198275SEric Cheng 		return (status);
35208453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "priority",
35218453SAnurag.Maskey@Sun.COM 	    mrp);
35228275SEric Cheng 	if (status != DLADM_STATUS_OK)
35238275SEric Cheng 		return (status);
35248453SAnurag.Maskey@Sun.COM 	status = i_dladm_link_proplist_extract_one(handle, proplist, "cpus",
35258453SAnurag.Maskey@Sun.COM 	    mrp);
35268275SEric Cheng 	if (status != DLADM_STATUS_OK)
35278275SEric Cheng 		return (status);
35288275SEric Cheng 	return (status);
35298275SEric Cheng }
35308275SEric Cheng 
35318275SEric Cheng static const char *
35328275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
35338275SEric Cheng {
35348275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
35358275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
35368275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
35378275SEric Cheng 	return (buf);
35388275SEric Cheng }
35398306SSowmini.Varadhan@Sun.COM 
35408306SSowmini.Varadhan@Sun.COM dladm_status_t
35418453SAnurag.Maskey@Sun.COM i_dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
35428453SAnurag.Maskey@Sun.COM     link_state_t *state)
35438306SSowmini.Varadhan@Sun.COM {
35448306SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
35458306SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
35468306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
35478306SSowmini.Varadhan@Sun.COM 
35488453SAnurag.Maskey@Sun.COM 	dip = i_dladm_get_public_prop(handle, linkid, "state", 0, &status,
35498453SAnurag.Maskey@Sun.COM 	    &perms);
35508306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
35518306SSowmini.Varadhan@Sun.COM 		return (status);
35528306SSowmini.Varadhan@Sun.COM 	(void) memcpy(state, dip->pr_val, sizeof (*state));
35538306SSowmini.Varadhan@Sun.COM 	free(dip);
35548306SSowmini.Varadhan@Sun.COM 	return (status);
35558306SSowmini.Varadhan@Sun.COM }
35568460SArtem.Kachitchkin@Sun.COM 
35578460SArtem.Kachitchkin@Sun.COM boolean_t
35588460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
35598460SArtem.Kachitchkin@Sun.COM {
35608460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
35618460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
35628460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
35638460SArtem.Kachitchkin@Sun.COM 		"name",
35648460SArtem.Kachitchkin@Sun.COM 		"class",
35658460SArtem.Kachitchkin@Sun.COM 		"media",
35668460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
35678460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
35688460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
35698460SArtem.Kachitchkin@Sun.COM 
35708460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
35718460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
35728460SArtem.Kachitchkin@Sun.COM 	};
35738460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
35748460SArtem.Kachitchkin@Sun.COM 	int		i;
35758460SArtem.Kachitchkin@Sun.COM 
35768460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
35778460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
35788460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
35798460SArtem.Kachitchkin@Sun.COM 			break;
35808460SArtem.Kachitchkin@Sun.COM 		}
35818460SArtem.Kachitchkin@Sun.COM 	}
35828460SArtem.Kachitchkin@Sun.COM 
35838460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
35848460SArtem.Kachitchkin@Sun.COM }
3585