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 /*
2212163SRamaswamy.Tummala@Sun.COM  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
233147Sxc151355  */
243147Sxc151355 
253147Sxc151355 #include <stdlib.h>
263147Sxc151355 #include <strings.h>
273147Sxc151355 #include <errno.h>
283147Sxc151355 #include <ctype.h>
295895Syz147064 #include <stddef.h>
303448Sdh155122 #include <sys/types.h>
313147Sxc151355 #include <sys/stat.h>
323448Sdh155122 #include <sys/dld.h>
333448Sdh155122 #include <sys/zone.h>
343448Sdh155122 #include <fcntl.h>
353448Sdh155122 #include <unistd.h>
363448Sdh155122 #include <libdevinfo.h>
373448Sdh155122 #include <zone.h>
383871Syz147064 #include <libdllink.h>
393147Sxc151355 #include <libdladm_impl.h>
405895Syz147064 #include <libdlwlan_impl.h>
413871Syz147064 #include <libdlwlan.h>
425895Syz147064 #include <libdlvlan.h>
438275SEric Cheng #include <libdlvnic.h>
4412163SRamaswamy.Tummala@Sun.COM #include <libdlib.h>
458275SEric Cheng #include <libintl.h>
463448Sdh155122 #include <dlfcn.h>
473448Sdh155122 #include <link.h>
485895Syz147064 #include <inet/wifi_ioctl.h>
495903Ssowmini #include <libdladm.h>
508275SEric Cheng #include <libdlstat.h>
515903Ssowmini #include <sys/param.h>
528275SEric Cheng #include <sys/debug.h>
538275SEric Cheng #include <sys/dld.h>
545903Ssowmini #include <inttypes.h>
555903Ssowmini #include <sys/ethernet.h>
5610616SSebastien.Roy@Sun.COM #include <inet/iptun.h>
577663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
587663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
5910491SRishi.Srivatsavai@Sun.COM #include <sys/vlan.h>
6010491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
6110491SRishi.Srivatsavai@Sun.COM #include <stp_in.h>
6211878SVenu.Iyer@Sun.COM #include <netinet/dhcp.h>
6311878SVenu.Iyer@Sun.COM #include <netinet/dhcp6.h>
6411878SVenu.Iyer@Sun.COM #include <net/if_types.h>
6511878SVenu.Iyer@Sun.COM #include <libinetutil.h>
6611878SVenu.Iyer@Sun.COM #include <pool.h>
673448Sdh155122 
685895Syz147064 /*
695895Syz147064  * The linkprop get() callback.
708275SEric Cheng  * - pd: 	pointer to the prop_desc_t
715895Syz147064  * - propstrp:	a property string array to keep the returned property.
725895Syz147064  *		Caller allocated.
735895Syz147064  * - cntp:	number of returned properties.
745895Syz147064  *		Caller also uses it to indicate how many it expects.
755895Syz147064  */
765903Ssowmini struct prop_desc;
778275SEric Cheng typedef struct prop_desc prop_desc_t;
788275SEric Cheng 
798453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_getf_t(dladm_handle_t, prop_desc_t *pdp,
805960Ssowmini 			datalink_id_t, char **propstp, uint_t *cntp,
818118SVasumathi.Sundaram@Sun.COM 			datalink_media_t, uint_t, uint_t *);
825895Syz147064 
835895Syz147064 /*
845895Syz147064  * The linkprop set() callback.
855895Syz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
865895Syz147064  * - cnt:	number of properties to be set.
875903Ssowmini  * - flags: 	additional flags passed down the system call.
885903Ssowmini  *
895903Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
905903Ssowmini  * a format suitable for kernel consumption. This may require allocation
915903Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
925903Ssowmini  * by all other pd_sets) which invokes the ioctl.
935895Syz147064  */
948453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_setf_t(dladm_handle_t, prop_desc_t *, datalink_id_t,
958275SEric Cheng 			    val_desc_t *propval, uint_t cnt, uint_t flags,
968275SEric Cheng 			    datalink_media_t);
973448Sdh155122 
985895Syz147064 /*
995895Syz147064  * The linkprop check() callback.
1005895Syz147064  * - propstrp:	property string array which keeps the property to be checked.
1015895Syz147064  * - cnt:	number of properties.
1025895Syz147064  * - propval:	return value; the property values of the given property strings.
1035903Ssowmini  *
1045903Ssowmini  * pd_check checks that the input values are valid. It does so by
1055903Ssowmini  * iteraring through the pd_modval list for the property. If
1065903Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
1075903Ssowmini  * specific to this property can be used. If the input values are
1085903Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
1095903Ssowmini  * with either a val_desc_t found on the pd_modval list or something
1105903Ssowmini  * generated on the fly.
1115895Syz147064  */
1128453SAnurag.Maskey@Sun.COM typedef dladm_status_t	pd_checkf_t(dladm_handle_t, prop_desc_t *pdp,
1138453SAnurag.Maskey@Sun.COM 			    datalink_id_t, char **propstrp, uint_t cnt,
11411878SVenu.Iyer@Sun.COM 			    uint_t flags, val_desc_t *propval,
11511878SVenu.Iyer@Sun.COM 			    datalink_media_t);
1163448Sdh155122 
1177663SSowmini.Varadhan@Sun.COM typedef struct link_attr_s {
1186789Sam223141 	mac_prop_id_t	pp_id;
1195903Ssowmini 	size_t		pp_valsize;
1205903Ssowmini 	char		*pp_name;
1217663SSowmini.Varadhan@Sun.COM } link_attr_t;
1225903Ssowmini 
12311878SVenu.Iyer@Sun.COM typedef struct dladm_linkprop_args_s {
12411878SVenu.Iyer@Sun.COM 	dladm_status_t	dla_status;
12511878SVenu.Iyer@Sun.COM 	uint_t		dla_flags;
12611878SVenu.Iyer@Sun.COM } dladm_linkprop_args_t;
12711878SVenu.Iyer@Sun.COM 
1287663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t,
1298275SEric Cheng 			    const char *, uint_t, dladm_status_t *);
1307663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t,
1318275SEric Cheng 			    mac_prop_id_t, uint_t, dladm_status_t *);
13211878SVenu.Iyer@Sun.COM static dladm_status_t	i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
13311878SVenu.Iyer@Sun.COM 			    char *, uint_t, uint_t *, void *, size_t);
13411878SVenu.Iyer@Sun.COM 
13511878SVenu.Iyer@Sun.COM static dladm_status_t	i_dladm_set_private_prop(dladm_handle_t, datalink_id_t,
1368453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
13711878SVenu.Iyer@Sun.COM static dladm_status_t	i_dladm_get_priv_prop(dladm_handle_t, datalink_id_t,
1388453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *, dladm_prop_type_t,
1398453SAnurag.Maskey@Sun.COM 			    uint_t);
1408453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_macprop(dladm_handle_t, void *, boolean_t);
1418275SEric Cheng static const char	*dladm_perm2str(uint_t, char *);
14211878SVenu.Iyer@Sun.COM static link_attr_t	*dladm_name2prop(const char *);
14311878SVenu.Iyer@Sun.COM static link_attr_t	*dladm_id2prop(mac_prop_id_t);
14411878SVenu.Iyer@Sun.COM 
14511878SVenu.Iyer@Sun.COM static pd_getf_t	get_zone, get_autopush, get_rate_mod, get_rate,
14611878SVenu.Iyer@Sun.COM 			get_speed, get_channel, get_powermode, get_radio,
14711878SVenu.Iyer@Sun.COM 			get_duplex, get_link_state, get_binary, get_uint32,
14811878SVenu.Iyer@Sun.COM 			get_flowctl, get_maxbw, get_cpus, get_priority,
14911878SVenu.Iyer@Sun.COM 			get_tagmode, get_range, get_stp, get_bridge_forward,
15011878SVenu.Iyer@Sun.COM 			get_bridge_pvid, get_protection, get_rxrings,
15111878SVenu.Iyer@Sun.COM 			get_txrings, get_cntavail,
15211878SVenu.Iyer@Sun.COM 			get_allowedips, get_allowedcids, get_pool,
15312163SRamaswamy.Tummala@Sun.COM 			get_rings_range, get_linkmode_prop;
15411878SVenu.Iyer@Sun.COM 
15511878SVenu.Iyer@Sun.COM static pd_setf_t	set_zone, set_rate, set_powermode, set_radio,
15611878SVenu.Iyer@Sun.COM 			set_public_prop, set_resource, set_stp_prop,
15711878SVenu.Iyer@Sun.COM 			set_bridge_forward, set_bridge_pvid;
15811878SVenu.Iyer@Sun.COM 
15911878SVenu.Iyer@Sun.COM static pd_checkf_t	check_zone, check_autopush, check_rate, check_hoplimit,
16011878SVenu.Iyer@Sun.COM 			check_encaplim, check_uint32, check_maxbw, check_cpus,
16111878SVenu.Iyer@Sun.COM 			check_stp_prop, check_bridge_pvid, check_allowedips,
16211878SVenu.Iyer@Sun.COM 			check_allowedcids, check_rings,
16311878SVenu.Iyer@Sun.COM 			check_pool, check_prop;
1648275SEric Cheng 
1658275SEric Cheng struct prop_desc {
1665895Syz147064 	/*
1675895Syz147064 	 * link property name
1685895Syz147064 	 */
1695895Syz147064 	char			*pd_name;
1705895Syz147064 
1715895Syz147064 	/*
1725895Syz147064 	 * default property value, can be set to { "", NULL }
1735895Syz147064 	 */
1745895Syz147064 	val_desc_t		pd_defval;
1755895Syz147064 
1765895Syz147064 	/*
1775895Syz147064 	 * list of optional property values, can be NULL.
1785895Syz147064 	 *
1795895Syz147064 	 * This is set to non-NULL if there is a list of possible property
1805895Syz147064 	 * values.  pd_optval would point to the array of possible values.
1815895Syz147064 	 */
1825895Syz147064 	val_desc_t		*pd_optval;
1835895Syz147064 
1845895Syz147064 	/*
1855895Syz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
1865895Syz147064 	 */
1875895Syz147064 	uint_t			pd_noptval;
1885895Syz147064 
1895895Syz147064 	/*
19010491SRishi.Srivatsavai@Sun.COM 	 * callback to set link property; set to NULL if this property is
19110491SRishi.Srivatsavai@Sun.COM 	 * read-only and may be called before or after permanent update; see
19210491SRishi.Srivatsavai@Sun.COM 	 * flags.
1935895Syz147064 	 */
1945895Syz147064 	pd_setf_t		*pd_set;
1955895Syz147064 
1965895Syz147064 	/*
1975895Syz147064 	 * callback to get modifiable link property
1985895Syz147064 	 */
1995895Syz147064 	pd_getf_t		*pd_getmod;
2005895Syz147064 
2015895Syz147064 	/*
2025895Syz147064 	 * callback to get current link property
2035895Syz147064 	 */
2045895Syz147064 	pd_getf_t		*pd_get;
2055895Syz147064 
2065895Syz147064 	/*
2075895Syz147064 	 * callback to validate link property value, set to NULL if pd_optval
2085895Syz147064 	 * is not NULL. In that case, validate the value by comparing it with
2095895Syz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
2105895Syz147064 	 * valid.
2115895Syz147064 	 */
2125895Syz147064 	pd_checkf_t		*pd_check;
2135895Syz147064 
2145895Syz147064 	uint_t			pd_flags;
2155903Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
2165903Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
21710491SRishi.Srivatsavai@Sun.COM #define	PD_AFTER_PERM	0x4	/* pd_set after db update; no temporary */
2185895Syz147064 	/*
2195895Syz147064 	 * indicate link classes this property applies to.
2205895Syz147064 	 */
2215895Syz147064 	datalink_class_t	pd_class;
2225895Syz147064 
2235895Syz147064 	/*
2245895Syz147064 	 * indicate link media type this property applies to.
2255895Syz147064 	 */
2265895Syz147064 	datalink_media_t	pd_dmedia;
2278275SEric Cheng };
2283448Sdh155122 
2296789Sam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
2305903Ssowmini 
2317663SSowmini.Varadhan@Sun.COM /*
2327663SSowmini.Varadhan@Sun.COM  * Supported link properties enumerated in the prop_table[] array are
2337663SSowmini.Varadhan@Sun.COM  * computed using the callback functions in that array. To compute the
2347663SSowmini.Varadhan@Sun.COM  * property value, multiple distinct system calls may be needed (e.g.,
2357663SSowmini.Varadhan@Sun.COM  * for wifi speed, we need to issue system calls to get desired/supported
2367663SSowmini.Varadhan@Sun.COM  * rates). The link_attr[] table enumerates the interfaces to the kernel,
2377663SSowmini.Varadhan@Sun.COM  * and the type/size of the data passed in the user-kernel interface.
2387663SSowmini.Varadhan@Sun.COM  */
2397663SSowmini.Varadhan@Sun.COM static link_attr_t link_attr[] = {
2407663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),	"duplex"},
2415903Ssowmini 
2427663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_SPEED,	sizeof (uint64_t),	"speed"},
2437663SSowmini.Varadhan@Sun.COM 
2447663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_STATUS,	sizeof (link_state_t),	"state"},
2457663SSowmini.Varadhan@Sun.COM 
2467663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),	"adv_autoneg_cap"},
2475903Ssowmini 
2487663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_MTU,		sizeof (uint32_t),	"mtu"},
2495903Ssowmini 
2507663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t), "flowctrl"},
2517663SSowmini.Varadhan@Sun.COM 
2527663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),	"zone"},
2535903Ssowmini 
2547663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush), "autopush"},
2557663SSowmini.Varadhan@Sun.COM 
2569449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_ADV_10GFDX_CAP, sizeof (uint8_t),	"adv_10gfdx_cap"},
2579449Sxiuyan.wang@Sun.COM 
2589449Sxiuyan.wang@Sun.COM 	{ MAC_PROP_EN_10GFDX_CAP, sizeof (uint8_t),	"en_10gfdx_cap"},
2599449Sxiuyan.wang@Sun.COM 
2607663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),	"adv_1000fdx_cap"},
2617663SSowmini.Varadhan@Sun.COM 
2627663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),	"en_1000fdx_cap"},
2635903Ssowmini 
2647663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),	"adv_1000hdx_cap"},
2655903Ssowmini 
2667663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),	"en_1000hdx_cap"},
2677663SSowmini.Varadhan@Sun.COM 
2687663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),	"adv_100fdx_cap"},
2697342SAruna.Ramakrishna@Sun.COM 
2707663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),	"en_100fdx_cap"},
2717663SSowmini.Varadhan@Sun.COM 
2727663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),	"adv_100hdx_cap"},
2737663SSowmini.Varadhan@Sun.COM 
2747663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),	"en_100hdx_cap"},
2757342SAruna.Ramakrishna@Sun.COM 
2767663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),	"adv_10fdx_cap"},
2777663SSowmini.Varadhan@Sun.COM 
2787663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),	"en_10fdx_cap"},
2795903Ssowmini 
2807663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),	"adv_10hdx_cap"},
2817663SSowmini.Varadhan@Sun.COM 
2827663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),	"en_10hdx_cap"},
2835903Ssowmini 
2847663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESSID,	sizeof (wl_linkstatus_t), "essid"},
2857663SSowmini.Varadhan@Sun.COM 
2867663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSID,	sizeof (wl_bssid_t),	"bssid"},
2875903Ssowmini 
2887663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_BSSTYPE,	sizeof (wl_bss_type_t),	"bsstype"},
2897663SSowmini.Varadhan@Sun.COM 
2907663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"},
2917663SSowmini.Varadhan@Sun.COM 
2927663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2937663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"},
2945903Ssowmini 
2957663SSowmini.Varadhan@Sun.COM 	/* wl_rates_t has variable length */
2967663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"},
2977663SSowmini.Varadhan@Sun.COM 
2987663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"},
2995903Ssowmini 
3007663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"},
3017663SSowmini.Varadhan@Sun.COM 
3027663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RSSI,	sizeof (wl_rssi_t),	"signal"},
3035903Ssowmini 
3047663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"},
3057663SSowmini.Varadhan@Sun.COM 
3067663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"},
3075903Ssowmini 
3087663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_WPA,	sizeof (wl_wpa_t),	"wpa"},
3097663SSowmini.Varadhan@Sun.COM 
3107663SSowmini.Varadhan@Sun.COM 	/*  wl_wpa_ess_t has variable length */
3117663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"},
3125903Ssowmini 
3137663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"},
3147663SSowmini.Varadhan@Sun.COM 
3157663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_RADIO,	sizeof (dladm_wlan_radio_t), "wl_radio"},
3165903Ssowmini 
3177663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t),	"wl_ess_list"},
3187663SSowmini.Varadhan@Sun.COM 
3197663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY_TAB,	sizeof (wl_wep_key_tab_t), "wl_wep_key"},
3205903Ssowmini 
3217663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"},
3227663SSowmini.Varadhan@Sun.COM 
3237663SSowmini.Varadhan@Sun.COM 	/* wl_wpa_ie_t has variable length */
3247663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_SETOPTIE,	sizeof (wl_wpa_ie_t),	"set_ie"},
3255903Ssowmini 
3267663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_DELKEY,	sizeof (wl_del_key_t),	"wpa_del_key"},
3277663SSowmini.Varadhan@Sun.COM 
3287663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_KEY,	sizeof (wl_key_t),	"wl_key"},
3295903Ssowmini 
3307663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_WL_MLME,	sizeof (wl_mlme_t),	"mlme"},
3317663SSowmini.Varadhan@Sun.COM 
3328874SSebastien.Roy@Sun.COM 	{ MAC_PROP_TAGMODE,	sizeof (link_tagmode_t),	"tagmode"},
3338874SSebastien.Roy@Sun.COM 
33410616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_HOPLIMIT, sizeof (uint32_t),	"hoplimit"},
33510616SSebastien.Roy@Sun.COM 
33610616SSebastien.Roy@Sun.COM 	{ MAC_PROP_IPTUN_ENCAPLIMIT, sizeof (uint32_t),	"encaplimit"},
33710616SSebastien.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 
34411878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RESOURCE,	sizeof (mac_resource_props_t),	"resource"},
34511878SVenu.Iyer@Sun.COM 
34611878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RESOURCE_EFF, sizeof (mac_resource_props_t),
34711878SVenu.Iyer@Sun.COM 	    "resource-effective"},
34811878SVenu.Iyer@Sun.COM 
34911878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RXRINGSRANGE, sizeof (mac_propval_range_t),	"rxrings"},
35011878SVenu.Iyer@Sun.COM 
35111878SVenu.Iyer@Sun.COM 	{ MAC_PROP_TXRINGSRANGE, sizeof (mac_propval_range_t),	"txrings"},
35211878SVenu.Iyer@Sun.COM 
35311878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_TX_RINGS_AVAIL,	sizeof (uint_t),
35411878SVenu.Iyer@Sun.COM 	    "txrings-available"},
35511878SVenu.Iyer@Sun.COM 
35611878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_RX_RINGS_AVAIL,	sizeof (uint_t),
35711878SVenu.Iyer@Sun.COM 	    "rxrings-available"},
35811878SVenu.Iyer@Sun.COM 
35911878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_RXHWCLNT_AVAIL,	sizeof (uint_t), "rxhwclnt-available"},
36011878SVenu.Iyer@Sun.COM 
36111878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_TXHWCLNT_AVAIL,	sizeof (uint_t), "txhwclnt-available"},
36210734SEric Cheng 
36312163SRamaswamy.Tummala@Sun.COM 	{ MAC_PROP_IB_LINKMODE,	sizeof (uint32_t),	"linkmode"},
36412163SRamaswamy.Tummala@Sun.COM 
3657663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3665903Ssowmini };
3675903Ssowmini 
36810491SRishi.Srivatsavai@Sun.COM typedef struct bridge_public_prop_s {
36910491SRishi.Srivatsavai@Sun.COM 	const char	*bpp_name;
37010491SRishi.Srivatsavai@Sun.COM 	int		bpp_code;
37110491SRishi.Srivatsavai@Sun.COM } bridge_public_prop_t;
37210491SRishi.Srivatsavai@Sun.COM 
37310491SRishi.Srivatsavai@Sun.COM static const bridge_public_prop_t bridge_prop[] = {
37410491SRishi.Srivatsavai@Sun.COM 	{ "stp", PT_CFG_NON_STP },
37510491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", PT_CFG_PRIO },
37610491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", PT_CFG_COST },
37710491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", PT_CFG_EDGE },
37810491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", PT_CFG_P2P },
37910491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", PT_CFG_MCHECK },
38010491SRishi.Srivatsavai@Sun.COM 	{ NULL, 0 }
38110491SRishi.Srivatsavai@Sun.COM };
38210491SRishi.Srivatsavai@Sun.COM 
3835903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3845903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3855903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3865903Ssowmini };
3875903Ssowmini static  val_desc_t	link_status_vals[] = {
3885903Ssowmini 	{ "up",		LINK_STATE_UP		},
3895903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3905903Ssowmini };
3915903Ssowmini static  val_desc_t	link_01_vals[] = {
3925903Ssowmini 	{ "1",		1			},
3935903Ssowmini 	{ "0",		0			}
3945903Ssowmini };
3955903Ssowmini static  val_desc_t	link_flow_vals[] = {
3965903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3975903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3985903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3995903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
4005903Ssowmini };
4018275SEric Cheng static  val_desc_t	link_priority_vals[] = {
4028275SEric Cheng 	{ "low",	MPL_LOW	},
4038275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
4048275SEric Cheng 	{ "high",	MPL_HIGH	}
4058275SEric Cheng };
4065903Ssowmini 
4078874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
4088874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
4098874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
4108874SSebastien.Roy@Sun.COM };
4118874SSebastien.Roy@Sun.COM 
41210734SEric Cheng static  val_desc_t	link_protect_vals[] = {
41310734SEric Cheng 	{ "mac-nospoof",	MPT_MACNOSPOOF	},
41411878SVenu.Iyer@Sun.COM 	{ "restricted",		MPT_RESTRICTED	},
41510734SEric Cheng 	{ "ip-nospoof",		MPT_IPNOSPOOF	},
41611878SVenu.Iyer@Sun.COM 	{ "dhcp-nospoof",	MPT_DHCPNOSPOOF	},
41710734SEric Cheng };
41810734SEric Cheng 
4195895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
4205895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
4215895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
4225895Syz147064 };
4235895Syz147064 
4245895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
4255895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
4265895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
4275895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
4285895Syz147064 };
4295895Syz147064 
43010491SRishi.Srivatsavai@Sun.COM static  val_desc_t	stp_p2p_vals[] = {
43110491SRishi.Srivatsavai@Sun.COM 	{ "true",	P2P_FORCE_TRUE		},
43210491SRishi.Srivatsavai@Sun.COM 	{ "false",	P2P_FORCE_FALSE		},
43310491SRishi.Srivatsavai@Sun.COM 	{ "auto",	P2P_AUTO		}
43410491SRishi.Srivatsavai@Sun.COM };
43510491SRishi.Srivatsavai@Sun.COM 
436*12303SRajkumar.Sivaprakasam@Sun.COM static  val_desc_t	dladm_part_linkmode_vals[] = {
437*12303SRajkumar.Sivaprakasam@Sun.COM 	{ "cm",		DLADM_PART_CM_MODE	},
438*12303SRajkumar.Sivaprakasam@Sun.COM 	{ "ud",		DLADM_PART_UD_MODE	},
43912163SRamaswamy.Tummala@Sun.COM };
44012163SRamaswamy.Tummala@Sun.COM 
4418275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
4428275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
44311878SVenu.Iyer@Sun.COM #define	UNSPEC_VAL	((uintptr_t)-2)
4448275SEric Cheng 
4453448Sdh155122 static prop_desc_t	prop_table[] = {
4465903Ssowmini 	{ "channel",	{ NULL, 0 },
4475903Ssowmini 	    NULL, 0, NULL, NULL,
44811878SVenu.Iyer@Sun.COM 	    get_channel, NULL, 0,
4495903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4505895Syz147064 
4515895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
4525895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
45311878SVenu.Iyer@Sun.COM 	    set_powermode, NULL,
45411878SVenu.Iyer@Sun.COM 	    get_powermode, NULL, 0,
4555903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4565895Syz147064 
4575895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
4585895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
45911878SVenu.Iyer@Sun.COM 	    set_radio, NULL,
46011878SVenu.Iyer@Sun.COM 	    get_radio, NULL, 0,
4615903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4625895Syz147064 
463*12303SRajkumar.Sivaprakasam@Sun.COM 	{ "linkmode",	{ "cm", DLADM_PART_CM_MODE },
464*12303SRajkumar.Sivaprakasam@Sun.COM 	    dladm_part_linkmode_vals, VALCNT(dladm_part_linkmode_vals),
46512163SRamaswamy.Tummala@Sun.COM 	    set_public_prop, NULL, get_linkmode_prop, NULL, 0,
46612163SRamaswamy.Tummala@Sun.COM 	    DATALINK_CLASS_PART, DL_IB },
46712163SRamaswamy.Tummala@Sun.COM 
4685895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
46911878SVenu.Iyer@Sun.COM 	    set_rate, get_rate_mod,
47011878SVenu.Iyer@Sun.COM 	    get_rate, check_rate, 0,
4715960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
4725895Syz147064 
4736512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
47411878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL,
47511878SVenu.Iyer@Sun.COM 	    get_autopush, check_autopush, PD_CHECK_ALLOC,
4765903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4775895Syz147064 
4786512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
47911878SVenu.Iyer@Sun.COM 	    set_zone, NULL,
48011878SVenu.Iyer@Sun.COM 	    get_zone, check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4815903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4825903Ssowmini 
4838275SEric Cheng 	{ "duplex",	{ "", 0 },
4845903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
48511878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_duplex, NULL,
4865903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4875903Ssowmini 
4888275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4895903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
49011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_link_state, NULL,
4916512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4925903Ssowmini 
49310191SSowmini.Varadhan@Sun.COM 	{ "adv_autoneg_cap", { "", 0 },
4945903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
49511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
4965903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4975903Ssowmini 
4986512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
49911878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range,
50011878SVenu.Iyer@Sun.COM 	    get_uint32, check_uint32, 0, DATALINK_CLASS_ALL,
5017342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
5025903Ssowmini 
5036512Ssowmini 	{ "flowctrl", { "", 0 },
5045903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
50511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_flowctl, NULL,
5065903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5075903Ssowmini 
5089449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
5099449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
51011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5119449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5129449Sxiuyan.wang@Sun.COM 
5139449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
5149449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
51511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5169449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5179449Sxiuyan.wang@Sun.COM 
5186512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
5196512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
52011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5215903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5225903Ssowmini 
5236512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
5245903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
52511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5265903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5275903Ssowmini 
5286512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
5295903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
53011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5315903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5325903Ssowmini 
5336512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
5345903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
53511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5365903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5375903Ssowmini 
5386512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
5395903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
54011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5415903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5425903Ssowmini 
5436512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
5445903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
54511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5465903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5475903Ssowmini 
5486512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
5495903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
55011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5515903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5525903Ssowmini 
5536512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
5545903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
55511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5565903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5575903Ssowmini 
5586512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
5595903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
56011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5615903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5625903Ssowmini 
5636512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
5645903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
56511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5665903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5675903Ssowmini 
5686512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
5695903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
57011878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5715903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5725903Ssowmini 
5736512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
5745903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
57511878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5768275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5778275SEric Cheng 
5788275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
57911878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
58011878SVenu.Iyer@Sun.COM 	    get_maxbw, check_maxbw, PD_CHECK_ALLOC,
5818275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5828275SEric Cheng 
5838275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
58411878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
58511878SVenu.Iyer@Sun.COM 	    get_cpus, check_cpus, 0,
58611878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
58711878SVenu.Iyer@Sun.COM 
58811878SVenu.Iyer@Sun.COM 	{ "cpus-effective", { "--", 0 },
58911878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
59011878SVenu.Iyer@Sun.COM 	    get_cpus, 0, 0,
5918275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5928275SEric Cheng 
59311878SVenu.Iyer@Sun.COM 	{ "pool", { "--", RESET_VAL }, NULL, 0,
59411878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
59511878SVenu.Iyer@Sun.COM 	    get_pool, check_pool, 0,
59611878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
59711878SVenu.Iyer@Sun.COM 
59811878SVenu.Iyer@Sun.COM 	{ "pool-effective", { "--", 0 },
59911878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
60011878SVenu.Iyer@Sun.COM 	    get_pool, 0, 0,
60111878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
60211878SVenu.Iyer@Sun.COM 
60311878SVenu.Iyer@Sun.COM 	{ "priority", { "high", MPL_RESET },
60411878SVenu.Iyer@Sun.COM 	    link_priority_vals, VALCNT(link_priority_vals), set_resource,
60511878SVenu.Iyer@Sun.COM 	    NULL, get_priority, check_prop, 0,
6068275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
6078874SSebastien.Roy@Sun.COM 
6088874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
6098874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
61011878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_tagmode,
6118874SSebastien.Roy@Sun.COM 	    NULL, 0,
6128874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
61310491SRishi.Srivatsavai@Sun.COM 	    DL_ETHER },
61410491SRishi.Srivatsavai@Sun.COM 
61510616SSebastien.Roy@Sun.COM 	{ "hoplimit", { "", 0 }, NULL, 0,
61611878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range, get_uint32,
61711878SVenu.Iyer@Sun.COM 	    check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
61810616SSebastien.Roy@Sun.COM 
61910616SSebastien.Roy@Sun.COM 	{ "encaplimit", { "", 0 }, NULL, 0,
62011878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range, get_uint32,
62111878SVenu.Iyer@Sun.COM 	    check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
62210616SSebastien.Roy@Sun.COM 
62310491SRishi.Srivatsavai@Sun.COM 	{ "forward", { "1", 1 },
62410491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
62510491SRishi.Srivatsavai@Sun.COM 	    set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
62610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
62710491SRishi.Srivatsavai@Sun.COM 
62810491SRishi.Srivatsavai@Sun.COM 	{ "default_tag", { "1", 1 }, NULL, 0,
62910491SRishi.Srivatsavai@Sun.COM 	    set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
63010491SRishi.Srivatsavai@Sun.COM 	    0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
63110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
63210491SRishi.Srivatsavai@Sun.COM 
63310491SRishi.Srivatsavai@Sun.COM 	{ "learn_limit", { "1000", 1000 }, NULL, 0,
63411878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_uint32,
63511878SVenu.Iyer@Sun.COM 	    check_uint32, 0,
63610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
63710491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
63810491SRishi.Srivatsavai@Sun.COM 
63910491SRishi.Srivatsavai@Sun.COM 	{ "learn_decay", { "200", 200 }, NULL, 0,
64011878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_uint32,
64111878SVenu.Iyer@Sun.COM 	    check_uint32, 0,
64210491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
64310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
64410491SRishi.Srivatsavai@Sun.COM 
64510491SRishi.Srivatsavai@Sun.COM 	{ "stp", { "1", 1 },
64610491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
64711878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
64810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
64910491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
65010491SRishi.Srivatsavai@Sun.COM 
65110491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", { "128", 128 }, NULL, 0,
65211878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
65310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
65410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
65510491SRishi.Srivatsavai@Sun.COM 
65610491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", { "auto", 0 }, NULL, 0,
65711878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
65810491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
65910491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
66010491SRishi.Srivatsavai@Sun.COM 
66110491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", { "1", 1 },
66210491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
66311878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
66410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
66510491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
66610491SRishi.Srivatsavai@Sun.COM 
66710491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", { "auto", P2P_AUTO },
66810491SRishi.Srivatsavai@Sun.COM 	    stp_p2p_vals, VALCNT(stp_p2p_vals),
66911878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
67010491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
67110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
67210491SRishi.Srivatsavai@Sun.COM 
67310491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", { "0", 0 },
67410491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
67511878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
67610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
67710491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
67810734SEric Cheng 
67910734SEric Cheng 	{ "protection", { "--", RESET_VAL },
68010734SEric Cheng 	    link_protect_vals, VALCNT(link_protect_vals),
68111878SVenu.Iyer@Sun.COM 	    set_resource, NULL, get_protection, check_prop, 0,
68210734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
68310734SEric Cheng 
68410734SEric Cheng 	{ "allowed-ips", { "--", 0 },
68511878SVenu.Iyer@Sun.COM 	    NULL, 0, set_resource, NULL,
68611878SVenu.Iyer@Sun.COM 	    get_allowedips, check_allowedips, PD_CHECK_ALLOC,
68711878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
68811878SVenu.Iyer@Sun.COM 
68911878SVenu.Iyer@Sun.COM 	{ "allowed-dhcp-cids", { "--", 0 },
69011878SVenu.Iyer@Sun.COM 	    NULL, 0, set_resource, NULL,
69111878SVenu.Iyer@Sun.COM 	    get_allowedcids, check_allowedcids, PD_CHECK_ALLOC,
69211878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
69311878SVenu.Iyer@Sun.COM 
69411878SVenu.Iyer@Sun.COM 	{ "rxrings", { "--", RESET_VAL }, NULL, 0,
69511878SVenu.Iyer@Sun.COM 	    set_resource, get_rings_range, get_rxrings, check_rings, 0,
69611878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
69711878SVenu.Iyer@Sun.COM 
69811878SVenu.Iyer@Sun.COM 	{ "rxrings-effective", { "--", 0 },
69911878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
70011878SVenu.Iyer@Sun.COM 	    get_rxrings, NULL, 0,
70111878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
70211878SVenu.Iyer@Sun.COM 
70311878SVenu.Iyer@Sun.COM 	{ "txrings", { "--", RESET_VAL }, NULL, 0,
70411878SVenu.Iyer@Sun.COM 	    set_resource, get_rings_range, get_txrings, check_rings, 0,
70510734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
70611878SVenu.Iyer@Sun.COM 
70711878SVenu.Iyer@Sun.COM 	{ "txrings-effective", { "--", 0 },
70811878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
70911878SVenu.Iyer@Sun.COM 	    get_txrings, NULL, 0,
71011878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
71111878SVenu.Iyer@Sun.COM 
71211878SVenu.Iyer@Sun.COM 	{ "txrings-available", { "", 0 }, NULL, 0,
71311878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
71411878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
71511878SVenu.Iyer@Sun.COM 
71611878SVenu.Iyer@Sun.COM 	{ "rxrings-available", { "", 0 }, NULL, 0,
71711878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
71811878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
71911878SVenu.Iyer@Sun.COM 
72011878SVenu.Iyer@Sun.COM 	{ "rxhwclnt-available", { "", 0 }, NULL, 0,
72111878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
72211878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
72311878SVenu.Iyer@Sun.COM 
72411878SVenu.Iyer@Sun.COM 	{ "txhwclnt-available", { "", 0 }, NULL, 0,
72511878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
72611878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
72711878SVenu.Iyer@Sun.COM 
7283448Sdh155122 };
7293448Sdh155122 
7305895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
7315895Syz147064 
7328275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
73311878SVenu.Iyer@Sun.COM 	{"maxbw",		extract_maxbw},
73411878SVenu.Iyer@Sun.COM 	{"priority",		extract_priority},
73511878SVenu.Iyer@Sun.COM 	{"cpus",		extract_cpus},
73611878SVenu.Iyer@Sun.COM 	{"cpus-effective",	extract_cpus},
73711878SVenu.Iyer@Sun.COM 	{"pool",		extract_pool},
73811878SVenu.Iyer@Sun.COM 	{"pool-effective",	extract_pool},
73911878SVenu.Iyer@Sun.COM 	{"protection",		extract_protection},
74011878SVenu.Iyer@Sun.COM 	{"allowed-ips",		extract_allowedips},
74111878SVenu.Iyer@Sun.COM 	{"allowed-dhcp-cids",	extract_allowedcids},
74211878SVenu.Iyer@Sun.COM 	{"rxrings",		extract_rxrings},
74311878SVenu.Iyer@Sun.COM 	{"rxrings-effective",	extract_rxrings},
74411878SVenu.Iyer@Sun.COM 	{"txrings",		extract_txrings},
74511878SVenu.Iyer@Sun.COM 	{"txrings-effective",	extract_txrings}
7468275SEric Cheng };
7478275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
7488275SEric Cheng 	sizeof (resource_prop_t))
7498275SEric Cheng 
7507663SSowmini.Varadhan@Sun.COM /*
7517663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
7527663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
7537663SSowmini.Varadhan@Sun.COM  */
7547663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
7557663SSowmini.Varadhan@Sun.COM 
7568453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
7578453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
7588453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
7598453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
7608460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
7618460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
7628460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
7638453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
7648453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
7658453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
7668453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
7678453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
7688453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
7698453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
7708275SEric Cheng 
7715895Syz147064 /*
7725895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
7735895Syz147064  * rates to be retrieved. However, we cannot increase it at this
7745895Syz147064  * time because it will break binary compatibility with unbundled
7755895Syz147064  * WiFi drivers and utilities. So for now we define an additional
7765895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
7775895Syz147064  */
7785895Syz147064 #define	MAX_SUPPORT_RATES	64
7795895Syz147064 
7805895Syz147064 #define	AP_ANCHOR	"[anchor]"
7815895Syz147064 #define	AP_DELIMITER	'.'
7825895Syz147064 
78310734SEric Cheng /* ARGSUSED */
7845895Syz147064 static dladm_status_t
78511878SVenu.Iyer@Sun.COM check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
78611878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
78711878SVenu.Iyer@Sun.COM     datalink_media_t media)
7885895Syz147064 {
7895895Syz147064 	int		i, j;
7903147Sxc151355 
7915895Syz147064 	for (j = 0; j < val_cnt; j++) {
7925895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
79310734SEric Cheng 			if (strcasecmp(prop_val[j],
7945895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
7955895Syz147064 				break;
7965895Syz147064 			}
7975895Syz147064 		}
79810734SEric Cheng 		if (i == pdp->pd_noptval)
79910734SEric Cheng 			return (DLADM_STATUS_BADVAL);
80010734SEric Cheng 
80110734SEric Cheng 		(void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
8025895Syz147064 	}
80310734SEric Cheng 	return (DLADM_STATUS_OK);
8045895Syz147064 }
8055895Syz147064 
8065895Syz147064 static dladm_status_t
8078453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
8088453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
8098453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
8103147Sxc151355 {
8115895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
8125895Syz147064 	val_desc_t	*vdp = NULL;
8135895Syz147064 	boolean_t	needfree = B_FALSE;
8145895Syz147064 	uint_t		cnt, i;
8153147Sxc151355 
8165895Syz147064 	if (!(pdp->pd_class & class))
8175895Syz147064 		return (DLADM_STATUS_BADARG);
8185895Syz147064 
8195895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
8203147Sxc151355 		return (DLADM_STATUS_BADARG);
8213147Sxc151355 
8225895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
8235895Syz147064 		return (DLADM_STATUS_TEMPONLY);
8245895Syz147064 
8255895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
8265895Syz147064 		return (DLADM_STATUS_OK);
8275895Syz147064 
8285895Syz147064 	if (pdp->pd_set == NULL)
8295895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
8303448Sdh155122 
8315895Syz147064 	if (prop_val != NULL) {
83211878SVenu.Iyer@Sun.COM 		vdp = calloc(val_cnt, sizeof (val_desc_t));
8335895Syz147064 		if (vdp == NULL)
8345895Syz147064 			return (DLADM_STATUS_NOMEM);
8355895Syz147064 
8365895Syz147064 		if (pdp->pd_check != NULL) {
8378275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
8388453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
83911878SVenu.Iyer@Sun.COM 			    val_cnt, flags, vdp, media);
8405895Syz147064 		} else if (pdp->pd_optval != NULL) {
84111878SVenu.Iyer@Sun.COM 			status = check_prop(handle, pdp, linkid, prop_val,
84211878SVenu.Iyer@Sun.COM 			    val_cnt, flags, vdp, media);
8435895Syz147064 		} else {
8443448Sdh155122 			status = DLADM_STATUS_BADARG;
8453147Sxc151355 		}
8465895Syz147064 
8473147Sxc151355 		if (status != DLADM_STATUS_OK)
8485895Syz147064 			goto done;
8495895Syz147064 
8505895Syz147064 		cnt = val_cnt;
8515895Syz147064 	} else {
8528275SEric Cheng 		boolean_t	defval = B_FALSE;
8538275SEric Cheng 
8545895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
8555895Syz147064 			return (DLADM_STATUS_NOTSUP);
8565895Syz147064 
8577342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
8588275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
8598275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
86011878SVenu.Iyer@Sun.COM 			if ((vdp = calloc(1, sizeof (val_desc_t))) == NULL)
8616512Ssowmini 				return (DLADM_STATUS_NOMEM);
8627342SAruna.Ramakrishna@Sun.COM 
8638275SEric Cheng 			if (defval) {
8648275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
8658275SEric Cheng 				    sizeof (val_desc_t));
8668275SEric Cheng 			} else if (pdp->pd_check != NULL) {
8678453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
86811878SVenu.Iyer@Sun.COM 				    prop_val, cnt, flags, vdp, media);
8697342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
8707342SAruna.Ramakrishna@Sun.COM 					goto done;
8717342SAruna.Ramakrishna@Sun.COM 			}
8726512Ssowmini 		} else {
8738453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
8746512Ssowmini 			    media, flags);
8756512Ssowmini 			return (status);
8766512Ssowmini 		}
8775895Syz147064 	}
87810491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_AFTER_PERM)
87910491SRishi.Srivatsavai@Sun.COM 		status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
88010491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_PERMONLY;
88110491SRishi.Srivatsavai@Sun.COM 	else
88210491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
88310491SRishi.Srivatsavai@Sun.COM 		    media);
8845895Syz147064 	if (needfree) {
8855895Syz147064 		for (i = 0; i < cnt; i++)
8865903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
8873147Sxc151355 	}
8885895Syz147064 done:
8895895Syz147064 	free(vdp);
8905895Syz147064 	return (status);
8915895Syz147064 }
8925895Syz147064 
8935895Syz147064 static dladm_status_t
8948453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8958453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8965895Syz147064 {
8975895Syz147064 	int			i;
8985895Syz147064 	boolean_t		found = B_FALSE;
8995895Syz147064 	datalink_class_t	class;
9005895Syz147064 	uint32_t		media;
9015895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
9025895Syz147064 
9038453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9048453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9055895Syz147064 	if (status != DLADM_STATUS_OK)
9065895Syz147064 		return (status);
9075895Syz147064 
9085895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
9095895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
9105895Syz147064 		dladm_status_t	s;
9115895Syz147064 
9125895Syz147064 		if (prop_name != NULL &&
9135895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
9145895Syz147064 			continue;
9155895Syz147064 		found = B_TRUE;
9168453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
9178453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
9183448Sdh155122 
9195895Syz147064 		if (prop_name != NULL) {
9205895Syz147064 			status = s;
9215895Syz147064 			break;
9225895Syz147064 		} else {
9235895Syz147064 			if (s != DLADM_STATUS_OK &&
9245895Syz147064 			    s != DLADM_STATUS_NOTSUP)
9255895Syz147064 				status = s;
9265895Syz147064 		}
9275895Syz147064 	}
9285903Ssowmini 	if (!found) {
9295903Ssowmini 		if (prop_name[0] == '_') {
9305903Ssowmini 			/* other private properties */
9319692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
9329692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
9335903Ssowmini 		} else  {
9345903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
9355903Ssowmini 		}
9365903Ssowmini 	}
9375895Syz147064 	return (status);
9385895Syz147064 }
9395895Syz147064 
9405895Syz147064 /*
9415895Syz147064  * Set/reset link property for specific link
9425895Syz147064  */
9435895Syz147064 dladm_status_t
9448453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9458453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
9465895Syz147064 {
9475895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
9485895Syz147064 
9495895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
9505895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
9515895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
9525895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
9535895Syz147064 		return (DLADM_STATUS_BADARG);
9545895Syz147064 	}
9555895Syz147064 
9569692SRishi.Srivatsavai@Sun.COM 	/*
9579692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
9589692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
9599692SRishi.Srivatsavai@Sun.COM 	 */
9608453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
9615895Syz147064 	    val_cnt, flags);
9625895Syz147064 	if (status != DLADM_STATUS_OK)
9635895Syz147064 		return (status);
9645895Syz147064 
9655895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
9668453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
9673147Sxc151355 		    prop_val, val_cnt);
96810491SRishi.Srivatsavai@Sun.COM 
96910491SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
97010491SRishi.Srivatsavai@Sun.COM 			prop_desc_t *pdp = prop_table;
97110491SRishi.Srivatsavai@Sun.COM 			int i;
97210491SRishi.Srivatsavai@Sun.COM 
97310491SRishi.Srivatsavai@Sun.COM 			for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
97410491SRishi.Srivatsavai@Sun.COM 				if (!(pdp->pd_flags & PD_AFTER_PERM))
97510491SRishi.Srivatsavai@Sun.COM 					continue;
97610491SRishi.Srivatsavai@Sun.COM 				if (prop_name != NULL &&
97710491SRishi.Srivatsavai@Sun.COM 				    strcasecmp(prop_name, pdp->pd_name) != 0)
97810491SRishi.Srivatsavai@Sun.COM 					continue;
97910491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_set(handle, pdp, linkid, NULL,
98010491SRishi.Srivatsavai@Sun.COM 				    0, flags, 0);
98110491SRishi.Srivatsavai@Sun.COM 			}
98210491SRishi.Srivatsavai@Sun.COM 		}
9833147Sxc151355 	}
9843147Sxc151355 	return (status);
9853147Sxc151355 }
9863147Sxc151355 
9875895Syz147064 /*
9888460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
9898460SArtem.Kachitchkin@Sun.COM  *
9908460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
9918460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
9928460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
9938460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
9945895Syz147064  */
9953147Sxc151355 dladm_status_t
9968453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
9978453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
9983147Sxc151355 {
9995895Syz147064 	dladm_status_t		status;
10005895Syz147064 	datalink_class_t	class;
10015895Syz147064 	uint_t			media;
10025895Syz147064 	int			i;
10035895Syz147064 
10045895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
10055895Syz147064 		return (DLADM_STATUS_BADARG);
10065895Syz147064 
10078453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
10088453SAnurag.Maskey@Sun.COM 	    NULL, 0);
10095895Syz147064 	if (status != DLADM_STATUS_OK)
10105895Syz147064 		return (status);
10115895Syz147064 
10128460SArtem.Kachitchkin@Sun.COM 	/* public */
10135895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
10145895Syz147064 		if (!(prop_table[i].pd_class & class))
10155895Syz147064 			continue;
10165895Syz147064 
10175895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
10185895Syz147064 			continue;
10195895Syz147064 
10208453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
10215895Syz147064 		    DLADM_WALK_TERMINATE) {
10225895Syz147064 			break;
10235895Syz147064 		}
10245895Syz147064 	}
10255895Syz147064 
10268460SArtem.Kachitchkin@Sun.COM 	/* private */
10278460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
10288460SArtem.Kachitchkin@Sun.COM 
10298460SArtem.Kachitchkin@Sun.COM 	return (status);
10305895Syz147064 }
10313448Sdh155122 
10325895Syz147064 /*
10335895Syz147064  * Get linkprop of the given specific link.
10345895Syz147064  */
10355895Syz147064 dladm_status_t
10368453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
10378453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
10388453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
10395895Syz147064 {
10405895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
10415895Syz147064 	datalink_class_t	class;
10425895Syz147064 	uint_t			media;
10435895Syz147064 	prop_desc_t		*pdp;
10446512Ssowmini 	uint_t			cnt, dld_flags = 0;
10455895Syz147064 	int			i;
10468118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
10475895Syz147064 
10486512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
104911878SVenu.Iyer@Sun.COM 		dld_flags |= DLD_PROP_DEFAULT;
10509514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
105111878SVenu.Iyer@Sun.COM 		dld_flags |= DLD_PROP_POSSIBLE;
10526512Ssowmini 
10535895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
10545895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
10555895Syz147064 		return (DLADM_STATUS_BADARG);
10565895Syz147064 
10575895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
10585895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
10595895Syz147064 			break;
10605895Syz147064 
10615903Ssowmini 	if (i == DLADM_MAX_PROPS) {
10625903Ssowmini 		if (prop_name[0] == '_') {
10635903Ssowmini 			/*
10645903Ssowmini 			 * private property.
10655903Ssowmini 			 */
10668460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
10678460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
10688460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
10698460SArtem.Kachitchkin@Sun.COM 			else
10708460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
10718460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
10728460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
10735903Ssowmini 		} else {
10745903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
10755903Ssowmini 		}
10765903Ssowmini 	}
10775895Syz147064 
10785895Syz147064 	pdp = &prop_table[i];
10795895Syz147064 
10808453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
10818453SAnurag.Maskey@Sun.COM 	    NULL, 0);
10825895Syz147064 	if (status != DLADM_STATUS_OK)
10835895Syz147064 		return (status);
10845895Syz147064 
10855895Syz147064 	if (!(pdp->pd_class & class))
10865895Syz147064 		return (DLADM_STATUS_BADARG);
10875895Syz147064 
10885895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
10893147Sxc151355 		return (DLADM_STATUS_BADARG);
10903147Sxc151355 
10915895Syz147064 	switch (type) {
10925895Syz147064 	case DLADM_PROP_VAL_CURRENT:
10938453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
10948453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
10958118SVasumathi.Sundaram@Sun.COM 		break;
10968118SVasumathi.Sundaram@Sun.COM 
10978118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
10988118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
10998118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
11008118SVasumathi.Sundaram@Sun.COM 		} else {
11018453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
11028453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
11038118SVasumathi.Sundaram@Sun.COM 		}
11048118SVasumathi.Sundaram@Sun.COM 
11058118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
11069055SMichael.Lim@Sun.COM 		*val_cntp = 1;
11078275SEric Cheng 		if (status == DLADM_STATUS_OK)
11088275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
11095895Syz147064 		break;
11105895Syz147064 
11115895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
11126768Sar224390 		/*
11136768Sar224390 		 * If defaults are not defined for the property,
11146768Sar224390 		 * pd_defval.vd_name should be null. If the driver
11156768Sar224390 		 * has to be contacted for the value, vd_name should
11166768Sar224390 		 * be the empty string (""). Otherwise, dladm will
11176768Sar224390 		 * just print whatever is in the table.
11186768Sar224390 		 */
11195895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
11205895Syz147064 			status = DLADM_STATUS_NOTSUP;
11215895Syz147064 			break;
11225895Syz147064 		}
11236512Ssowmini 
11246512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
11258453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
11268453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
11276512Ssowmini 		} else {
11286512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
11296512Ssowmini 		}
11305895Syz147064 		*val_cntp = 1;
11315895Syz147064 		break;
11323448Sdh155122 
11335895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
11345895Syz147064 		if (pdp->pd_getmod != NULL) {
11358453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
11368118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
11375895Syz147064 			break;
11385895Syz147064 		}
11395895Syz147064 		cnt = pdp->pd_noptval;
11405895Syz147064 		if (cnt == 0) {
11415895Syz147064 			status = DLADM_STATUS_NOTSUP;
11425895Syz147064 		} else if (cnt > *val_cntp) {
11435895Syz147064 			status = DLADM_STATUS_TOOSMALL;
11445895Syz147064 		} else {
11455895Syz147064 			for (i = 0; i < cnt; i++) {
11465895Syz147064 				(void) strcpy(prop_val[i],
11475895Syz147064 				    pdp->pd_optval[i].vd_name);
11485895Syz147064 			}
11495895Syz147064 			*val_cntp = cnt;
11505895Syz147064 		}
11515895Syz147064 		break;
11525895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
11535895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
11545895Syz147064 			return (DLADM_STATUS_TEMPONLY);
11558453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
11565895Syz147064 		    prop_val, val_cntp);
11575895Syz147064 		break;
11585895Syz147064 	default:
11595895Syz147064 		status = DLADM_STATUS_BADARG;
11605895Syz147064 		break;
11613147Sxc151355 	}
11623448Sdh155122 
11635895Syz147064 	return (status);
11645895Syz147064 }
11655895Syz147064 
116610491SRishi.Srivatsavai@Sun.COM /*
116710491SRishi.Srivatsavai@Sun.COM  * Get linkprop of the given specific link and run any possible conversion
116810491SRishi.Srivatsavai@Sun.COM  * of the values using the check function for the property. Fails if the
116910491SRishi.Srivatsavai@Sun.COM  * check function doesn't succeed for the property value.
117010491SRishi.Srivatsavai@Sun.COM  */
117110491SRishi.Srivatsavai@Sun.COM dladm_status_t
117210491SRishi.Srivatsavai@Sun.COM dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
117310491SRishi.Srivatsavai@Sun.COM     dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
117410491SRishi.Srivatsavai@Sun.COM     uint_t *val_cntp)
117510491SRishi.Srivatsavai@Sun.COM {
117610491SRishi.Srivatsavai@Sun.COM 	dladm_status_t		status;
117710491SRishi.Srivatsavai@Sun.COM 	datalink_class_t	class;
117810491SRishi.Srivatsavai@Sun.COM 	uint_t			media;
117910491SRishi.Srivatsavai@Sun.COM 	prop_desc_t		*pdp;
118010491SRishi.Srivatsavai@Sun.COM 	uint_t			dld_flags;
118110491SRishi.Srivatsavai@Sun.COM 	int			valc, i;
118210491SRishi.Srivatsavai@Sun.COM 	char			**prop_val;
118310491SRishi.Srivatsavai@Sun.COM 	uint_t			perm_flags;
118410491SRishi.Srivatsavai@Sun.COM 
118510491SRishi.Srivatsavai@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
118610491SRishi.Srivatsavai@Sun.COM 	    ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
118710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
118810491SRishi.Srivatsavai@Sun.COM 
118910491SRishi.Srivatsavai@Sun.COM 	for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
119010491SRishi.Srivatsavai@Sun.COM 		if (strcasecmp(prop_name, pdp->pd_name) == 0)
119110491SRishi.Srivatsavai@Sun.COM 			break;
119210491SRishi.Srivatsavai@Sun.COM 
119310491SRishi.Srivatsavai@Sun.COM 	if (pdp == prop_table + DLADM_MAX_PROPS)
119410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
119510491SRishi.Srivatsavai@Sun.COM 
119610491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_CHECK_ALLOC)
119710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
119810491SRishi.Srivatsavai@Sun.COM 
119910491SRishi.Srivatsavai@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
120010491SRishi.Srivatsavai@Sun.COM 	    NULL, 0);
120110491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
120210491SRishi.Srivatsavai@Sun.COM 		return (status);
120310491SRishi.Srivatsavai@Sun.COM 
120410491SRishi.Srivatsavai@Sun.COM 	if (!(pdp->pd_class & class))
120510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
120610491SRishi.Srivatsavai@Sun.COM 
120710491SRishi.Srivatsavai@Sun.COM 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
120810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
120910491SRishi.Srivatsavai@Sun.COM 
121010491SRishi.Srivatsavai@Sun.COM 	prop_val = malloc(*val_cntp * sizeof (*prop_val) +
121110491SRishi.Srivatsavai@Sun.COM 	    *val_cntp * DLADM_PROP_VAL_MAX);
121210491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL)
121310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOMEM);
121410491SRishi.Srivatsavai@Sun.COM 	for (valc = 0; valc < *val_cntp; valc++)
121510491SRishi.Srivatsavai@Sun.COM 		prop_val[valc] = (char *)(prop_val + *val_cntp) +
121610491SRishi.Srivatsavai@Sun.COM 		    valc * DLADM_PROP_VAL_MAX;
121710491SRishi.Srivatsavai@Sun.COM 
121811878SVenu.Iyer@Sun.COM 	dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? DLD_PROP_DEFAULT : 0;
121910491SRishi.Srivatsavai@Sun.COM 
122010491SRishi.Srivatsavai@Sun.COM 	switch (type) {
122110491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_CURRENT:
122210491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
122310491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
122410491SRishi.Srivatsavai@Sun.COM 		break;
122510491SRishi.Srivatsavai@Sun.COM 
122610491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_DEFAULT:
122710491SRishi.Srivatsavai@Sun.COM 		/*
122810491SRishi.Srivatsavai@Sun.COM 		 * If defaults are not defined for the property,
122910491SRishi.Srivatsavai@Sun.COM 		 * pd_defval.vd_name should be null. If the driver
123010491SRishi.Srivatsavai@Sun.COM 		 * has to be contacted for the value, vd_name should
123110491SRishi.Srivatsavai@Sun.COM 		 * be the empty string (""). Otherwise, dladm will
123210491SRishi.Srivatsavai@Sun.COM 		 * just print whatever is in the table.
123310491SRishi.Srivatsavai@Sun.COM 		 */
123410491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name == NULL) {
123510491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_NOTSUP;
123610491SRishi.Srivatsavai@Sun.COM 			break;
123710491SRishi.Srivatsavai@Sun.COM 		}
123810491SRishi.Srivatsavai@Sun.COM 
123910491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name[0] != '\0') {
124010491SRishi.Srivatsavai@Sun.COM 			*val_cntp = 1;
124110491SRishi.Srivatsavai@Sun.COM 			*ret_val = pdp->pd_defval.vd_val;
124210491SRishi.Srivatsavai@Sun.COM 			free(prop_val);
124310491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
124410491SRishi.Srivatsavai@Sun.COM 		}
124510491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
124610491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
124710491SRishi.Srivatsavai@Sun.COM 		break;
124810491SRishi.Srivatsavai@Sun.COM 
124910491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_PERSISTENT:
125010491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_flags & PD_TEMPONLY)
125110491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_TEMPONLY;
125210491SRishi.Srivatsavai@Sun.COM 		else
125310491SRishi.Srivatsavai@Sun.COM 			status = i_dladm_get_linkprop_db(handle, linkid,
125410491SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cntp);
125510491SRishi.Srivatsavai@Sun.COM 		break;
125610491SRishi.Srivatsavai@Sun.COM 
125710491SRishi.Srivatsavai@Sun.COM 	default:
125810491SRishi.Srivatsavai@Sun.COM 		status = DLADM_STATUS_BADARG;
125910491SRishi.Srivatsavai@Sun.COM 		break;
126010491SRishi.Srivatsavai@Sun.COM 	}
126110491SRishi.Srivatsavai@Sun.COM 
126210491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
126310491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_check != NULL) {
126410491SRishi.Srivatsavai@Sun.COM 			val_desc_t *vdp;
126510491SRishi.Srivatsavai@Sun.COM 
126610491SRishi.Srivatsavai@Sun.COM 			vdp = malloc(sizeof (val_desc_t) * *val_cntp);
126710491SRishi.Srivatsavai@Sun.COM 			if (vdp == NULL)
126810491SRishi.Srivatsavai@Sun.COM 				status = DLADM_STATUS_NOMEM;
126910491SRishi.Srivatsavai@Sun.COM 			else
127010491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
127111878SVenu.Iyer@Sun.COM 				    prop_val, *val_cntp, 0, vdp, media);
127210491SRishi.Srivatsavai@Sun.COM 			if (status == DLADM_STATUS_OK) {
127310491SRishi.Srivatsavai@Sun.COM 				for (valc = 0; valc < *val_cntp; valc++)
127410491SRishi.Srivatsavai@Sun.COM 					ret_val[valc] = vdp[valc].vd_val;
127510491SRishi.Srivatsavai@Sun.COM 			}
127610491SRishi.Srivatsavai@Sun.COM 			free(vdp);
127710491SRishi.Srivatsavai@Sun.COM 		} else {
127810491SRishi.Srivatsavai@Sun.COM 			for (valc = 0; valc < *val_cntp; valc++) {
127910491SRishi.Srivatsavai@Sun.COM 				for (i = 0; i < pdp->pd_noptval; i++) {
128010491SRishi.Srivatsavai@Sun.COM 					if (strcmp(pdp->pd_optval[i].vd_name,
128110491SRishi.Srivatsavai@Sun.COM 					    prop_val[valc]) == 0) {
128210491SRishi.Srivatsavai@Sun.COM 						ret_val[valc] =
128310491SRishi.Srivatsavai@Sun.COM 						    pdp->pd_optval[i].vd_val;
128410491SRishi.Srivatsavai@Sun.COM 						break;
128510491SRishi.Srivatsavai@Sun.COM 					}
128610491SRishi.Srivatsavai@Sun.COM 				}
128710491SRishi.Srivatsavai@Sun.COM 				if (i == pdp->pd_noptval) {
128810491SRishi.Srivatsavai@Sun.COM 					status = DLADM_STATUS_FAILED;
128910491SRishi.Srivatsavai@Sun.COM 					break;
129010491SRishi.Srivatsavai@Sun.COM 				}
129110491SRishi.Srivatsavai@Sun.COM 			}
129210491SRishi.Srivatsavai@Sun.COM 		}
129310491SRishi.Srivatsavai@Sun.COM 	}
129410491SRishi.Srivatsavai@Sun.COM 
129510491SRishi.Srivatsavai@Sun.COM 	free(prop_val);
129610491SRishi.Srivatsavai@Sun.COM 
129710491SRishi.Srivatsavai@Sun.COM 	return (status);
129810491SRishi.Srivatsavai@Sun.COM }
129910491SRishi.Srivatsavai@Sun.COM 
13005895Syz147064 /*ARGSUSED*/
13015895Syz147064 static int
13028453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
13038453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
13045895Syz147064 {
130511878SVenu.Iyer@Sun.COM 	char			*buf, **propvals;
130611878SVenu.Iyer@Sun.COM 	uint_t			i, valcnt = DLADM_MAX_PROP_VALCNT;
130711878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
130811878SVenu.Iyer@Sun.COM 	dladm_linkprop_args_t	*dla = arg;
13095895Syz147064 
13105895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
13115895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
13125895Syz147064 		return (DLADM_WALK_CONTINUE);
13135895Syz147064 	}
13145895Syz147064 
13155895Syz147064 	propvals = (char **)(void *)buf;
13165895Syz147064 	for (i = 0; i < valcnt; i++) {
13175895Syz147064 		propvals[i] = buf +
13185895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
13195895Syz147064 		    i * DLADM_PROP_VAL_MAX;
13205895Syz147064 	}
13215895Syz147064 
13228453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
13238453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
13245895Syz147064 		goto done;
13255895Syz147064 	}
13265895Syz147064 
132711021SEric.Cheng@Sun.COM 	status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
132811878SVenu.Iyer@Sun.COM 	    valcnt, dla->dla_flags | DLADM_OPT_ACTIVE);
132911878SVenu.Iyer@Sun.COM 
133011021SEric.Cheng@Sun.COM 	if (status != DLADM_STATUS_OK)
133111878SVenu.Iyer@Sun.COM 		dla->dla_status = status;
13325895Syz147064 
13335895Syz147064 done:
13345895Syz147064 	if (buf != NULL)
13355895Syz147064 		free(buf);
13365895Syz147064 
13375895Syz147064 	return (DLADM_WALK_CONTINUE);
13385895Syz147064 }
13395895Syz147064 
13405895Syz147064 /*ARGSUSED*/
13415895Syz147064 static int
13428453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
13435895Syz147064 {
13448275SEric Cheng 	datalink_class_t	class;
13458275SEric Cheng 	dladm_status_t		status;
13468275SEric Cheng 
13478453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
13488453SAnurag.Maskey@Sun.COM 	    NULL, 0);
13498275SEric Cheng 	if (status != DLADM_STATUS_OK)
13508275SEric Cheng 		return (DLADM_WALK_TERMINATE);
13518275SEric Cheng 
13528275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
13538453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
13548275SEric Cheng 
13555895Syz147064 	return (DLADM_WALK_CONTINUE);
13565895Syz147064 }
13575895Syz147064 
13585895Syz147064 dladm_status_t
13598453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
13608453SAnurag.Maskey@Sun.COM     boolean_t any_media)
13615895Syz147064 {
136211021SEric.Cheng@Sun.COM 	dladm_status_t		status = DLADM_STATUS_OK;
13636916Sartem 	datalink_media_t	dmedia;
13646916Sartem 	uint32_t		media;
136511878SVenu.Iyer@Sun.COM 	dladm_linkprop_args_t	*dla;
13666916Sartem 
13676916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
13686916Sartem 
136911878SVenu.Iyer@Sun.COM 	dla = malloc(sizeof (dladm_linkprop_args_t));
137011878SVenu.Iyer@Sun.COM 	if (dla == NULL)
137111878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
137211878SVenu.Iyer@Sun.COM 	dla->dla_flags = DLADM_OPT_BOOT;
137311878SVenu.Iyer@Sun.COM 	dla->dla_status = DLADM_STATUS_OK;
137411878SVenu.Iyer@Sun.COM 
13755895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
13768453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
13778453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
13788453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
13798453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
13808453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
13816916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
138211878SVenu.Iyer@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, (void *)dla,
13838453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
138411878SVenu.Iyer@Sun.COM 		status = dla->dla_status;
13853448Sdh155122 	}
138611878SVenu.Iyer@Sun.COM 	free(dla);
138711021SEric.Cheng@Sun.COM 	return (status);
13883147Sxc151355 }
13893147Sxc151355 
13905903Ssowmini /* ARGSUSED */
13915895Syz147064 static dladm_status_t
139211878SVenu.Iyer@Sun.COM get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13938275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
13948275SEric Cheng     uint_t flags, uint_t *perm_flags)
13953147Sxc151355 {
13968275SEric Cheng 	char			zone_name[ZONENAME_MAX];
13978275SEric Cheng 	zoneid_t		zid;
13988275SEric Cheng 	dladm_status_t		status;
13993147Sxc151355 
14006512Ssowmini 	if (flags != 0)
14016512Ssowmini 		return (DLADM_STATUS_NOTSUP);
14026512Ssowmini 
140311878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
140411878SVenu.Iyer@Sun.COM 	    perm_flags, &zid, sizeof (zid));
14055895Syz147064 	if (status != DLADM_STATUS_OK)
14063448Sdh155122 		return (status);
14073448Sdh155122 
14085895Syz147064 	*val_cnt = 1;
14095895Syz147064 	if (zid != GLOBAL_ZONEID) {
14108118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
14115895Syz147064 			return (dladm_errno2status(errno));
14128118SVasumathi.Sundaram@Sun.COM 		}
14133147Sxc151355 
14145895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
14153147Sxc151355 	} else {
14165895Syz147064 		*prop_val[0] = '\0';
14173147Sxc151355 	}
14183147Sxc151355 
14193448Sdh155122 	return (DLADM_STATUS_OK);
14203448Sdh155122 }
14213448Sdh155122 
14223448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
14233448Sdh155122 
14243448Sdh155122 static int
14253448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
14263448Sdh155122 {
14273448Sdh155122 	char			root[MAXPATHLEN];
14283448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
14293448Sdh155122 	void			*dlhandle;
14303448Sdh155122 	void			*sym;
14313448Sdh155122 	int			ret;
14323448Sdh155122 
14333448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
14343448Sdh155122 		return (-1);
14353448Sdh155122 
14363448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
14373448Sdh155122 		(void) dlclose(dlhandle);
14383448Sdh155122 		return (-1);
14393448Sdh155122 	}
14403448Sdh155122 
14413448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
14423448Sdh155122 
14433448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
14443448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
14453448Sdh155122 	(void) dlclose(dlhandle);
14463448Sdh155122 	return (ret);
14473448Sdh155122 }
14483448Sdh155122 
14493448Sdh155122 static dladm_status_t
14508453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
14518453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
14523448Sdh155122 {
14533448Sdh155122 	char		path[MAXPATHLEN];
14545895Syz147064 	char		name[MAXLINKNAMELEN];
14553448Sdh155122 	di_prof_t	prof = NULL;
14563448Sdh155122 	char		zone_name[ZONENAME_MAX];
14573448Sdh155122 	dladm_status_t	status;
14585895Syz147064 	int		ret;
14593448Sdh155122 
14603448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
14613448Sdh155122 		return (dladm_errno2status(errno));
14623448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
14633448Sdh155122 		return (dladm_errno2status(errno));
14643448Sdh155122 	if (di_prof_init(path, &prof) != 0)
14653448Sdh155122 		return (dladm_errno2status(errno));
14663448Sdh155122 
14678453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
14685895Syz147064 	if (status != DLADM_STATUS_OK)
14695895Syz147064 		goto cleanup;
14705895Syz147064 
14715895Syz147064 	if (add)
14725895Syz147064 		ret = di_prof_add_dev(prof, name);
14735895Syz147064 	else
14745895Syz147064 		ret = di_prof_add_exclude(prof, name);
14755895Syz147064 
14765895Syz147064 	if (ret != 0) {
14773448Sdh155122 		status = dladm_errno2status(errno);
14783448Sdh155122 		goto cleanup;
14793448Sdh155122 	}
14803448Sdh155122 
14813448Sdh155122 	if (di_prof_commit(prof) != 0)
14823448Sdh155122 		status = dladm_errno2status(errno);
14833448Sdh155122 cleanup:
14843448Sdh155122 	if (prof)
14853448Sdh155122 		di_prof_fini(prof);
14863448Sdh155122 
14873448Sdh155122 	return (status);
14883448Sdh155122 }
14893448Sdh155122 
14905903Ssowmini /* ARGSUSED */
14913448Sdh155122 static dladm_status_t
149211878SVenu.Iyer@Sun.COM set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14938453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
14943448Sdh155122 {
14958275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
14968275SEric Cheng 	zoneid_t		zid_old, zid_new;
14977342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
14983448Sdh155122 
14993448Sdh155122 	if (val_cnt != 1)
15003448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
15013448Sdh155122 
15027342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
15037342SAruna.Ramakrishna@Sun.COM 
150411878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
150511878SVenu.Iyer@Sun.COM 	    NULL, &zid_old, sizeof (zid_old));
15068275SEric Cheng 	if (status != DLADM_STATUS_OK)
15078275SEric Cheng 		return (status);
15088275SEric Cheng 
15097342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
15103448Sdh155122 	if (zid_new == zid_old)
151110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_OK);
151210616SSebastien.Roy@Sun.COM 
151311878SVenu.Iyer@Sun.COM 	if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt,
151410616SSebastien.Roy@Sun.COM 	    flags, media)) != DLADM_STATUS_OK)
15155895Syz147064 		return (status);
15165895Syz147064 
151710616SSebastien.Roy@Sun.COM 	/*
151810616SSebastien.Roy@Sun.COM 	 * It is okay to fail to update the /dev entry (some vanity-named
151910616SSebastien.Roy@Sun.COM 	 * links do not have a /dev entry).
152010616SSebastien.Roy@Sun.COM 	 */
15213448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
15228453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
15238453SAnurag.Maskey@Sun.COM 		    B_FALSE);
15245895Syz147064 	}
152510616SSebastien.Roy@Sun.COM 	if (zid_new != GLOBAL_ZONEID)
15268453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
15273448Sdh155122 
15283448Sdh155122 	return (DLADM_STATUS_OK);
15293448Sdh155122 }
15303448Sdh155122 
15313448Sdh155122 /* ARGSUSED */
15323448Sdh155122 static dladm_status_t
153311878SVenu.Iyer@Sun.COM check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
153411878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
153511878SVenu.Iyer@Sun.COM     datalink_media_t media)
15363448Sdh155122 {
15377342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
15387342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
15397342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
15407342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
15413448Sdh155122 
15423448Sdh155122 	if (val_cnt != 1)
15433448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
15443448Sdh155122 
15457342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
15467342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
15477342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
15483448Sdh155122 
15498275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
15507342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
15517342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
15527342SAruna.Ramakrishna@Sun.COM 		goto done;
15537342SAruna.Ramakrishna@Sun.COM 	}
15547342SAruna.Ramakrishna@Sun.COM 
15557342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
15563448Sdh155122 		ushort_t	flags;
15573448Sdh155122 
15587342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
15593448Sdh155122 		    sizeof (flags)) < 0) {
15607342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
15617342SAruna.Ramakrishna@Sun.COM 			goto done;
15623448Sdh155122 		}
15633448Sdh155122 
15643448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
15657342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
15667342SAruna.Ramakrishna@Sun.COM 			goto done;
15673448Sdh155122 		}
15683448Sdh155122 	}
15693448Sdh155122 
15707342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
15717342SAruna.Ramakrishna@Sun.COM 
15727342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
157310616SSebastien.Roy@Sun.COM 	dzp->diz_linkid = linkid;
15747342SAruna.Ramakrishna@Sun.COM 
15757342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
15765895Syz147064 	return (DLADM_STATUS_OK);
15777342SAruna.Ramakrishna@Sun.COM done:
15787342SAruna.Ramakrishna@Sun.COM 	free(dzp);
15797342SAruna.Ramakrishna@Sun.COM 	return (status);
15805895Syz147064 }
15815895Syz147064 
15825903Ssowmini /* ARGSUSED */
15835895Syz147064 static dladm_status_t
158411878SVenu.Iyer@Sun.COM get_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15858275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15868275SEric Cheng     uint_t flags, uint_t *perm_flags)
15878275SEric Cheng {
15888275SEric Cheng 	mac_resource_props_t	mrp;
15898275SEric Cheng 	dladm_status_t		status;
15908275SEric Cheng 
159111878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
159211878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
159311878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
15948275SEric Cheng 		return (status);
15958275SEric Cheng 
15968275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
159711878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
159811878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
15998275SEric Cheng 	}
160011878SVenu.Iyer@Sun.COM 
160111878SVenu.Iyer@Sun.COM 	(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
16028275SEric Cheng 	*val_cnt = 1;
16038275SEric Cheng 	return (DLADM_STATUS_OK);
16048275SEric Cheng }
16058275SEric Cheng 
16068275SEric Cheng /* ARGSUSED */
16078275SEric Cheng static dladm_status_t
160811878SVenu.Iyer@Sun.COM check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
160911878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
161011878SVenu.Iyer@Sun.COM     datalink_media_t media)
16118275SEric Cheng {
16128275SEric Cheng 	uint64_t	*maxbw;
16138275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
16148275SEric Cheng 
16158275SEric Cheng 	if (val_cnt != 1)
16168275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
16178275SEric Cheng 
16188275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
16198275SEric Cheng 	if (maxbw == NULL)
16208275SEric Cheng 		return (DLADM_STATUS_NOMEM);
16218275SEric Cheng 
16228275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
16238275SEric Cheng 	if (status != DLADM_STATUS_OK) {
16248275SEric Cheng 		free(maxbw);
16258275SEric Cheng 		return (status);
16268275SEric Cheng 	}
16278275SEric Cheng 
16288275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
16298275SEric Cheng 		free(maxbw);
16308275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
16318275SEric Cheng 	}
16328275SEric Cheng 
16338275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
16348275SEric Cheng 	return (DLADM_STATUS_OK);
16358275SEric Cheng }
16368275SEric Cheng 
16378275SEric Cheng /* ARGSUSED */
16388275SEric Cheng dladm_status_t
163911878SVenu.Iyer@Sun.COM extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
16408275SEric Cheng {
164110734SEric Cheng 	mac_resource_props_t *mrp = arg;
16428275SEric Cheng 
164311878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL) {
164411878SVenu.Iyer@Sun.COM 		mrp->mrp_maxbw = MRP_MAXBW_RESETVAL;
164511878SVenu.Iyer@Sun.COM 	} else {
164611878SVenu.Iyer@Sun.COM 		bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
164711878SVenu.Iyer@Sun.COM 	}
16488275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
16498275SEric Cheng 
16508275SEric Cheng 	return (DLADM_STATUS_OK);
16518275SEric Cheng }
16528275SEric Cheng 
16538275SEric Cheng /* ARGSUSED */
16548275SEric Cheng static dladm_status_t
165511878SVenu.Iyer@Sun.COM get_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16568275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
16578275SEric Cheng     uint_t flags, uint_t *perm_flags)
16588275SEric Cheng {
165911878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
16608275SEric Cheng 	mac_resource_props_t	mrp;
16618275SEric Cheng 	int			i;
16628275SEric Cheng 	uint32_t		ncpus;
166311878SVenu.Iyer@Sun.COM 
166411878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "cpus-effective") == 0) {
166511878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
166611878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
166711878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
166811878SVenu.Iyer@Sun.COM 	} else {
166911878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
167011878SVenu.Iyer@Sun.COM 		    "resource", flags, perm_flags, &mrp, sizeof (mrp));
167111878SVenu.Iyer@Sun.COM 	}
167211878SVenu.Iyer@Sun.COM 
167311878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
16748275SEric Cheng 		return (status);
16758275SEric Cheng 
16768275SEric Cheng 	ncpus = mrp.mrp_ncpus;
16778275SEric Cheng 	if (ncpus > *val_cnt)
16788275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
16798275SEric Cheng 
16808275SEric Cheng 	if (ncpus == 0) {
168111878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
16828275SEric Cheng 		return (DLADM_STATUS_OK);
16838275SEric Cheng 	}
16848275SEric Cheng 
16858275SEric Cheng 	*val_cnt = ncpus;
16868275SEric Cheng 	for (i = 0; i < ncpus; i++) {
16878275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
16888275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
16898275SEric Cheng 	}
16908275SEric Cheng 	return (DLADM_STATUS_OK);
16918275SEric Cheng }
16928275SEric Cheng 
16938275SEric Cheng /* ARGSUSED */
16948275SEric Cheng static dladm_status_t
169511878SVenu.Iyer@Sun.COM check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
169611878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
169711878SVenu.Iyer@Sun.COM     datalink_media_t media)
16988275SEric Cheng {
169911878SVenu.Iyer@Sun.COM 	uint32_t		cpuid;
170011878SVenu.Iyer@Sun.COM 	int			i, j, rc;
170111878SVenu.Iyer@Sun.COM 	char			*endp;
170211878SVenu.Iyer@Sun.COM 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
17038275SEric Cheng 	mac_resource_props_t	mrp;
170411878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
170511878SVenu.Iyer@Sun.COM 	uint_t			perm_flags;
170611878SVenu.Iyer@Sun.COM 
170711878SVenu.Iyer@Sun.COM 	/* Get the current pool property */
170811878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
170911878SVenu.Iyer@Sun.COM 	    &perm_flags, &mrp, sizeof (mrp));
171011878SVenu.Iyer@Sun.COM 
171111878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_OK) {
171211878SVenu.Iyer@Sun.COM 		/* Can't set cpus if a pool is set */
171311878SVenu.Iyer@Sun.COM 		if (strlen(mrp.mrp_pool) != 0)
171411878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_POOLCPU);
171511878SVenu.Iyer@Sun.COM 	}
17168275SEric Cheng 
17178275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
171811878SVenu.Iyer@Sun.COM 
171911878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
172011878SVenu.Iyer@Sun.COM 		errno = 0;
172111878SVenu.Iyer@Sun.COM 		cpuid = strtol(prop_val[i], &endp, 10);
172211878SVenu.Iyer@Sun.COM 		if (errno != 0 || *endp != '\0')
172311878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
172411878SVenu.Iyer@Sun.COM 
172511878SVenu.Iyer@Sun.COM 		if (cpuid >= nproc)
172611878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUMAX);
172711878SVenu.Iyer@Sun.COM 
172811878SVenu.Iyer@Sun.COM 		rc = p_online(cpuid, P_STATUS);
172911878SVenu.Iyer@Sun.COM 		if (rc < 1)
173011878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUERR);
173111878SVenu.Iyer@Sun.COM 
173211878SVenu.Iyer@Sun.COM 		if (rc != P_ONLINE)
173311878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUNOTONLINE);
173411878SVenu.Iyer@Sun.COM 
173511878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)cpuid;
173611878SVenu.Iyer@Sun.COM 	}
173711878SVenu.Iyer@Sun.COM 
173811878SVenu.Iyer@Sun.COM 	/* Check for duplicates */
173911878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
174011878SVenu.Iyer@Sun.COM 		for (j = 0; j < val_cnt; j++) {
174111878SVenu.Iyer@Sun.COM 			if (i != j && vdp[i].vd_val == vdp[j].vd_val)
174211878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADVAL);
17438275SEric Cheng 		}
17448275SEric Cheng 	}
174511878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
174611878SVenu.Iyer@Sun.COM }
174711878SVenu.Iyer@Sun.COM 
174811878SVenu.Iyer@Sun.COM /* ARGSUSED */
174911878SVenu.Iyer@Sun.COM dladm_status_t
175011878SVenu.Iyer@Sun.COM extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
175111878SVenu.Iyer@Sun.COM {
175211878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = arg;
175311878SVenu.Iyer@Sun.COM 	int			i;
175411878SVenu.Iyer@Sun.COM 
175511878SVenu.Iyer@Sun.COM 	if (vdp[0].vd_val == RESET_VAL) {
175611878SVenu.Iyer@Sun.COM 		bzero(&mrp->mrp_cpus, sizeof (mac_cpus_t));
175711878SVenu.Iyer@Sun.COM 		mrp->mrp_mask |= MRP_CPUS;
175811878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
175911878SVenu.Iyer@Sun.COM 	}
176011878SVenu.Iyer@Sun.COM 
176111878SVenu.Iyer@Sun.COM 	for (i = 0; i < cnt; i++)
176211878SVenu.Iyer@Sun.COM 		mrp->mrp_cpu[i] = (uint32_t)vdp[i].vd_val;
176311878SVenu.Iyer@Sun.COM 
176411878SVenu.Iyer@Sun.COM 	mrp->mrp_ncpus = cnt;
176511878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
176611878SVenu.Iyer@Sun.COM 	mrp->mrp_fanout_mode = MCM_CPUS;
176711878SVenu.Iyer@Sun.COM 	mrp->mrp_rx_intr_cpu = -1;
176811878SVenu.Iyer@Sun.COM 
176911878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
177011878SVenu.Iyer@Sun.COM }
177111878SVenu.Iyer@Sun.COM 
177211878SVenu.Iyer@Sun.COM /*
177311878SVenu.Iyer@Sun.COM  * Get the pool datalink property from the kernel.  This is used
177411878SVenu.Iyer@Sun.COM  * for both the user specified pool and effective pool properties.
177511878SVenu.Iyer@Sun.COM  */
177611878SVenu.Iyer@Sun.COM /* ARGSUSED */
177711878SVenu.Iyer@Sun.COM static dladm_status_t
177811878SVenu.Iyer@Sun.COM get_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
177911878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
178011878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
178111878SVenu.Iyer@Sun.COM {
178211878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
178311878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
178411878SVenu.Iyer@Sun.COM 
178511878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "pool-effective") == 0) {
178611878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
178711878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
178811878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
178911878SVenu.Iyer@Sun.COM 	} else {
179011878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
179111878SVenu.Iyer@Sun.COM 		    "resource", flags, perm_flags, &mrp, sizeof (mrp));
179211878SVenu.Iyer@Sun.COM 	}
179311878SVenu.Iyer@Sun.COM 
179411878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
179511878SVenu.Iyer@Sun.COM 		return (status);
179611878SVenu.Iyer@Sun.COM 
179711878SVenu.Iyer@Sun.COM 	if (strlen(mrp.mrp_pool) == 0) {
179811878SVenu.Iyer@Sun.COM 		(*prop_val)[0] = '\0';
179911878SVenu.Iyer@Sun.COM 	} else {
180011878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
180111878SVenu.Iyer@Sun.COM 		    "%s", mrp.mrp_pool);
180211878SVenu.Iyer@Sun.COM 	}
180311878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
180411878SVenu.Iyer@Sun.COM 
180511878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
18068275SEric Cheng }
18078275SEric Cheng 
18088275SEric Cheng /* ARGSUSED */
18098275SEric Cheng static dladm_status_t
181011878SVenu.Iyer@Sun.COM check_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
181111878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
181211878SVenu.Iyer@Sun.COM     datalink_media_t media)
18138275SEric Cheng {
181411878SVenu.Iyer@Sun.COM 	pool_conf_t		*poolconf;
181511878SVenu.Iyer@Sun.COM 	pool_t			*pool;
18168275SEric Cheng 	mac_resource_props_t	mrp;
18178275SEric Cheng 	dladm_status_t		status;
181811878SVenu.Iyer@Sun.COM 	uint_t			perm_flags;
181911878SVenu.Iyer@Sun.COM 	char			*poolname;
182011878SVenu.Iyer@Sun.COM 
182111878SVenu.Iyer@Sun.COM 	/* Get the current cpus property */
182211878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
182311878SVenu.Iyer@Sun.COM 	    &perm_flags, &mrp, sizeof (mrp));
182411878SVenu.Iyer@Sun.COM 
182511878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_OK) {
182611878SVenu.Iyer@Sun.COM 		/* Can't set pool if cpus are set */
182711878SVenu.Iyer@Sun.COM 		if (mrp.mrp_ncpus != 0)
182811878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_POOLCPU);
18298275SEric Cheng 	}
18308275SEric Cheng 
183111878SVenu.Iyer@Sun.COM 	poolname = malloc(sizeof (mrp.mrp_pool));
183211878SVenu.Iyer@Sun.COM 	if (poolname == NULL)
18338275SEric Cheng 		return (DLADM_STATUS_NOMEM);
18348275SEric Cheng 
183511878SVenu.Iyer@Sun.COM 	/* Check for pool's availability if not booting */
183611878SVenu.Iyer@Sun.COM 	if ((flags & DLADM_OPT_BOOT) == 0) {
183711878SVenu.Iyer@Sun.COM 
183811878SVenu.Iyer@Sun.COM 		/* Allocate and open pool configuration */
183911878SVenu.Iyer@Sun.COM 		if ((poolconf = pool_conf_alloc()) == NULL)
184011878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
184111878SVenu.Iyer@Sun.COM 
184211878SVenu.Iyer@Sun.COM 		if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY)
184311878SVenu.Iyer@Sun.COM 		    != PO_SUCCESS) {
184411878SVenu.Iyer@Sun.COM 			pool_conf_free(poolconf);
184511878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
18468275SEric Cheng 		}
184711878SVenu.Iyer@Sun.COM 
184811878SVenu.Iyer@Sun.COM 		/* Look for pool name */
184911878SVenu.Iyer@Sun.COM 		if ((pool = pool_get_pool(poolconf, *prop_val)) == NULL) {
185011878SVenu.Iyer@Sun.COM 			pool_conf_free(poolconf);
185111878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
18528275SEric Cheng 		}
185311878SVenu.Iyer@Sun.COM 
185411878SVenu.Iyer@Sun.COM 		pool_conf_free(poolconf);
185511878SVenu.Iyer@Sun.COM 		free(pool);
18568275SEric Cheng 	}
185711878SVenu.Iyer@Sun.COM 
185811878SVenu.Iyer@Sun.COM 	(void) strlcpy(poolname, *prop_val, sizeof (mrp.mrp_pool));
185911878SVenu.Iyer@Sun.COM 	vdp->vd_val = (uintptr_t)poolname;
18608275SEric Cheng 
18618275SEric Cheng 	return (DLADM_STATUS_OK);
18628275SEric Cheng }
18638275SEric Cheng 
18648275SEric Cheng /* ARGSUSED */
18658275SEric Cheng dladm_status_t
186611878SVenu.Iyer@Sun.COM extract_pool(val_desc_t *vdp, uint_t cnt, void *arg)
18678275SEric Cheng {
186811878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
186911878SVenu.Iyer@Sun.COM 
187011878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL) {
187111878SVenu.Iyer@Sun.COM 		bzero(&mrp->mrp_pool, sizeof (mrp->mrp_pool));
187211878SVenu.Iyer@Sun.COM 		mrp->mrp_mask |= MRP_POOL;
187311878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
18748275SEric Cheng 	}
187511878SVenu.Iyer@Sun.COM 
187611878SVenu.Iyer@Sun.COM 	(void) strlcpy(mrp->mrp_pool, (char *)vdp->vd_val,
187711878SVenu.Iyer@Sun.COM 	    sizeof (mrp->mrp_pool));
187811878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_POOL;
187911878SVenu.Iyer@Sun.COM 	/*
188011878SVenu.Iyer@Sun.COM 	 * Use MCM_CPUS since the fanout count is not user specified
188111878SVenu.Iyer@Sun.COM 	 * and will be determined by the cpu list generated from the
188211878SVenu.Iyer@Sun.COM 	 * pool.
188311878SVenu.Iyer@Sun.COM 	 */
18848275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
18858275SEric Cheng 
18868275SEric Cheng 	return (DLADM_STATUS_OK);
18878275SEric Cheng }
18888275SEric Cheng 
18898275SEric Cheng /* ARGSUSED */
18908275SEric Cheng static dladm_status_t
189111878SVenu.Iyer@Sun.COM get_priority(dladm_handle_t handle, prop_desc_t *pdp,
18928460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
18938460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
18948275SEric Cheng {
18958275SEric Cheng 	mac_resource_props_t	mrp;
18968275SEric Cheng 	mac_priority_level_t	pri;
18978275SEric Cheng 	dladm_status_t		status;
18988275SEric Cheng 
189911878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
190011878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
190111878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
19028275SEric Cheng 		return (status);
19038275SEric Cheng 
19048275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
19058275SEric Cheng 	    mrp.mrp_priority;
19068275SEric Cheng 
19078275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
19088275SEric Cheng 	*val_cnt = 1;
19098275SEric Cheng 	return (DLADM_STATUS_OK);
19108275SEric Cheng }
19118275SEric Cheng 
19128275SEric Cheng /* ARGSUSED */
191311878SVenu.Iyer@Sun.COM dladm_status_t
191411878SVenu.Iyer@Sun.COM extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
191511878SVenu.Iyer@Sun.COM {
191611878SVenu.Iyer@Sun.COM 	mac_resource_props_t *mrp = arg;
191711878SVenu.Iyer@Sun.COM 
191811878SVenu.Iyer@Sun.COM 	if (cnt != 1)
191911878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVAL);
192011878SVenu.Iyer@Sun.COM 
192111878SVenu.Iyer@Sun.COM 	mrp->mrp_priority = (mac_priority_level_t)vdp->vd_val;
192211878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_PRIORITY;
192311878SVenu.Iyer@Sun.COM 
192411878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
192511878SVenu.Iyer@Sun.COM }
192611878SVenu.Iyer@Sun.COM 
192711878SVenu.Iyer@Sun.COM /*
192811878SVenu.Iyer@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
192911878SVenu.Iyer@Sun.COM  * for retrieving the property range values.
193011878SVenu.Iyer@Sun.COM  */
193111878SVenu.Iyer@Sun.COM static int
193211878SVenu.Iyer@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
19338275SEric Cheng {
193411878SVenu.Iyer@Sun.COM 	uint_t count = r->mpr_count;
193511878SVenu.Iyer@Sun.COM 
193611878SVenu.Iyer@Sun.COM 	*sz = sizeof (mac_propval_range_t);
193711878SVenu.Iyer@Sun.COM 	--count;
193811878SVenu.Iyer@Sun.COM 
193911878SVenu.Iyer@Sun.COM 	switch (r->mpr_type) {
194011878SVenu.Iyer@Sun.COM 	case MAC_PROPVAL_UINT32:
194111878SVenu.Iyer@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
194211878SVenu.Iyer@Sun.COM 		return (0);
194311878SVenu.Iyer@Sun.COM 	default:
194411878SVenu.Iyer@Sun.COM 		break;
194511878SVenu.Iyer@Sun.COM 	}
194611878SVenu.Iyer@Sun.COM 	*sz = 0;
194711878SVenu.Iyer@Sun.COM 	return (EINVAL);
194811878SVenu.Iyer@Sun.COM }
194911878SVenu.Iyer@Sun.COM 
195011878SVenu.Iyer@Sun.COM 
195111878SVenu.Iyer@Sun.COM /* ARGSUSED */
195211878SVenu.Iyer@Sun.COM static dladm_status_t
195311878SVenu.Iyer@Sun.COM check_rings(dladm_handle_t handle, prop_desc_t *pdp,
195411878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
195511878SVenu.Iyer@Sun.COM     val_desc_t *v, datalink_media_t media)
195611878SVenu.Iyer@Sun.COM {
19578275SEric Cheng 	if (val_cnt != 1)
195811878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVAL);
195911878SVenu.Iyer@Sun.COM 	if (strncasecmp(prop_val[0], "hw", strlen("hw")) == 0) {
196011878SVenu.Iyer@Sun.COM 		v->vd_val = UNSPEC_VAL;
196111878SVenu.Iyer@Sun.COM 	} else if (strncasecmp(prop_val[0], "sw", strlen("sw")) == 0) {
196211878SVenu.Iyer@Sun.COM 		v->vd_val = 0;
196311878SVenu.Iyer@Sun.COM 	} else {
196411878SVenu.Iyer@Sun.COM 		v->vd_val = strtoul(prop_val[0], NULL, 0);
196511878SVenu.Iyer@Sun.COM 		if (v->vd_val == 0)
196611878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
196711878SVenu.Iyer@Sun.COM 	}
196811878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
196911878SVenu.Iyer@Sun.COM }
197011878SVenu.Iyer@Sun.COM 
197111878SVenu.Iyer@Sun.COM /* ARGSUSED */
197211878SVenu.Iyer@Sun.COM static dladm_status_t
197311878SVenu.Iyer@Sun.COM get_rings_range(dladm_handle_t handle, prop_desc_t *pdp,
197411878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
197511878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
197611878SVenu.Iyer@Sun.COM {
197711878SVenu.Iyer@Sun.COM 	dld_ioc_macprop_t *dip;
197811878SVenu.Iyer@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
197911878SVenu.Iyer@Sun.COM 	mac_propval_range_t *rangep;
198011878SVenu.Iyer@Sun.COM 	size_t	sz;
198111878SVenu.Iyer@Sun.COM 	mac_propval_uint32_range_t *ur;
198211878SVenu.Iyer@Sun.COM 
198311878SVenu.Iyer@Sun.COM 	sz = sizeof (mac_propval_range_t);
198411878SVenu.Iyer@Sun.COM 
198511878SVenu.Iyer@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
198611878SVenu.Iyer@Sun.COM 	    &status)) == NULL)
198711878SVenu.Iyer@Sun.COM 		return (status);
198811878SVenu.Iyer@Sun.COM 
198911878SVenu.Iyer@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
199011878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
19918275SEric Cheng 		return (status);
199211878SVenu.Iyer@Sun.COM 
199311878SVenu.Iyer@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
199411878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
199511878SVenu.Iyer@Sun.COM 	ur = &rangep->mpr_range_uint32[0];
199611878SVenu.Iyer@Sun.COM 	/* This is the case where the dev doesn't have any rings/groups */
199711878SVenu.Iyer@Sun.COM 	if (rangep->mpr_count == 0) {
199811878SVenu.Iyer@Sun.COM 		(*prop_val)[0] = '\0';
199911878SVenu.Iyer@Sun.COM 	/*
200011878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings, but static
200111878SVenu.Iyer@Sun.COM 	 * grouping.
200211878SVenu.Iyer@Sun.COM 	 */
200311878SVenu.Iyer@Sun.COM 	} else if (ur->mpur_min == ur->mpur_max &&
200411878SVenu.Iyer@Sun.COM 	    ur->mpur_max == 0) {
200511878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw");
200611878SVenu.Iyer@Sun.COM 	/*
200711878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings and dynamic
200811878SVenu.Iyer@Sun.COM 	 * grouping, but has only one value (say 2 rings and 2 groups).
200911878SVenu.Iyer@Sun.COM 	 */
201011878SVenu.Iyer@Sun.COM 	} else if (ur->mpur_min == ur->mpur_max) {
201111878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw,%d",
201211878SVenu.Iyer@Sun.COM 		    ur->mpur_min);
201311878SVenu.Iyer@Sun.COM 	/*
201411878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings and dynamic
201511878SVenu.Iyer@Sun.COM 	 * grouping and has a range of rings.
201611878SVenu.Iyer@Sun.COM 	 */
201711878SVenu.Iyer@Sun.COM 	} else {
201811878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX,
201911878SVenu.Iyer@Sun.COM 		    "sw,hw,<%ld-%ld>", ur->mpur_min, ur->mpur_max);
20208275SEric Cheng 	}
202111878SVenu.Iyer@Sun.COM 	free(dip);
202211878SVenu.Iyer@Sun.COM 	return (status);
202311878SVenu.Iyer@Sun.COM }
202411878SVenu.Iyer@Sun.COM 
202511878SVenu.Iyer@Sun.COM 
202611878SVenu.Iyer@Sun.COM /* ARGSUSED */
202711878SVenu.Iyer@Sun.COM static dladm_status_t
202811878SVenu.Iyer@Sun.COM get_rxrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
202911878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
203011878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
203111878SVenu.Iyer@Sun.COM {
203211878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
203311878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
203411878SVenu.Iyer@Sun.COM 	uint32_t		nrings = 0;
203511878SVenu.Iyer@Sun.COM 
203611878SVenu.Iyer@Sun.COM 	/*
203711878SVenu.Iyer@Sun.COM 	 * Get the number of (effective-)rings from the resource property.
203811878SVenu.Iyer@Sun.COM 	 */
203911878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "rxrings-effective") == 0) {
204011878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
204111878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
204211878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
204311878SVenu.Iyer@Sun.COM 	} else {
204411878SVenu.Iyer@Sun.COM 		/*
204511878SVenu.Iyer@Sun.COM 		 * Get the permissions from the "rxrings" property.
204611878SVenu.Iyer@Sun.COM 		 */
204711878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "rxrings",
204811878SVenu.Iyer@Sun.COM 		    flags, perm_flags, NULL, 0);
204911878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
205011878SVenu.Iyer@Sun.COM 			return (status);
205111878SVenu.Iyer@Sun.COM 
205211878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
205311878SVenu.Iyer@Sun.COM 		    "resource", flags, NULL, &mrp, sizeof (mrp));
20548275SEric Cheng 	}
20558275SEric Cheng 
205611878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
205711878SVenu.Iyer@Sun.COM 		return (status);
205811878SVenu.Iyer@Sun.COM 
205911878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_RX_RINGS) == 0) {
206011878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
206111878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
206211878SVenu.Iyer@Sun.COM 	}
206311878SVenu.Iyer@Sun.COM 	nrings = mrp.mrp_nrxrings;
206411878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
206511878SVenu.Iyer@Sun.COM 	if (mrp.mrp_mask & MRP_RXRINGS_UNSPEC)
206611878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
206711878SVenu.Iyer@Sun.COM 	else if (nrings == 0)
206811878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
206911878SVenu.Iyer@Sun.COM 	else
207011878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
20718275SEric Cheng 	return (DLADM_STATUS_OK);
20728275SEric Cheng }
20738275SEric Cheng 
20748275SEric Cheng /* ARGSUSED */
20758275SEric Cheng dladm_status_t
207611878SVenu.Iyer@Sun.COM extract_rxrings(val_desc_t *vdp, uint_t cnt, void *arg)
20778275SEric Cheng {
207811878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
207911878SVenu.Iyer@Sun.COM 
208011878SVenu.Iyer@Sun.COM 	mrp->mrp_nrxrings = 0;
208111878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL)
208211878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RINGS_RESET;
208311878SVenu.Iyer@Sun.COM 	else if (vdp->vd_val == UNSPEC_VAL)
208411878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RXRINGS_UNSPEC;
208511878SVenu.Iyer@Sun.COM 	else
208611878SVenu.Iyer@Sun.COM 		mrp->mrp_nrxrings = vdp->vd_val;
208711878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_RX_RINGS;
20888275SEric Cheng 
20898275SEric Cheng 	return (DLADM_STATUS_OK);
20908275SEric Cheng }
20918275SEric Cheng 
20928275SEric Cheng /* ARGSUSED */
20938275SEric Cheng static dladm_status_t
209411878SVenu.Iyer@Sun.COM get_txrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
209511878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
209611878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
209711878SVenu.Iyer@Sun.COM {
209811878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
209911878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
210011878SVenu.Iyer@Sun.COM 	uint32_t		nrings = 0;
210111878SVenu.Iyer@Sun.COM 
210211878SVenu.Iyer@Sun.COM 
210311878SVenu.Iyer@Sun.COM 	/*
210411878SVenu.Iyer@Sun.COM 	 * Get the number of (effective-)rings from the resource property.
210511878SVenu.Iyer@Sun.COM 	 */
210611878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "txrings-effective") == 0) {
210711878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
210811878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
210911878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
211011878SVenu.Iyer@Sun.COM 	} else {
211111878SVenu.Iyer@Sun.COM 		/*
211211878SVenu.Iyer@Sun.COM 		 * Get the permissions from the "txrings" property.
211311878SVenu.Iyer@Sun.COM 		 */
211411878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "txrings",
211511878SVenu.Iyer@Sun.COM 		    flags, perm_flags, NULL, 0);
211611878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
211711878SVenu.Iyer@Sun.COM 			return (status);
211811878SVenu.Iyer@Sun.COM 
211911878SVenu.Iyer@Sun.COM 		/*
212011878SVenu.Iyer@Sun.COM 		 * Get the number of rings from the "resource" property.
212111878SVenu.Iyer@Sun.COM 		 */
212211878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "resource",
212311878SVenu.Iyer@Sun.COM 		    flags, NULL, &mrp, sizeof (mrp));
212411878SVenu.Iyer@Sun.COM 	}
212511878SVenu.Iyer@Sun.COM 
212611878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
212711878SVenu.Iyer@Sun.COM 		return (status);
212811878SVenu.Iyer@Sun.COM 
212911878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_TX_RINGS) == 0) {
213011878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
213111878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
213211878SVenu.Iyer@Sun.COM 	}
213311878SVenu.Iyer@Sun.COM 	nrings = mrp.mrp_ntxrings;
213411878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
213511878SVenu.Iyer@Sun.COM 	if (mrp.mrp_mask & MRP_TXRINGS_UNSPEC)
213611878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
213711878SVenu.Iyer@Sun.COM 	else if (nrings == 0)
213811878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
213911878SVenu.Iyer@Sun.COM 	else
214011878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
214111878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
214211878SVenu.Iyer@Sun.COM }
214311878SVenu.Iyer@Sun.COM 
214411878SVenu.Iyer@Sun.COM /* ARGSUSED */
214511878SVenu.Iyer@Sun.COM dladm_status_t
214611878SVenu.Iyer@Sun.COM extract_txrings(val_desc_t *vdp, uint_t cnt, void *arg)
214711878SVenu.Iyer@Sun.COM {
214811878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
214911878SVenu.Iyer@Sun.COM 
215011878SVenu.Iyer@Sun.COM 	mrp->mrp_ntxrings = 0;
215111878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL)
215211878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RINGS_RESET;
215311878SVenu.Iyer@Sun.COM 	else if (vdp->vd_val == UNSPEC_VAL)
215411878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_TXRINGS_UNSPEC;
215511878SVenu.Iyer@Sun.COM 	else
215611878SVenu.Iyer@Sun.COM 		mrp->mrp_ntxrings = vdp->vd_val;
215711878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_TX_RINGS;
215811878SVenu.Iyer@Sun.COM 
215911878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
216011878SVenu.Iyer@Sun.COM }
216111878SVenu.Iyer@Sun.COM 
216211878SVenu.Iyer@Sun.COM /* ARGSUSED */
216311878SVenu.Iyer@Sun.COM static dladm_status_t
216411878SVenu.Iyer@Sun.COM get_cntavail(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
216511878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
216611878SVenu.Iyer@Sun.COM     uint_t *perm_flags)
216711878SVenu.Iyer@Sun.COM {
216811878SVenu.Iyer@Sun.COM 	if (flags & DLD_PROP_DEFAULT)
216911878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
217011878SVenu.Iyer@Sun.COM 
217111878SVenu.Iyer@Sun.COM 	return (get_uint32(handle, pdp, linkid, prop_val, val_cnt, media,
217211878SVenu.Iyer@Sun.COM 	    flags, perm_flags));
217311878SVenu.Iyer@Sun.COM }
217411878SVenu.Iyer@Sun.COM 
217511878SVenu.Iyer@Sun.COM /* ARGSUSED */
217611878SVenu.Iyer@Sun.COM static dladm_status_t
217711878SVenu.Iyer@Sun.COM set_resource(dladm_handle_t handle, prop_desc_t *pdp,
217810734SEric Cheng     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
217910734SEric Cheng     uint_t flags, datalink_media_t media)
218010734SEric Cheng {
218110734SEric Cheng 	mac_resource_props_t	mrp;
218210734SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
218310734SEric Cheng 	dld_ioc_macprop_t	*dip;
218411878SVenu.Iyer@Sun.COM 	int			i;
218510734SEric Cheng 
218610734SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
218711878SVenu.Iyer@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, "resource",
218810734SEric Cheng 	    flags, &status);
218910734SEric Cheng 
219010734SEric Cheng 	if (dip == NULL)
219110734SEric Cheng 		return (status);
219210734SEric Cheng 
219311878SVenu.Iyer@Sun.COM 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
219411878SVenu.Iyer@Sun.COM 		resource_prop_t	*rp = &rsrc_prop_table[i];
219511878SVenu.Iyer@Sun.COM 
219611878SVenu.Iyer@Sun.COM 		if (strcmp(pdp->pd_name, rp->rp_name) != 0)
219711878SVenu.Iyer@Sun.COM 			continue;
219811878SVenu.Iyer@Sun.COM 
219911878SVenu.Iyer@Sun.COM 		status = rp->rp_extract(vdp, val_cnt, &mrp);
220010734SEric Cheng 		if (status != DLADM_STATUS_OK)
220110734SEric Cheng 			goto done;
220210734SEric Cheng 
220311878SVenu.Iyer@Sun.COM 		break;
220410734SEric Cheng 	}
220510734SEric Cheng 
220610734SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
220710734SEric Cheng 	status = i_dladm_macprop(handle, dip, B_TRUE);
220810734SEric Cheng 
220910734SEric Cheng done:
221010734SEric Cheng 	free(dip);
221110734SEric Cheng 	return (status);
221210734SEric Cheng }
221310734SEric Cheng 
221410734SEric Cheng /* ARGSUSED */
221510734SEric Cheng static dladm_status_t
221611878SVenu.Iyer@Sun.COM get_protection(dladm_handle_t handle, prop_desc_t *pdp,
221710734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
221810734SEric Cheng     datalink_media_t media, uint_t flags, uint_t *perm_flags)
221910734SEric Cheng {
222011878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
222111878SVenu.Iyer@Sun.COM 	mac_protect_t		*p;
222211878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
222311878SVenu.Iyer@Sun.COM 	uint32_t		i, cnt = 0, setbits[32];
222411878SVenu.Iyer@Sun.COM 
222511878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
222611878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
222711878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
222811878SVenu.Iyer@Sun.COM 		return (status);
222911878SVenu.Iyer@Sun.COM 
223011878SVenu.Iyer@Sun.COM 	p = &mrp.mrp_protect;
223111878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_PROTECT) == 0) {
223211878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
223311878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
223411878SVenu.Iyer@Sun.COM 	}
223511878SVenu.Iyer@Sun.COM 	dladm_find_setbits32(p->mp_types, setbits, &cnt);
223611878SVenu.Iyer@Sun.COM 	if (cnt > *val_cnt)
223711878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
223811878SVenu.Iyer@Sun.COM 
223911878SVenu.Iyer@Sun.COM 	for (i = 0; i < cnt; i++)
224011878SVenu.Iyer@Sun.COM 		(void) dladm_protect2str(setbits[i], prop_val[i]);
224111878SVenu.Iyer@Sun.COM 
224211878SVenu.Iyer@Sun.COM 	*val_cnt = cnt;
224311878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
224411878SVenu.Iyer@Sun.COM }
224511878SVenu.Iyer@Sun.COM 
224611878SVenu.Iyer@Sun.COM /* ARGSUSED */
224711878SVenu.Iyer@Sun.COM static dladm_status_t
224811878SVenu.Iyer@Sun.COM get_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
224911878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
225011878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
225111878SVenu.Iyer@Sun.COM {
225210734SEric Cheng 	mac_resource_props_t	mrp;
225310734SEric Cheng 	mac_protect_t		*p;
225410734SEric Cheng 	dladm_status_t		status;
225510734SEric Cheng 	int			i;
225610734SEric Cheng 
225711878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
225811878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
225911878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
226010734SEric Cheng 		return (status);
226110734SEric Cheng 
226210734SEric Cheng 	p = &mrp.mrp_protect;
226311878SVenu.Iyer@Sun.COM 	if (p->mp_ipaddrcnt == 0) {
226411878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
226510734SEric Cheng 		return (DLADM_STATUS_OK);
226610734SEric Cheng 	}
226711878SVenu.Iyer@Sun.COM 	if (p->mp_ipaddrcnt > *val_cnt)
226811878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
226911878SVenu.Iyer@Sun.COM 
227011878SVenu.Iyer@Sun.COM 	for (i = 0; i < p->mp_ipaddrcnt; i++) {
227111878SVenu.Iyer@Sun.COM 		if (p->mp_ipaddrs[i].ip_version == IPV4_VERSION) {
227211878SVenu.Iyer@Sun.COM 			ipaddr_t	v4addr;
227311878SVenu.Iyer@Sun.COM 
227411878SVenu.Iyer@Sun.COM 			v4addr = V4_PART_OF_V6(p->mp_ipaddrs[i].ip_addr);
227511878SVenu.Iyer@Sun.COM 			(void) dladm_ipv4addr2str(&v4addr, prop_val[i]);
227611878SVenu.Iyer@Sun.COM 		} else {
227711878SVenu.Iyer@Sun.COM 			(void) dladm_ipv6addr2str(&p->mp_ipaddrs[i].ip_addr,
227810734SEric Cheng 			    prop_val[i]);
227910734SEric Cheng 		}
228010734SEric Cheng 	}
228111878SVenu.Iyer@Sun.COM 	*val_cnt = p->mp_ipaddrcnt;
228210734SEric Cheng 	return (DLADM_STATUS_OK);
228310734SEric Cheng }
228410734SEric Cheng 
228510734SEric Cheng dladm_status_t
228611878SVenu.Iyer@Sun.COM extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
228710734SEric Cheng {
228810734SEric Cheng 	mac_resource_props_t	*mrp = arg;
228910734SEric Cheng 	uint32_t		types = 0;
229010734SEric Cheng 	int			i;
229110734SEric Cheng 
229210734SEric Cheng 	for (i = 0; i < cnt; i++)
229310734SEric Cheng 		types |= (uint32_t)vdp[i].vd_val;
229410734SEric Cheng 
229510734SEric Cheng 	mrp->mrp_protect.mp_types = types;
229610734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
229710734SEric Cheng 	return (DLADM_STATUS_OK);
229810734SEric Cheng }
229910734SEric Cheng 
230010734SEric Cheng dladm_status_t
230111878SVenu.Iyer@Sun.COM extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
230210734SEric Cheng {
230310734SEric Cheng 	mac_resource_props_t	*mrp = arg;
230410734SEric Cheng 	mac_protect_t		*p = &mrp->mrp_protect;
230510734SEric Cheng 	int			i;
230610734SEric Cheng 
230710734SEric Cheng 	if (vdp->vd_val == 0) {
230810734SEric Cheng 		cnt = (uint_t)-1;
230910734SEric Cheng 	} else {
231011878SVenu.Iyer@Sun.COM 		for (i = 0; i < cnt; i++) {
231111878SVenu.Iyer@Sun.COM 			bcopy((void *)vdp[i].vd_val, &p->mp_ipaddrs[i],
231211878SVenu.Iyer@Sun.COM 			    sizeof (mac_ipaddr_t));
231311878SVenu.Iyer@Sun.COM 		}
231410734SEric Cheng 	}
231510734SEric Cheng 	p->mp_ipaddrcnt = cnt;
231610734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
231710734SEric Cheng 	return (DLADM_STATUS_OK);
231810734SEric Cheng }
231910734SEric Cheng 
232011878SVenu.Iyer@Sun.COM static dladm_status_t
232111878SVenu.Iyer@Sun.COM check_single_ip(char *buf, mac_ipaddr_t *addr)
232211878SVenu.Iyer@Sun.COM {
232311878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
232411878SVenu.Iyer@Sun.COM 	ipaddr_t	v4addr;
232511878SVenu.Iyer@Sun.COM 	in6_addr_t	v6addr;
232611878SVenu.Iyer@Sun.COM 	boolean_t	isv4 = B_TRUE;
232711878SVenu.Iyer@Sun.COM 
232811878SVenu.Iyer@Sun.COM 	status = dladm_str2ipv4addr(buf, &v4addr);
232911878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_INVALID_IP) {
233011878SVenu.Iyer@Sun.COM 		status = dladm_str2ipv6addr(buf, &v6addr);
233111878SVenu.Iyer@Sun.COM 		if (status == DLADM_STATUS_OK)
233211878SVenu.Iyer@Sun.COM 			isv4 = B_FALSE;
233311878SVenu.Iyer@Sun.COM 	}
233411878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
233511878SVenu.Iyer@Sun.COM 		return (status);
233611878SVenu.Iyer@Sun.COM 
233711878SVenu.Iyer@Sun.COM 	if (isv4) {
233811878SVenu.Iyer@Sun.COM 		if (v4addr == INADDR_ANY)
233911878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_INVALID_IP);
234011878SVenu.Iyer@Sun.COM 
234111878SVenu.Iyer@Sun.COM 		IN6_IPADDR_TO_V4MAPPED(v4addr, &addr->ip_addr);
234211878SVenu.Iyer@Sun.COM 		addr->ip_version = IPV4_VERSION;
234311878SVenu.Iyer@Sun.COM 	} else {
234411878SVenu.Iyer@Sun.COM 		if (IN6_IS_ADDR_UNSPECIFIED(&v6addr))
234511878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_INVALID_IP);
234611878SVenu.Iyer@Sun.COM 
234711878SVenu.Iyer@Sun.COM 		addr->ip_addr = v6addr;
234811878SVenu.Iyer@Sun.COM 		addr->ip_version = IPV6_VERSION;
234911878SVenu.Iyer@Sun.COM 	}
235011878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
235111878SVenu.Iyer@Sun.COM }
235211878SVenu.Iyer@Sun.COM 
235310734SEric Cheng /* ARGSUSED */
235410734SEric Cheng static dladm_status_t
235511878SVenu.Iyer@Sun.COM check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
235611878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
235710734SEric Cheng     val_desc_t *vdp, datalink_media_t media)
235810734SEric Cheng {
235910734SEric Cheng 	dladm_status_t	status;
236011878SVenu.Iyer@Sun.COM 	mac_ipaddr_t	*addr;
236110734SEric Cheng 	int		i;
236210734SEric Cheng 
236310734SEric Cheng 	if (val_cnt > MPT_MAXIPADDR)
236410734SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
236510734SEric Cheng 
236610734SEric Cheng 	for (i = 0; i < val_cnt; i++) {
236711878SVenu.Iyer@Sun.COM 		if ((addr = calloc(1, sizeof (mac_ipaddr_t))) == NULL) {
236811878SVenu.Iyer@Sun.COM 			status = DLADM_STATUS_NOMEM;
236911878SVenu.Iyer@Sun.COM 			goto fail;
237011878SVenu.Iyer@Sun.COM 		}
237111878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)addr;
237211878SVenu.Iyer@Sun.COM 
237311878SVenu.Iyer@Sun.COM 		status = check_single_ip(prop_val[i], addr);
237410734SEric Cheng 		if (status != DLADM_STATUS_OK)
237511878SVenu.Iyer@Sun.COM 			goto fail;
237611878SVenu.Iyer@Sun.COM 	}
237711878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
237811878SVenu.Iyer@Sun.COM 
237911878SVenu.Iyer@Sun.COM fail:
238011878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
238111878SVenu.Iyer@Sun.COM 		free((void *)vdp[i].vd_val);
238211878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = NULL;
238311878SVenu.Iyer@Sun.COM 	}
238411878SVenu.Iyer@Sun.COM 	return (status);
238511878SVenu.Iyer@Sun.COM }
238611878SVenu.Iyer@Sun.COM 
238711878SVenu.Iyer@Sun.COM static void
238811878SVenu.Iyer@Sun.COM dladm_cid2str(mac_dhcpcid_t *cid, char *buf)
238911878SVenu.Iyer@Sun.COM {
239011878SVenu.Iyer@Sun.COM 	char	tmp_buf[DLADM_STRSIZE];
239111878SVenu.Iyer@Sun.COM 	uint_t	hexlen;
239211878SVenu.Iyer@Sun.COM 
239311878SVenu.Iyer@Sun.COM 	switch (cid->dc_form) {
239411878SVenu.Iyer@Sun.COM 	case CIDFORM_TYPED: {
239511878SVenu.Iyer@Sun.COM 		uint16_t	duidtype, hwtype;
239611878SVenu.Iyer@Sun.COM 		uint32_t	timestamp, ennum;
239711878SVenu.Iyer@Sun.COM 		char		*lladdr;
239811878SVenu.Iyer@Sun.COM 
239911878SVenu.Iyer@Sun.COM 		if (cid->dc_len < sizeof (duidtype))
240011878SVenu.Iyer@Sun.COM 			goto fail;
240111878SVenu.Iyer@Sun.COM 
240211878SVenu.Iyer@Sun.COM 		bcopy(cid->dc_id, &duidtype, sizeof (duidtype));
240311878SVenu.Iyer@Sun.COM 		duidtype = ntohs(duidtype);
240411878SVenu.Iyer@Sun.COM 		switch (duidtype) {
240511878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LLT: {
240611878SVenu.Iyer@Sun.COM 			duid_llt_t	llt;
240711878SVenu.Iyer@Sun.COM 
240811878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (llt))
240911878SVenu.Iyer@Sun.COM 				goto fail;
241011878SVenu.Iyer@Sun.COM 
241111878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &llt, sizeof (llt));
241211878SVenu.Iyer@Sun.COM 			hwtype = ntohs(llt.dllt_hwtype);
241311878SVenu.Iyer@Sun.COM 			timestamp = ntohl(llt.dllt_time);
241411878SVenu.Iyer@Sun.COM 			lladdr = _link_ntoa(cid->dc_id + sizeof (llt),
241511878SVenu.Iyer@Sun.COM 			    NULL, cid->dc_len - sizeof (llt), IFT_OTHER);
241611878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
241711878SVenu.Iyer@Sun.COM 				goto fail;
241811878SVenu.Iyer@Sun.COM 
241911878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%d.%s",
242011878SVenu.Iyer@Sun.COM 			    duidtype, hwtype, timestamp, lladdr);
242111878SVenu.Iyer@Sun.COM 			free(lladdr);
242211878SVenu.Iyer@Sun.COM 			break;
242311878SVenu.Iyer@Sun.COM 		}
242411878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_EN: {
242511878SVenu.Iyer@Sun.COM 			duid_en_t	en;
242611878SVenu.Iyer@Sun.COM 
242711878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (en))
242811878SVenu.Iyer@Sun.COM 				goto fail;
242911878SVenu.Iyer@Sun.COM 
243011878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &en, sizeof (en));
243111878SVenu.Iyer@Sun.COM 			ennum = DHCPV6_GET_ENTNUM(&en);
243211878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
243311878SVenu.Iyer@Sun.COM 			if (octet_to_hexascii(cid->dc_id + sizeof (en),
243411878SVenu.Iyer@Sun.COM 			    cid->dc_len - sizeof (en), tmp_buf, &hexlen) != 0)
243511878SVenu.Iyer@Sun.COM 				goto fail;
243611878SVenu.Iyer@Sun.COM 
243711878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
243811878SVenu.Iyer@Sun.COM 			    duidtype, ennum, tmp_buf);
243911878SVenu.Iyer@Sun.COM 			break;
244011878SVenu.Iyer@Sun.COM 		}
244111878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LL: {
244211878SVenu.Iyer@Sun.COM 			duid_ll_t	ll;
244311878SVenu.Iyer@Sun.COM 
244411878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (ll))
244511878SVenu.Iyer@Sun.COM 				goto fail;
244611878SVenu.Iyer@Sun.COM 
244711878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &ll, sizeof (ll));
244811878SVenu.Iyer@Sun.COM 			hwtype = ntohs(ll.dll_hwtype);
244911878SVenu.Iyer@Sun.COM 			lladdr = _link_ntoa(cid->dc_id + sizeof (ll),
245011878SVenu.Iyer@Sun.COM 			    NULL, cid->dc_len - sizeof (ll), IFT_OTHER);
245111878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
245211878SVenu.Iyer@Sun.COM 				goto fail;
245311878SVenu.Iyer@Sun.COM 
245411878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
245511878SVenu.Iyer@Sun.COM 			    duidtype, hwtype, lladdr);
245611878SVenu.Iyer@Sun.COM 			free(lladdr);
245711878SVenu.Iyer@Sun.COM 			break;
245811878SVenu.Iyer@Sun.COM 		}
245911878SVenu.Iyer@Sun.COM 		default: {
246011878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
246111878SVenu.Iyer@Sun.COM 			if (octet_to_hexascii(cid->dc_id + sizeof (duidtype),
246211878SVenu.Iyer@Sun.COM 			    cid->dc_len - sizeof (duidtype),
246311878SVenu.Iyer@Sun.COM 			    tmp_buf, &hexlen) != 0)
246411878SVenu.Iyer@Sun.COM 				goto fail;
246511878SVenu.Iyer@Sun.COM 
246611878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%s",
246711878SVenu.Iyer@Sun.COM 			    duidtype, tmp_buf);
246811878SVenu.Iyer@Sun.COM 		}
246911878SVenu.Iyer@Sun.COM 		}
247011878SVenu.Iyer@Sun.COM 		break;
247111878SVenu.Iyer@Sun.COM 	}
247211878SVenu.Iyer@Sun.COM 	case CIDFORM_HEX: {
247311878SVenu.Iyer@Sun.COM 		hexlen = sizeof (tmp_buf);
247411878SVenu.Iyer@Sun.COM 		if (octet_to_hexascii(cid->dc_id, cid->dc_len,
247511878SVenu.Iyer@Sun.COM 		    tmp_buf, &hexlen) != 0)
247611878SVenu.Iyer@Sun.COM 			goto fail;
247711878SVenu.Iyer@Sun.COM 
247811878SVenu.Iyer@Sun.COM 		(void) snprintf(buf, DLADM_STRSIZE, "0x%s", tmp_buf);
247911878SVenu.Iyer@Sun.COM 		break;
248011878SVenu.Iyer@Sun.COM 	}
248111878SVenu.Iyer@Sun.COM 	case CIDFORM_STR: {
248211878SVenu.Iyer@Sun.COM 		int	i;
248311878SVenu.Iyer@Sun.COM 
248411878SVenu.Iyer@Sun.COM 		for (i = 0; i < cid->dc_len; i++) {
248511878SVenu.Iyer@Sun.COM 			if (!isprint(cid->dc_id[i]))
248611878SVenu.Iyer@Sun.COM 				goto fail;
248711878SVenu.Iyer@Sun.COM 		}
248811878SVenu.Iyer@Sun.COM 		(void) snprintf(buf, DLADM_STRSIZE, "%s", cid->dc_id);
248911878SVenu.Iyer@Sun.COM 		break;
249011878SVenu.Iyer@Sun.COM 	}
249111878SVenu.Iyer@Sun.COM 	default:
249211878SVenu.Iyer@Sun.COM 		goto fail;
249310734SEric Cheng 	}
249411878SVenu.Iyer@Sun.COM 	return;
249511878SVenu.Iyer@Sun.COM 
249611878SVenu.Iyer@Sun.COM fail:
249711878SVenu.Iyer@Sun.COM 	(void) snprintf(buf, DLADM_STRSIZE, "<unknown>");
249811878SVenu.Iyer@Sun.COM }
249911878SVenu.Iyer@Sun.COM 
250011878SVenu.Iyer@Sun.COM static dladm_status_t
250111878SVenu.Iyer@Sun.COM dladm_str2cid(char *buf, mac_dhcpcid_t *cid)
250211878SVenu.Iyer@Sun.COM {
250311878SVenu.Iyer@Sun.COM 	char	*ptr = buf;
250411878SVenu.Iyer@Sun.COM 	char	tmp_buf[DLADM_STRSIZE];
250511878SVenu.Iyer@Sun.COM 	uint_t	hexlen, cidlen;
250611878SVenu.Iyer@Sun.COM 
250711878SVenu.Iyer@Sun.COM 	bzero(cid, sizeof (*cid));
250811878SVenu.Iyer@Sun.COM 	if (isdigit(*ptr) &&
250911878SVenu.Iyer@Sun.COM 	    ptr[strspn(ptr, "0123456789")] == '.') {
251011878SVenu.Iyer@Sun.COM 		char	*cp;
251111878SVenu.Iyer@Sun.COM 		ulong_t	duidtype;
251211878SVenu.Iyer@Sun.COM 		ulong_t	subtype;
251311878SVenu.Iyer@Sun.COM 		ulong_t	timestamp;
251411878SVenu.Iyer@Sun.COM 		uchar_t	*lladdr;
251511878SVenu.Iyer@Sun.COM 		int	addrlen;
251611878SVenu.Iyer@Sun.COM 
251711878SVenu.Iyer@Sun.COM 		errno = 0;
251811878SVenu.Iyer@Sun.COM 		duidtype = strtoul(ptr, &cp, 0);
251911878SVenu.Iyer@Sun.COM 		if (ptr == cp || errno != 0 || *cp != '.' ||
252011878SVenu.Iyer@Sun.COM 		    duidtype > USHRT_MAX)
252111878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADARG);
252211878SVenu.Iyer@Sun.COM 		ptr = cp + 1;
252311878SVenu.Iyer@Sun.COM 
252411878SVenu.Iyer@Sun.COM 		if (duidtype != 0 && duidtype <= DHCPV6_DUID_LL) {
252511878SVenu.Iyer@Sun.COM 			errno = 0;
252611878SVenu.Iyer@Sun.COM 			subtype = strtoul(ptr, &cp, 0);
252711878SVenu.Iyer@Sun.COM 			if (ptr == cp || errno != 0 || *cp != '.')
252811878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
252911878SVenu.Iyer@Sun.COM 			ptr = cp + 1;
253011878SVenu.Iyer@Sun.COM 		}
253111878SVenu.Iyer@Sun.COM 		switch (duidtype) {
253211878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LLT: {
253311878SVenu.Iyer@Sun.COM 			duid_llt_t	llt;
253411878SVenu.Iyer@Sun.COM 
253511878SVenu.Iyer@Sun.COM 			errno = 0;
253611878SVenu.Iyer@Sun.COM 			timestamp = strtoul(ptr, &cp, 0);
253711878SVenu.Iyer@Sun.COM 			if (ptr == cp || errno != 0 || *cp != '.')
253811878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
253911878SVenu.Iyer@Sun.COM 
254011878SVenu.Iyer@Sun.COM 			ptr = cp + 1;
254111878SVenu.Iyer@Sun.COM 			lladdr = _link_aton(ptr, &addrlen);
254211878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
254311878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
254411878SVenu.Iyer@Sun.COM 
254511878SVenu.Iyer@Sun.COM 			cidlen = sizeof (llt) + addrlen;
254611878SVenu.Iyer@Sun.COM 			if (cidlen > sizeof (cid->dc_id)) {
254711878SVenu.Iyer@Sun.COM 				free(lladdr);
254811878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_TOOSMALL);
254911878SVenu.Iyer@Sun.COM 			}
255011878SVenu.Iyer@Sun.COM 			llt.dllt_dutype = htons(duidtype);
255111878SVenu.Iyer@Sun.COM 			llt.dllt_hwtype = htons(subtype);
255211878SVenu.Iyer@Sun.COM 			llt.dllt_time = htonl(timestamp);
255311878SVenu.Iyer@Sun.COM 			bcopy(&llt, cid->dc_id, sizeof (llt));
255411878SVenu.Iyer@Sun.COM 			bcopy(lladdr, cid->dc_id + sizeof (llt), addrlen);
255511878SVenu.Iyer@Sun.COM 			free(lladdr);
255611878SVenu.Iyer@Sun.COM 			break;
255711878SVenu.Iyer@Sun.COM 		}
255811878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LL: {
255911878SVenu.Iyer@Sun.COM 			duid_ll_t	ll;
256011878SVenu.Iyer@Sun.COM 
256111878SVenu.Iyer@Sun.COM 			lladdr = _link_aton(ptr, &addrlen);
256211878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
256311878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
256411878SVenu.Iyer@Sun.COM 
256511878SVenu.Iyer@Sun.COM 			cidlen = sizeof (ll) + addrlen;
256611878SVenu.Iyer@Sun.COM 			if (cidlen > sizeof (cid->dc_id)) {
256711878SVenu.Iyer@Sun.COM 				free(lladdr);
256811878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_TOOSMALL);
256911878SVenu.Iyer@Sun.COM 			}
257011878SVenu.Iyer@Sun.COM 			ll.dll_dutype = htons(duidtype);
257111878SVenu.Iyer@Sun.COM 			ll.dll_hwtype = htons(subtype);
257211878SVenu.Iyer@Sun.COM 			bcopy(&ll, cid->dc_id, sizeof (ll));
257311878SVenu.Iyer@Sun.COM 			bcopy(lladdr, cid->dc_id + sizeof (ll), addrlen);
257411878SVenu.Iyer@Sun.COM 			free(lladdr);
257511878SVenu.Iyer@Sun.COM 			break;
257611878SVenu.Iyer@Sun.COM 		}
257711878SVenu.Iyer@Sun.COM 		default: {
257811878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
257911878SVenu.Iyer@Sun.COM 			if (hexascii_to_octet(ptr, strlen(ptr),
258011878SVenu.Iyer@Sun.COM 			    tmp_buf, &hexlen) != 0)
258111878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
258211878SVenu.Iyer@Sun.COM 
258311878SVenu.Iyer@Sun.COM 			if (duidtype == DHCPV6_DUID_EN) {
258411878SVenu.Iyer@Sun.COM 				duid_en_t	en;
258511878SVenu.Iyer@Sun.COM 
258611878SVenu.Iyer@Sun.COM 				en.den_dutype = htons(duidtype);
258711878SVenu.Iyer@Sun.COM 				DHCPV6_SET_ENTNUM(&en, subtype);
258811878SVenu.Iyer@Sun.COM 
258911878SVenu.Iyer@Sun.COM 				cidlen = sizeof (en) + hexlen;
259011878SVenu.Iyer@Sun.COM 				if (cidlen > sizeof (cid->dc_id))
259111878SVenu.Iyer@Sun.COM 					return (DLADM_STATUS_TOOSMALL);
259211878SVenu.Iyer@Sun.COM 
259311878SVenu.Iyer@Sun.COM 				bcopy(&en, cid->dc_id, sizeof (en));
259411878SVenu.Iyer@Sun.COM 				bcopy(tmp_buf, cid->dc_id + sizeof (en),
259511878SVenu.Iyer@Sun.COM 				    hexlen);
259611878SVenu.Iyer@Sun.COM 			} else {
259711878SVenu.Iyer@Sun.COM 				uint16_t	dutype = htons(duidtype);
259811878SVenu.Iyer@Sun.COM 
259911878SVenu.Iyer@Sun.COM 				cidlen = sizeof (dutype) + hexlen;
260011878SVenu.Iyer@Sun.COM 				if (cidlen > sizeof (cid->dc_id))
260111878SVenu.Iyer@Sun.COM 					return (DLADM_STATUS_TOOSMALL);
260211878SVenu.Iyer@Sun.COM 
260311878SVenu.Iyer@Sun.COM 				bcopy(&dutype, cid->dc_id, sizeof (dutype));
260411878SVenu.Iyer@Sun.COM 				bcopy(tmp_buf, cid->dc_id + sizeof (dutype),
260511878SVenu.Iyer@Sun.COM 				    hexlen);
260611878SVenu.Iyer@Sun.COM 			}
260711878SVenu.Iyer@Sun.COM 			break;
260811878SVenu.Iyer@Sun.COM 		}
260911878SVenu.Iyer@Sun.COM 		}
261011878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_TYPED;
261111878SVenu.Iyer@Sun.COM 	} else if (strncasecmp("0x", ptr, 2) == 0 && ptr[2] != '\0') {
261211878SVenu.Iyer@Sun.COM 		ptr += 2;
261311878SVenu.Iyer@Sun.COM 		hexlen = sizeof (tmp_buf);
261411878SVenu.Iyer@Sun.COM 		if (hexascii_to_octet(ptr, strlen(ptr), tmp_buf,
261511878SVenu.Iyer@Sun.COM 		    &hexlen) != 0) {
261611878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADARG);
261711878SVenu.Iyer@Sun.COM 		}
261811878SVenu.Iyer@Sun.COM 		cidlen = hexlen;
261911878SVenu.Iyer@Sun.COM 		if (cidlen > sizeof (cid->dc_id))
262011878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_TOOSMALL);
262111878SVenu.Iyer@Sun.COM 
262211878SVenu.Iyer@Sun.COM 		bcopy(tmp_buf, cid->dc_id, cidlen);
262311878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_HEX;
262411878SVenu.Iyer@Sun.COM 	} else {
262511878SVenu.Iyer@Sun.COM 		cidlen = strlen(ptr);
262611878SVenu.Iyer@Sun.COM 		if (cidlen > sizeof (cid->dc_id))
262711878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_TOOSMALL);
262811878SVenu.Iyer@Sun.COM 
262911878SVenu.Iyer@Sun.COM 		bcopy(ptr, cid->dc_id, cidlen);
263011878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_STR;
263111878SVenu.Iyer@Sun.COM 	}
263211878SVenu.Iyer@Sun.COM 	cid->dc_len = cidlen;
263310734SEric Cheng 	return (DLADM_STATUS_OK);
263410734SEric Cheng }
263510734SEric Cheng 
263610734SEric Cheng /* ARGSUSED */
263710734SEric Cheng static dladm_status_t
263811878SVenu.Iyer@Sun.COM get_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
263911878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
264011878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
264111878SVenu.Iyer@Sun.COM {
264211878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
264311878SVenu.Iyer@Sun.COM 	mac_protect_t		*p;
264411878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
264511878SVenu.Iyer@Sun.COM 	int			i;
264611878SVenu.Iyer@Sun.COM 
264711878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
264811878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
264911878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
265011878SVenu.Iyer@Sun.COM 		return (status);
265111878SVenu.Iyer@Sun.COM 
265211878SVenu.Iyer@Sun.COM 	p = &mrp.mrp_protect;
265311878SVenu.Iyer@Sun.COM 	if (p->mp_cidcnt == 0) {
265411878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
265511878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
265611878SVenu.Iyer@Sun.COM 	}
265711878SVenu.Iyer@Sun.COM 	if (p->mp_cidcnt > *val_cnt)
265811878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
265911878SVenu.Iyer@Sun.COM 
266011878SVenu.Iyer@Sun.COM 	for (i = 0; i < p->mp_cidcnt; i++) {
266111878SVenu.Iyer@Sun.COM 		mac_dhcpcid_t	*cid = &p->mp_cids[i];
266211878SVenu.Iyer@Sun.COM 
266311878SVenu.Iyer@Sun.COM 		dladm_cid2str(cid, prop_val[i]);
266411878SVenu.Iyer@Sun.COM 	}
266511878SVenu.Iyer@Sun.COM 	*val_cnt = p->mp_cidcnt;
266611878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
266711878SVenu.Iyer@Sun.COM }
266811878SVenu.Iyer@Sun.COM 
266911878SVenu.Iyer@Sun.COM dladm_status_t
267011878SVenu.Iyer@Sun.COM extract_allowedcids(val_desc_t *vdp, uint_t cnt, void *arg)
267111878SVenu.Iyer@Sun.COM {
267211878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = arg;
267311878SVenu.Iyer@Sun.COM 	mac_protect_t		*p = &mrp->mrp_protect;
267411878SVenu.Iyer@Sun.COM 	int			i;
267511878SVenu.Iyer@Sun.COM 
267611878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == 0) {
267711878SVenu.Iyer@Sun.COM 		cnt = (uint_t)-1;
267811878SVenu.Iyer@Sun.COM 	} else {
267911878SVenu.Iyer@Sun.COM 		for (i = 0; i < cnt; i++) {
268011878SVenu.Iyer@Sun.COM 			bcopy((void *)vdp[i].vd_val, &p->mp_cids[i],
268111878SVenu.Iyer@Sun.COM 			    sizeof (mac_dhcpcid_t));
268211878SVenu.Iyer@Sun.COM 		}
268311878SVenu.Iyer@Sun.COM 	}
268411878SVenu.Iyer@Sun.COM 	p->mp_cidcnt = cnt;
268511878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_PROTECT;
268611878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
268711878SVenu.Iyer@Sun.COM }
268811878SVenu.Iyer@Sun.COM 
268911878SVenu.Iyer@Sun.COM /* ARGSUSED */
269011878SVenu.Iyer@Sun.COM static dladm_status_t
269111878SVenu.Iyer@Sun.COM check_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
269211878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt,
269311878SVenu.Iyer@Sun.COM     uint_t flags, val_desc_t *vdp, datalink_media_t media)
269411878SVenu.Iyer@Sun.COM {
269511878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
269611878SVenu.Iyer@Sun.COM 	mac_dhcpcid_t	*cid;
269711878SVenu.Iyer@Sun.COM 	int		i;
269811878SVenu.Iyer@Sun.COM 
269911878SVenu.Iyer@Sun.COM 	if (val_cnt > MPT_MAXCID)
270011878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
270111878SVenu.Iyer@Sun.COM 
270211878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
270311878SVenu.Iyer@Sun.COM 		if ((cid = calloc(1, sizeof (mac_dhcpcid_t))) == NULL) {
270411878SVenu.Iyer@Sun.COM 			status = DLADM_STATUS_NOMEM;
270511878SVenu.Iyer@Sun.COM 			goto fail;
270611878SVenu.Iyer@Sun.COM 		}
270711878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)cid;
270811878SVenu.Iyer@Sun.COM 
270911878SVenu.Iyer@Sun.COM 		status = dladm_str2cid(prop_val[i], cid);
271011878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
271111878SVenu.Iyer@Sun.COM 			goto fail;
271211878SVenu.Iyer@Sun.COM 	}
271311878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
271411878SVenu.Iyer@Sun.COM 
271511878SVenu.Iyer@Sun.COM fail:
271611878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
271711878SVenu.Iyer@Sun.COM 		free((void *)vdp[i].vd_val);
271811878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = NULL;
271911878SVenu.Iyer@Sun.COM 	}
272011878SVenu.Iyer@Sun.COM 	return (status);
272111878SVenu.Iyer@Sun.COM }
272211878SVenu.Iyer@Sun.COM 
272311878SVenu.Iyer@Sun.COM /* ARGSUSED */
272411878SVenu.Iyer@Sun.COM static dladm_status_t
272511878SVenu.Iyer@Sun.COM get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
27268275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
27278275SEric Cheng     uint_t flags, uint_t *perm_flags)
27285895Syz147064 {
27297342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
27307342SAruna.Ramakrishna@Sun.COM 	int		i, len;
27317342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
273211878SVenu.Iyer@Sun.COM 
273311878SVenu.Iyer@Sun.COM 	if (flags & DLD_PROP_DEFAULT)
27347776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
27356512Ssowmini 
273611878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
273711878SVenu.Iyer@Sun.COM 	    perm_flags, &dlap, sizeof (dlap));
273811878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
273911878SVenu.Iyer@Sun.COM 		return (status);
274011878SVenu.Iyer@Sun.COM 
274111878SVenu.Iyer@Sun.COM 	if (dlap.dap_npush == 0) {
274211878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
27438275SEric Cheng 		return (DLADM_STATUS_OK);
27445895Syz147064 	}
27457342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
27465895Syz147064 		if (i != 0) {
27475895Syz147064 			(void) snprintf(*prop_val + len,
27485895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
27495895Syz147064 			len += 1;
27505895Syz147064 		}
27515895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
27527342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
27537342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
27547342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
27555895Syz147064 			(void) snprintf(*prop_val + len,
27565895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
27575895Syz147064 			    AP_ANCHOR);
27585895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
27595895Syz147064 		}
27605895Syz147064 	}
276111878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
27625895Syz147064 	return (DLADM_STATUS_OK);
27635895Syz147064 }
27645895Syz147064 
27655895Syz147064 /*
27665895Syz147064  * Add the specified module to the dlautopush structure; returns a
27675895Syz147064  * DLADM_STATUS_* code.
27685895Syz147064  */
27695895Syz147064 dladm_status_t
27705895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
27715895Syz147064 {
27725895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
27735895Syz147064 		return (DLADM_STATUS_BADVAL);
27745895Syz147064 
27755895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
27765895Syz147064 		/*
27775895Syz147064 		 * We don't allow multiple anchors, and the anchor must
27785895Syz147064 		 * be after at least one module.
27795895Syz147064 		 */
27805895Syz147064 		if (dlap->dap_anchor != 0)
27815895Syz147064 			return (DLADM_STATUS_BADVAL);
27825895Syz147064 		if (dlap->dap_npush == 0)
27835895Syz147064 			return (DLADM_STATUS_BADVAL);
27845895Syz147064 
27855895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
27865895Syz147064 		return (DLADM_STATUS_OK);
27875895Syz147064 	}
27888957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
27895895Syz147064 		return (DLADM_STATUS_BADVALCNT);
27905895Syz147064 
27915895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
27925895Syz147064 	    FMNAMESZ + 1);
27935895Syz147064 
27945895Syz147064 	return (DLADM_STATUS_OK);
27955895Syz147064 }
27965895Syz147064 
27975895Syz147064 /*
27985895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
27995895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
28005895Syz147064  * latter is used in the autopush(1M) file.
28015895Syz147064  */
28025895Syz147064 /* ARGSUSED */
28035895Syz147064 static dladm_status_t
280411878SVenu.Iyer@Sun.COM check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
280511878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
280611878SVenu.Iyer@Sun.COM     datalink_media_t media)
28075895Syz147064 {
28085895Syz147064 	char			*module;
28095895Syz147064 	struct dlautopush	*dlap;
28105895Syz147064 	dladm_status_t		status;
28115895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
28125895Syz147064 	char			delimiters[4];
28135895Syz147064 
28145895Syz147064 	if (val_cnt != 1)
28155895Syz147064 		return (DLADM_STATUS_BADVALCNT);
28165895Syz147064 
28177342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
28187342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
28197342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
28207342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
28213448Sdh155122 
28227342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
28237342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
28247342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
28257342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
28267342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
28277342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
28287342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
28297342SAruna.Ramakrishna@Sun.COM 				return (status);
28307342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
28317342SAruna.Ramakrishna@Sun.COM 		}
28327342SAruna.Ramakrishna@Sun.COM 
28337342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
28347342SAruna.Ramakrishna@Sun.COM 	} else {
28357342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
28365895Syz147064 	}
28373448Sdh155122 	return (DLADM_STATUS_OK);
28383448Sdh155122 }
28393448Sdh155122 
28407663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
28417663SSowmini.Varadhan@Sun.COM 
28425903Ssowmini /* ARGSUSED */
28433448Sdh155122 static dladm_status_t
284411878SVenu.Iyer@Sun.COM get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
28458453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
28468453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
28473448Sdh155122 {
28485895Syz147064 	wl_rates_t	*wrp;
28495895Syz147064 	uint_t		i;
28505895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
28515895Syz147064 
28527663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
28537663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
28547663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
28555895Syz147064 
28568453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
28578453SAnurag.Maskey@Sun.COM 	    B_FALSE);
28585895Syz147064 	if (status != DLADM_STATUS_OK)
28595895Syz147064 		goto done;
28605895Syz147064 
28615895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
28625895Syz147064 		status = DLADM_STATUS_TOOSMALL;
28635895Syz147064 		goto done;
28645895Syz147064 	}
28655895Syz147064 
28665895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
28675895Syz147064 		prop_val[0][0] = '\0';
28685895Syz147064 		*val_cnt = 1;
28695895Syz147064 		goto done;
28705895Syz147064 	}
28715895Syz147064 
28725895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
28735895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
28745895Syz147064 		    wrp->wl_rates_rates[i] % 2,
28755895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
28765895Syz147064 	}
28775895Syz147064 	*val_cnt = wrp->wl_rates_num;
28788275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
28793448Sdh155122 
28805895Syz147064 done:
28817663SSowmini.Varadhan@Sun.COM 	free(wrp);
28825895Syz147064 	return (status);
28835895Syz147064 }
28845895Syz147064 
28855895Syz147064 static dladm_status_t
288611878SVenu.Iyer@Sun.COM get_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
28878275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
28888275SEric Cheng     uint_t flags, uint_t *perm_flags)
28895895Syz147064 {
28908118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
289111878SVenu.Iyer@Sun.COM 		return (get_speed(handle, pdp, linkid, prop_val,
289211878SVenu.Iyer@Sun.COM 		    val_cnt, media, flags, perm_flags));
28938118SVasumathi.Sundaram@Sun.COM 	}
28945960Ssowmini 
289511878SVenu.Iyer@Sun.COM 	return (get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
28968275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
28975895Syz147064 }
28985895Syz147064 
28996512Ssowmini /* ARGSUSED */
29005895Syz147064 static dladm_status_t
290111878SVenu.Iyer@Sun.COM get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
29028275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
29038275SEric Cheng     uint_t flags, uint_t *perm_flags)
29045895Syz147064 {
29055960Ssowmini 	switch (media) {
29065960Ssowmini 	case DL_ETHER:
29076512Ssowmini 		/*
29086512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
29096512Ssowmini 		 * links can have a speed of 5.5 Gbps.
29106512Ssowmini 		 */
29116512Ssowmini 		return (DLADM_STATUS_NOTSUP);
29125960Ssowmini 
29135960Ssowmini 	case DL_WIFI:
291411878SVenu.Iyer@Sun.COM 		return (get_rate_common(handle, pdp, linkid, prop_val,
29158453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
29165960Ssowmini 	default:
29175960Ssowmini 		return (DLADM_STATUS_BADARG);
29185960Ssowmini 	}
29195895Syz147064 }
29205895Syz147064 
29215895Syz147064 static dladm_status_t
292211878SVenu.Iyer@Sun.COM set_wlan_rate(dladm_handle_t handle, datalink_id_t linkid,
29238453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
29245895Syz147064 {
29255895Syz147064 	int		i;
29265895Syz147064 	uint_t		len;
29275895Syz147064 	wl_rates_t	*wrp;
29285895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
29295895Syz147064 
29307663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
29317663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
29325895Syz147064 		return (DLADM_STATUS_NOMEM);
29335895Syz147064 
29347663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
29355895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
29365895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
29375895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
29385895Syz147064 
29395895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
29405895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
29418453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
29428453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
29435895Syz147064 
29447663SSowmini.Varadhan@Sun.COM 	free(wrp);
29455895Syz147064 	return (status);
29465895Syz147064 }
29473448Sdh155122 
29485903Ssowmini /* ARGSUSED */
29495895Syz147064 static dladm_status_t
295011878SVenu.Iyer@Sun.COM set_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
29515960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
29525895Syz147064 {
29535895Syz147064 	dladm_wlan_rates_t	rates;
29545895Syz147064 	dladm_status_t		status;
29555895Syz147064 
29565960Ssowmini 	/*
29575960Ssowmini 	 * can currently set rate on WIFI links only.
29585960Ssowmini 	 */
29595960Ssowmini 	if (media != DL_WIFI)
29605960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
29615960Ssowmini 
29625895Syz147064 	if (val_cnt != 1)
29635895Syz147064 		return (DLADM_STATUS_BADVALCNT);
29645895Syz147064 
29655895Syz147064 	rates.wr_cnt = 1;
29665895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
29675895Syz147064 
296811878SVenu.Iyer@Sun.COM 	status = set_wlan_rate(handle, linkid, &rates);
296911878SVenu.Iyer@Sun.COM 
29705895Syz147064 	return (status);
29715895Syz147064 }
29723448Sdh155122 
29735895Syz147064 /* ARGSUSED */
29745895Syz147064 static dladm_status_t
297511878SVenu.Iyer@Sun.COM check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
297611878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
297711878SVenu.Iyer@Sun.COM     datalink_media_t media)
29785895Syz147064 {
29795895Syz147064 	int		i;
29805895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
29815895Syz147064 	char		*buf, **modval;
29825895Syz147064 	dladm_status_t	status;
29838118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
29845895Syz147064 
29855895Syz147064 	if (val_cnt != 1)
29865895Syz147064 		return (DLADM_STATUS_BADVALCNT);
29875895Syz147064 
29885895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
29895895Syz147064 	    MAX_SUPPORT_RATES);
29905895Syz147064 	if (buf == NULL) {
29915895Syz147064 		status = DLADM_STATUS_NOMEM;
29925895Syz147064 		goto done;
29935895Syz147064 	}
29943448Sdh155122 
29955895Syz147064 	modval = (char **)(void *)buf;
29965895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
29975895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
29985895Syz147064 		    i * DLADM_STRSIZE;
29995895Syz147064 	}
30005895Syz147064 
300111878SVenu.Iyer@Sun.COM 	status = get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
30028453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
30035895Syz147064 	if (status != DLADM_STATUS_OK)
30045895Syz147064 		goto done;
30055895Syz147064 
30065895Syz147064 	for (i = 0; i < modval_cnt; i++) {
30075895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
30085903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
30095903Ssowmini 			    (atof(*prop_val) * 2);
30105895Syz147064 			status = DLADM_STATUS_OK;
30113448Sdh155122 			break;
30123448Sdh155122 		}
30135895Syz147064 	}
30145895Syz147064 	if (i == modval_cnt)
30155895Syz147064 		status = DLADM_STATUS_BADVAL;
30165895Syz147064 done:
30175895Syz147064 	free(buf);
30185895Syz147064 	return (status);
30195895Syz147064 }
30205895Syz147064 
30215895Syz147064 static dladm_status_t
302211878SVenu.Iyer@Sun.COM get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
30238453SAnurag.Maskey@Sun.COM     int buflen)
30245895Syz147064 {
30258453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
30267663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
30275895Syz147064 }
30285895Syz147064 
30295903Ssowmini /* ARGSUSED */
30305895Syz147064 static dladm_status_t
303111878SVenu.Iyer@Sun.COM get_channel(dladm_handle_t handle, prop_desc_t *pdp,
30328453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30338453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30345895Syz147064 {
30355895Syz147064 	uint32_t	channel;
30367663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
303711878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
30387663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
30395895Syz147064 
304011878SVenu.Iyer@Sun.COM 	if ((status = get_phyconf(handle, linkid, buf, sizeof (buf)))
30417663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
304211878SVenu.Iyer@Sun.COM 		return (status);
30435895Syz147064 
30447663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
304511878SVenu.Iyer@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel))
304611878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
30475895Syz147064 
30485895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
30495895Syz147064 	*val_cnt = 1;
30508275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
305111878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
30525895Syz147064 }
30535895Syz147064 
30545903Ssowmini /* ARGSUSED */
30555895Syz147064 static dladm_status_t
305611878SVenu.Iyer@Sun.COM get_powermode(dladm_handle_t handle, prop_desc_t *pdp,
30578453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30588453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30595895Syz147064 {
30607663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
30615895Syz147064 	const char	*s;
30627663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
306311878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
306411878SVenu.Iyer@Sun.COM 
306511878SVenu.Iyer@Sun.COM 	if ((status = i_dladm_wlan_param(handle, linkid, buf,
306611878SVenu.Iyer@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
306711878SVenu.Iyer@Sun.COM 		return (status);
30685895Syz147064 
30697663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
30707663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
30715895Syz147064 	case WL_PM_AM:
30725895Syz147064 		s = "off";
30735895Syz147064 		break;
30745895Syz147064 	case WL_PM_MPS:
30755895Syz147064 		s = "max";
30765895Syz147064 		break;
30775895Syz147064 	case WL_PM_FAST:
30785895Syz147064 		s = "fast";
30793448Sdh155122 		break;
30803448Sdh155122 	default:
308111878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
30825895Syz147064 	}
30835895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
30845895Syz147064 	*val_cnt = 1;
30858275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
308611878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
30875895Syz147064 }
30885895Syz147064 
308911878SVenu.Iyer@Sun.COM /* ARGSUSED */
30905895Syz147064 static dladm_status_t
309111878SVenu.Iyer@Sun.COM set_powermode(dladm_handle_t handle, prop_desc_t *pdp,
309211878SVenu.Iyer@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
309311878SVenu.Iyer@Sun.COM     datalink_media_t media)
30945895Syz147064 {
309511878SVenu.Iyer@Sun.COM 	dladm_wlan_powermode_t	powermode = vdp->vd_val;
309611878SVenu.Iyer@Sun.COM 	wl_ps_mode_t		ps_mode;
309711878SVenu.Iyer@Sun.COM 
309811878SVenu.Iyer@Sun.COM 	if (val_cnt != 1)
309911878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
31005895Syz147064 
31015895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
31025895Syz147064 
310311878SVenu.Iyer@Sun.COM 	switch (powermode) {
31045895Syz147064 	case DLADM_WLAN_PM_OFF:
31055895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
31063448Sdh155122 		break;
31075895Syz147064 	case DLADM_WLAN_PM_MAX:
31085895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
31095895Syz147064 		break;
31105895Syz147064 	case DLADM_WLAN_PM_FAST:
31115895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
31125895Syz147064 		break;
31135895Syz147064 	default:
31145895Syz147064 		return (DLADM_STATUS_NOTSUP);
31153448Sdh155122 	}
31168453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
31178453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
31185895Syz147064 }
31195895Syz147064 
31205895Syz147064 /* ARGSUSED */
31215895Syz147064 static dladm_status_t
312211878SVenu.Iyer@Sun.COM get_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
31238275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
31248275SEric Cheng     uint_t flags, uint_t *perm_flags)
31255895Syz147064 {
31265895Syz147064 	wl_radio_t	radio;
31275895Syz147064 	const char	*s;
31287663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
312911878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
313011878SVenu.Iyer@Sun.COM 
313111878SVenu.Iyer@Sun.COM 	if ((status = i_dladm_wlan_param(handle, linkid, buf,
313211878SVenu.Iyer@Sun.COM 	    MAC_PROP_WL_RADIO, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
313311878SVenu.Iyer@Sun.COM 		return (status);
31343448Sdh155122 
31357663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
31365895Syz147064 	switch (radio) {
31375895Syz147064 	case B_TRUE:
31385895Syz147064 		s = "on";
31395895Syz147064 		break;
31405895Syz147064 	case B_FALSE:
31415895Syz147064 		s = "off";
31425895Syz147064 		break;
31435895Syz147064 	default:
314411878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
31455895Syz147064 	}
31465895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
31475895Syz147064 	*val_cnt = 1;
31488275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
314911878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
31503448Sdh155122 }
31513448Sdh155122 
315211878SVenu.Iyer@Sun.COM /* ARGSUSED */
31533448Sdh155122 static dladm_status_t
315411878SVenu.Iyer@Sun.COM set_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
315511878SVenu.Iyer@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
31563448Sdh155122 {
315711878SVenu.Iyer@Sun.COM 	dladm_wlan_radio_t	radio = vdp->vd_val;
315811878SVenu.Iyer@Sun.COM 	wl_radio_t		r;
315911878SVenu.Iyer@Sun.COM 
316011878SVenu.Iyer@Sun.COM 	if (val_cnt != 1)
316111878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
316211878SVenu.Iyer@Sun.COM 
316311878SVenu.Iyer@Sun.COM 	switch (radio) {
31645895Syz147064 	case DLADM_WLAN_RADIO_ON:
31655895Syz147064 		r = B_TRUE;
31665895Syz147064 		break;
31675895Syz147064 	case DLADM_WLAN_RADIO_OFF:
31685895Syz147064 		r = B_FALSE;
31695895Syz147064 		break;
31705895Syz147064 	default:
31715895Syz147064 		return (DLADM_STATUS_NOTSUP);
31725895Syz147064 	}
31738453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
31747663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
31755895Syz147064 }
31763448Sdh155122 
31775895Syz147064 /* ARGSUSED */
31785895Syz147064 static dladm_status_t
317911878SVenu.Iyer@Sun.COM check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
318011878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
318111878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
318210616SSebastien.Roy@Sun.COM {
318310616SSebastien.Roy@Sun.COM 	int32_t	hlim;
318410616SSebastien.Roy@Sun.COM 	char	*ep;
318510616SSebastien.Roy@Sun.COM 
318610616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
318710616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
318810616SSebastien.Roy@Sun.COM 
318910616SSebastien.Roy@Sun.COM 	errno = 0;
319010616SSebastien.Roy@Sun.COM 	hlim = strtol(*prop_val, &ep, 10);
319110616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || hlim < 1 ||
319210616SSebastien.Roy@Sun.COM 	    hlim > (int32_t)UINT8_MAX)
319310616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
319410616SSebastien.Roy@Sun.COM 	vdp->vd_val = hlim;
319510616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
319610616SSebastien.Roy@Sun.COM }
319710616SSebastien.Roy@Sun.COM 
319810616SSebastien.Roy@Sun.COM /* ARGSUSED */
319910616SSebastien.Roy@Sun.COM static dladm_status_t
320011878SVenu.Iyer@Sun.COM check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
320111878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
320211878SVenu.Iyer@Sun.COM     datalink_media_t media)
320310616SSebastien.Roy@Sun.COM {
320410616SSebastien.Roy@Sun.COM 	int32_t	elim;
320510616SSebastien.Roy@Sun.COM 	char	*ep;
320610616SSebastien.Roy@Sun.COM 
320710616SSebastien.Roy@Sun.COM 	if (media != DL_IPV6)
320810616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADARG);
320910616SSebastien.Roy@Sun.COM 
321010616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
321110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
321210616SSebastien.Roy@Sun.COM 
321310616SSebastien.Roy@Sun.COM 	errno = 0;
321410616SSebastien.Roy@Sun.COM 	elim = strtol(*prop_val, &ep, 10);
321510616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || elim < 0 ||
321610616SSebastien.Roy@Sun.COM 	    elim > (int32_t)UINT8_MAX)
321710616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
321810616SSebastien.Roy@Sun.COM 	vdp->vd_val = elim;
321910616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
322010616SSebastien.Roy@Sun.COM }
322110616SSebastien.Roy@Sun.COM 
32225895Syz147064 static dladm_status_t
32238453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
32248453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
32253448Sdh155122 {
32265895Syz147064 	char		buf[MAXLINELEN];
32275895Syz147064 	int		i;
32285895Syz147064 	dladm_conf_t	conf;
32295895Syz147064 	dladm_status_t	status;
32303448Sdh155122 
32318453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
32325895Syz147064 	if (status != DLADM_STATUS_OK)
32335895Syz147064 		return (status);
32343448Sdh155122 
32355895Syz147064 	/*
32365895Syz147064 	 * reset case.
32375895Syz147064 	 */
32385895Syz147064 	if (val_cnt == 0) {
32398453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
32405895Syz147064 		if (status == DLADM_STATUS_OK)
32418453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
32425895Syz147064 		goto done;
32435895Syz147064 	}
32443448Sdh155122 
32455895Syz147064 	buf[0] = '\0';
32465895Syz147064 	for (i = 0; i < val_cnt; i++) {
32475895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
32485895Syz147064 		if (i != val_cnt - 1)
32495895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
32503448Sdh155122 	}
32513448Sdh155122 
32528453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
32538453SAnurag.Maskey@Sun.COM 	    buf);
32545895Syz147064 	if (status == DLADM_STATUS_OK)
32558453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
32565895Syz147064 
32575895Syz147064 done:
32588453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
32595895Syz147064 	return (status);
32603448Sdh155122 }
32615895Syz147064 
32625895Syz147064 static dladm_status_t
32638453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
32648453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
32655895Syz147064 {
32665895Syz147064 	char		buf[MAXLINELEN], *str;
32675895Syz147064 	uint_t		cnt = 0;
32685895Syz147064 	dladm_conf_t	conf;
32695895Syz147064 	dladm_status_t	status;
32705895Syz147064 
32718453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
32725895Syz147064 	if (status != DLADM_STATUS_OK)
32735895Syz147064 		return (status);
32745895Syz147064 
32758453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
32765895Syz147064 	if (status != DLADM_STATUS_OK)
32775895Syz147064 		goto done;
32785895Syz147064 
32795895Syz147064 	str = strtok(buf, ",");
32805895Syz147064 	while (str != NULL) {
32815895Syz147064 		if (cnt == *val_cntp) {
32825895Syz147064 			status = DLADM_STATUS_TOOSMALL;
32835895Syz147064 			goto done;
32845895Syz147064 		}
32855895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
32865895Syz147064 		str = strtok(NULL, ",");
32875895Syz147064 	}
32885895Syz147064 
32895895Syz147064 	*val_cntp = cnt;
32905895Syz147064 
32915895Syz147064 done:
32928453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
32935895Syz147064 	return (status);
32945895Syz147064 }
32955903Ssowmini 
32968460SArtem.Kachitchkin@Sun.COM /*
32978460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
32988460SArtem.Kachitchkin@Sun.COM  */
32998460SArtem.Kachitchkin@Sun.COM static dladm_status_t
33008460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
33018460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
33028460SArtem.Kachitchkin@Sun.COM {
33038460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
33048460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
33058460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
33068460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
33078460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
33088460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
33098460SArtem.Kachitchkin@Sun.COM 
33108460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
33118460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
33128460SArtem.Kachitchkin@Sun.COM 
33138460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
33148460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
33158460SArtem.Kachitchkin@Sun.COM 		return (status);
33168460SArtem.Kachitchkin@Sun.COM 
33178460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
33188460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
33198460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
33208460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
33218460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
33228460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
33238460SArtem.Kachitchkin@Sun.COM 				break;
33248460SArtem.Kachitchkin@Sun.COM 		}
33258460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
33268460SArtem.Kachitchkin@Sun.COM 	}
33278460SArtem.Kachitchkin@Sun.COM 
33288460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
33298460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
33308460SArtem.Kachitchkin@Sun.COM }
33318460SArtem.Kachitchkin@Sun.COM 
33327663SSowmini.Varadhan@Sun.COM static link_attr_t *
33335903Ssowmini dladm_name2prop(const char *prop_name)
33345903Ssowmini {
33357663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33365903Ssowmini 
33377663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
33385903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
33395903Ssowmini 			break;
33405903Ssowmini 	}
33415903Ssowmini 	return (p);
33425903Ssowmini }
33435903Ssowmini 
33447663SSowmini.Varadhan@Sun.COM static link_attr_t *
33457663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
33467663SSowmini.Varadhan@Sun.COM {
33477663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33487663SSowmini.Varadhan@Sun.COM 
33497663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
33507663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
33517663SSowmini.Varadhan@Sun.COM 			break;
33527663SSowmini.Varadhan@Sun.COM 	}
33537663SSowmini.Varadhan@Sun.COM 	return (p);
33547663SSowmini.Varadhan@Sun.COM }
33555903Ssowmini 
33566789Sam223141 static dld_ioc_macprop_t *
33577663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
33587663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
33597663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
33605903Ssowmini {
33615903Ssowmini 	int dsize;
33626789Sam223141 	dld_ioc_macprop_t *dip;
33635903Ssowmini 
33645903Ssowmini 	*status = DLADM_STATUS_OK;
33656789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
33665903Ssowmini 	dip = malloc(dsize);
33675903Ssowmini 	if (dip == NULL) {
33685903Ssowmini 		*status = DLADM_STATUS_NOMEM;
33695903Ssowmini 		return (NULL);
33705903Ssowmini 	}
33715903Ssowmini 	bzero(dip, dsize);
33725903Ssowmini 	dip->pr_valsize = valsize;
33736512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
33745960Ssowmini 	dip->pr_linkid = linkid;
33757663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
33766512Ssowmini 	dip->pr_flags = flags;
33775903Ssowmini 	return (dip);
33785903Ssowmini }
33795903Ssowmini 
33807663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
33817663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
33827663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
33837663SSowmini.Varadhan@Sun.COM {
33847663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33857663SSowmini.Varadhan@Sun.COM 
33867663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
33877663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
33887663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
33897663SSowmini.Varadhan@Sun.COM 	    flags, status));
33907663SSowmini.Varadhan@Sun.COM }
33917663SSowmini.Varadhan@Sun.COM 
33927663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
33937663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
33947663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, uint_t flags, dladm_status_t *status)
33957663SSowmini.Varadhan@Sun.COM {
33967663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33977663SSowmini.Varadhan@Sun.COM 
33987663SSowmini.Varadhan@Sun.COM 	p = dladm_id2prop(propid);
33997663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
34007663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
34017663SSowmini.Varadhan@Sun.COM 	    flags, status));
34027663SSowmini.Varadhan@Sun.COM }
34037663SSowmini.Varadhan@Sun.COM 
34045903Ssowmini /* ARGSUSED */
34055903Ssowmini static dladm_status_t
340611878SVenu.Iyer@Sun.COM set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
34078453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
34088453SAnurag.Maskey@Sun.COM     datalink_media_t media)
34095903Ssowmini {
34106789Sam223141 	dld_ioc_macprop_t	*dip;
34115903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
34125903Ssowmini 	uint8_t		u8;
34135903Ssowmini 	uint16_t	u16;
34145903Ssowmini 	uint32_t	u32;
34155903Ssowmini 	void		*val;
34165903Ssowmini 
34178275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
34185903Ssowmini 	if (dip == NULL)
34195903Ssowmini 		return (status);
34205903Ssowmini 
34218275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
34225903Ssowmini 		val = (void *)vdp->vd_val;
34235903Ssowmini 	else {
34245903Ssowmini 		/*
34255903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
34265903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
34275903Ssowmini 		 */
34285903Ssowmini 		switch (dip->pr_valsize) {
34295903Ssowmini 		case 1:
34305903Ssowmini 			u8 = vdp->vd_val;
34315903Ssowmini 			val = &u8;
34325903Ssowmini 			break;
34335903Ssowmini 		case 2:
34345903Ssowmini 			u16 = vdp->vd_val;
34355903Ssowmini 			val = &u16;
34365903Ssowmini 			break;
34375903Ssowmini 		case 4:
34385903Ssowmini 			u32 = vdp->vd_val;
34395903Ssowmini 			val = &u32;
34405903Ssowmini 			break;
34415903Ssowmini 		default:
34425903Ssowmini 			val = &vdp->vd_val;
34435903Ssowmini 			break;
34445903Ssowmini 		}
34455903Ssowmini 	}
34465903Ssowmini 
34477342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
34487342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
34497342SAruna.Ramakrishna@Sun.COM 	else
34507342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
34517342SAruna.Ramakrishna@Sun.COM 
34528453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
34537663SSowmini.Varadhan@Sun.COM 
34547663SSowmini.Varadhan@Sun.COM done:
34557663SSowmini.Varadhan@Sun.COM 	free(dip);
34567663SSowmini.Varadhan@Sun.COM 	return (status);
34577663SSowmini.Varadhan@Sun.COM }
34587663SSowmini.Varadhan@Sun.COM 
34597663SSowmini.Varadhan@Sun.COM dladm_status_t
34608453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
34617663SSowmini.Varadhan@Sun.COM {
34627663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
34637663SSowmini.Varadhan@Sun.COM 
34648453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
34658453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
34665903Ssowmini 		status = dladm_errno2status(errno);
34678453SAnurag.Maskey@Sun.COM 
34685903Ssowmini 	return (status);
34695903Ssowmini }
34705903Ssowmini 
347111878SVenu.Iyer@Sun.COM static dladm_status_t
34728453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
347311878SVenu.Iyer@Sun.COM     char *prop_name, uint_t flags, uint_t *perm_flags, void *arg, size_t size)
34745903Ssowmini {
347511878SVenu.Iyer@Sun.COM 	dld_ioc_macprop_t	*dip;
347611878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
347711878SVenu.Iyer@Sun.COM 
347811878SVenu.Iyer@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, &status);
34796512Ssowmini 	if (dip == NULL)
348011878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
348111878SVenu.Iyer@Sun.COM 
348211878SVenu.Iyer@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
348311878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK) {
34846512Ssowmini 		free(dip);
348511878SVenu.Iyer@Sun.COM 		return (status);
34866512Ssowmini 	}
348711878SVenu.Iyer@Sun.COM 
34888275SEric Cheng 	if (perm_flags != NULL)
34898275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
34908275SEric Cheng 
349111878SVenu.Iyer@Sun.COM 	if (arg != NULL)
349211878SVenu.Iyer@Sun.COM 		(void) memcpy(arg, dip->pr_val, size);
349311878SVenu.Iyer@Sun.COM 	free(dip);
349411878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
34955903Ssowmini }
34965903Ssowmini 
34975903Ssowmini /* ARGSUSED */
34985903Ssowmini static dladm_status_t
349911878SVenu.Iyer@Sun.COM check_uint32(dladm_handle_t handle, prop_desc_t *pdp,
350011878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
350111878SVenu.Iyer@Sun.COM     val_desc_t *v, datalink_media_t media)
35025903Ssowmini {
35035903Ssowmini 	if (val_cnt != 1)
35045903Ssowmini 		return (DLADM_STATUS_BADVAL);
350510491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
35065903Ssowmini 	return (DLADM_STATUS_OK);
35075903Ssowmini }
35085903Ssowmini 
35095903Ssowmini /* ARGSUSED */
35105903Ssowmini static dladm_status_t
351111878SVenu.Iyer@Sun.COM get_duplex(dladm_handle_t handle, prop_desc_t *pdp,
35128453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35138453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35145903Ssowmini {
35155903Ssowmini 	link_duplex_t   link_duplex;
35165903Ssowmini 	dladm_status_t  status;
35175903Ssowmini 
35188453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
35195903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
35205903Ssowmini 		return (status);
35215903Ssowmini 
35225903Ssowmini 	switch (link_duplex) {
35235903Ssowmini 	case LINK_DUPLEX_FULL:
35245903Ssowmini 		(void) strcpy(*prop_val, "full");
35255903Ssowmini 		break;
35265903Ssowmini 	case LINK_DUPLEX_HALF:
35275903Ssowmini 		(void) strcpy(*prop_val, "half");
35285903Ssowmini 		break;
35295903Ssowmini 	default:
35305903Ssowmini 		(void) strcpy(*prop_val, "unknown");
35315903Ssowmini 		break;
35325903Ssowmini 	}
35335903Ssowmini 	*val_cnt = 1;
35345903Ssowmini 	return (DLADM_STATUS_OK);
35355903Ssowmini }
35365903Ssowmini 
35375903Ssowmini /* ARGSUSED */
35385903Ssowmini static dladm_status_t
353911878SVenu.Iyer@Sun.COM get_speed(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
354011878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
354111878SVenu.Iyer@Sun.COM     uint_t *perm_flags)
35425903Ssowmini {
35435903Ssowmini 	uint64_t	ifspeed = 0;
35445903Ssowmini 	dladm_status_t status;
35455903Ssowmini 
35468453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
35475903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
35485903Ssowmini 		return (status);
35496512Ssowmini 
35505960Ssowmini 	if ((ifspeed % 1000000) != 0) {
35515960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
35525960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
35535960Ssowmini 	} else {
35545960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
35555960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
35565960Ssowmini 	}
35575903Ssowmini 	*val_cnt = 1;
35588275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
35595903Ssowmini 	return (DLADM_STATUS_OK);
35605903Ssowmini }
35615903Ssowmini 
35625903Ssowmini /* ARGSUSED */
35635903Ssowmini static dladm_status_t
356411878SVenu.Iyer@Sun.COM get_link_state(dladm_handle_t handle, prop_desc_t *pdp,
35658453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35668453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35675903Ssowmini {
35688275SEric Cheng 	link_state_t		link_state;
35698275SEric Cheng 	dladm_status_t		status;
35708306SSowmini.Varadhan@Sun.COM 
357111878SVenu.Iyer@Sun.COM 	status = dladm_get_state(handle, linkid, &link_state);
35726512Ssowmini 	if (status != DLADM_STATUS_OK)
35735903Ssowmini 		return (status);
35748275SEric Cheng 
35755903Ssowmini 	switch (link_state) {
35765903Ssowmini 	case LINK_STATE_UP:
35775903Ssowmini 		(void) strcpy(*prop_val, "up");
35785903Ssowmini 		break;
35795903Ssowmini 	case LINK_STATE_DOWN:
35805903Ssowmini 		(void) strcpy(*prop_val, "down");
35815903Ssowmini 		break;
35825903Ssowmini 	default:
35835903Ssowmini 		(void) strcpy(*prop_val, "unknown");
35845903Ssowmini 		break;
35855903Ssowmini 	}
35865903Ssowmini 	*val_cnt = 1;
35878306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
35885903Ssowmini 	return (DLADM_STATUS_OK);
35895903Ssowmini }
35905903Ssowmini 
35915903Ssowmini /* ARGSUSED */
35925903Ssowmini static dladm_status_t
359311878SVenu.Iyer@Sun.COM get_binary(dladm_handle_t handle, prop_desc_t *pdp,
35948453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35958453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35965903Ssowmini {
359711878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
359811878SVenu.Iyer@Sun.COM 	uint_t		v = 0;
359911878SVenu.Iyer@Sun.COM 
360011878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
360111878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
360211878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
36035903Ssowmini 		return (status);
36048275SEric Cheng 
360511878SVenu.Iyer@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%d", (uint_t)(v > 0));
36065903Ssowmini 	*val_cnt = 1;
36075903Ssowmini 	return (DLADM_STATUS_OK);
36085903Ssowmini }
36095903Ssowmini 
36105960Ssowmini /* ARGSUSED */
36115903Ssowmini static dladm_status_t
361211878SVenu.Iyer@Sun.COM get_uint32(dladm_handle_t handle, prop_desc_t *pdp,
36138453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
36148453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
36155903Ssowmini {
361611878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
361711878SVenu.Iyer@Sun.COM 	uint32_t	v = 0;
361811878SVenu.Iyer@Sun.COM 
361911878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
362011878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
362111878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
36225903Ssowmini 		return (status);
36238275SEric Cheng 
36246512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
36255903Ssowmini 	*val_cnt = 1;
36265903Ssowmini 	return (DLADM_STATUS_OK);
36275903Ssowmini }
36285903Ssowmini 
36299514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
36309514SGirish.Moodalbail@Sun.COM static dladm_status_t
363111878SVenu.Iyer@Sun.COM get_range(dladm_handle_t handle, prop_desc_t *pdp,
36329514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
36339514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
36349514SGirish.Moodalbail@Sun.COM {
36359514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
36369514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
36379514SGirish.Moodalbail@Sun.COM 	size_t	sz;
36389514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
36399514SGirish.Moodalbail@Sun.COM 
36409514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
36419514SGirish.Moodalbail@Sun.COM 
36429514SGirish.Moodalbail@Sun.COM 	/*
36439514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
36449514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
36459514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
36469514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
36479514SGirish.Moodalbail@Sun.COM 	 */
36489514SGirish.Moodalbail@Sun.COM retry:
36499514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
36509514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
36519514SGirish.Moodalbail@Sun.COM 		return (status);
36529514SGirish.Moodalbail@Sun.COM 
36539514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
36549514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
36559514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
36569514SGirish.Moodalbail@Sun.COM 			int err;
36579514SGirish.Moodalbail@Sun.COM 
36589514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
36599514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
36609514SGirish.Moodalbail@Sun.COM 				free(dip);
36619514SGirish.Moodalbail@Sun.COM 				goto retry;
36629514SGirish.Moodalbail@Sun.COM 			} else {
36639514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
36649514SGirish.Moodalbail@Sun.COM 			}
36659514SGirish.Moodalbail@Sun.COM 		}
36669514SGirish.Moodalbail@Sun.COM 		free(dip);
36679514SGirish.Moodalbail@Sun.COM 		return (status);
36689514SGirish.Moodalbail@Sun.COM 	}
366911878SVenu.Iyer@Sun.COM 
36709514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
367111878SVenu.Iyer@Sun.COM 	if (rangep->mpr_count == 0) {
367211878SVenu.Iyer@Sun.COM 		*val_cnt = 1;
367311878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "--");
367411878SVenu.Iyer@Sun.COM 		goto done;
367511878SVenu.Iyer@Sun.COM 	}
36769514SGirish.Moodalbail@Sun.COM 
36779514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
36789514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
36799514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
36809514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
36819514SGirish.Moodalbail@Sun.COM 
368211878SVenu.Iyer@Sun.COM 		ur = &rangep->mpr_range_uint32[0];
36839514SGirish.Moodalbail@Sun.COM 
36849514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
36859514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
36869514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
36879514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
36889514SGirish.Moodalbail@Sun.COM 			} else {
36899514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
36909514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
36919514SGirish.Moodalbail@Sun.COM 			}
36929514SGirish.Moodalbail@Sun.COM 		}
36939514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
36949514SGirish.Moodalbail@Sun.COM 		break;
36959514SGirish.Moodalbail@Sun.COM 	}
36969514SGirish.Moodalbail@Sun.COM 	default:
36979514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
36989514SGirish.Moodalbail@Sun.COM 		break;
36999514SGirish.Moodalbail@Sun.COM 	}
370011878SVenu.Iyer@Sun.COM done:
37019514SGirish.Moodalbail@Sun.COM 	free(dip);
37029514SGirish.Moodalbail@Sun.COM 	return (status);
37039514SGirish.Moodalbail@Sun.COM }
37049514SGirish.Moodalbail@Sun.COM 
37055960Ssowmini /* ARGSUSED */
37065903Ssowmini static dladm_status_t
370711878SVenu.Iyer@Sun.COM get_tagmode(dladm_handle_t handle, prop_desc_t *pdp,
37088874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
37098874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
37108874SSebastien.Roy@Sun.COM {
37118874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
37128874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
37138874SSebastien.Roy@Sun.COM 
371411878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
371511878SVenu.Iyer@Sun.COM 	    perm_flags, &mode, sizeof (mode));
371611878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
37178874SSebastien.Roy@Sun.COM 		return (status);
37188874SSebastien.Roy@Sun.COM 
37198874SSebastien.Roy@Sun.COM 	switch (mode) {
37208874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
37218874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
37228874SSebastien.Roy@Sun.COM 		break;
37238874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
37248874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
37258874SSebastien.Roy@Sun.COM 		break;
37268874SSebastien.Roy@Sun.COM 	default:
37278874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
37288874SSebastien.Roy@Sun.COM 	}
37298874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
37308874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
37318874SSebastien.Roy@Sun.COM }
37328874SSebastien.Roy@Sun.COM 
37338874SSebastien.Roy@Sun.COM /* ARGSUSED */
37348874SSebastien.Roy@Sun.COM static dladm_status_t
373511878SVenu.Iyer@Sun.COM get_flowctl(dladm_handle_t handle, prop_desc_t *pdp,
37368453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
37378453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
37385903Ssowmini {
373911878SVenu.Iyer@Sun.COM 	link_flowctrl_t	v;
374011878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
374111878SVenu.Iyer@Sun.COM 
374211878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
374311878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
374411878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
37455903Ssowmini 		return (status);
37468275SEric Cheng 
37475903Ssowmini 	switch (v) {
37485903Ssowmini 	case LINK_FLOWCTRL_NONE:
37495903Ssowmini 		(void) sprintf(*prop_val, "no");
37505903Ssowmini 		break;
37515903Ssowmini 	case LINK_FLOWCTRL_RX:
37525903Ssowmini 		(void) sprintf(*prop_val, "rx");
37535903Ssowmini 		break;
37545903Ssowmini 	case LINK_FLOWCTRL_TX:
37555903Ssowmini 		(void) sprintf(*prop_val, "tx");
37565903Ssowmini 		break;
37575903Ssowmini 	case LINK_FLOWCTRL_BI:
37585903Ssowmini 		(void) sprintf(*prop_val, "bi");
37595903Ssowmini 		break;
37605903Ssowmini 	}
37615903Ssowmini 	*val_cnt = 1;
37625903Ssowmini 	return (DLADM_STATUS_OK);
37635903Ssowmini }
37645903Ssowmini 
37655903Ssowmini 
37665903Ssowmini /* ARGSUSED */
37675903Ssowmini static dladm_status_t
37689692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
37698453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
37708453SAnurag.Maskey@Sun.COM 
37715903Ssowmini {
37727663SSowmini.Varadhan@Sun.COM 	int		i, slen;
37737408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
37746789Sam223141 	dld_ioc_macprop_t *dip = NULL;
37755903Ssowmini 	uchar_t 	*dp;
37767663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
37776512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
37785903Ssowmini 
37795903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
37805903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
37815903Ssowmini 		return (DLADM_STATUS_BADARG);
37825903Ssowmini 	p = dladm_name2prop(prop_name);
37836789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
37845903Ssowmini 		return (DLADM_STATUS_BADARG);
37855903Ssowmini 
37869692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
37879692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
37889692SRishi.Srivatsavai@Sun.COM 
37895903Ssowmini 	/*
37905903Ssowmini 	 * private properties: all parsing is done in the kernel.
37915903Ssowmini 	 * allocate a enough space for each property + its separator (',').
37925903Ssowmini 	 */
37935903Ssowmini 	for (i = 0; i < val_cnt; i++) {
37945903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
37955903Ssowmini 	}
37966512Ssowmini 
37976512Ssowmini 	if (prop_val == NULL) {
37986512Ssowmini 		/*
37996512Ssowmini 		 * getting default value. so use more buffer space.
38006512Ssowmini 		 */
38017663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
38026512Ssowmini 	}
38036512Ssowmini 
38047663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
380511878SVenu.Iyer@Sun.COM 	    (prop_val != NULL ? 0 : DLD_PROP_DEFAULT), &status);
38065903Ssowmini 	if (dip == NULL)
38075903Ssowmini 		return (status);
38085903Ssowmini 
38095903Ssowmini 	dp = (uchar_t *)dip->pr_val;
38105903Ssowmini 	slen = 0;
38117663SSowmini.Varadhan@Sun.COM 
38126512Ssowmini 	if (prop_val == NULL) {
38138453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
38148460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
38156512Ssowmini 	} else {
38166512Ssowmini 		for (i = 0; i < val_cnt; i++) {
38176512Ssowmini 			int plen = 0;
38185903Ssowmini 
38196512Ssowmini 			plen = strlen(prop_val[i]);
38206512Ssowmini 			bcopy(prop_val[i], dp, plen);
38216512Ssowmini 			slen += plen;
38226512Ssowmini 			/*
38236512Ssowmini 			 * add a "," separator and update dp.
38246512Ssowmini 			 */
38256512Ssowmini 			if (i != (val_cnt -1))
38266512Ssowmini 				dp[slen++] = ',';
38276512Ssowmini 			dp += (plen + 1);
38286512Ssowmini 		}
38298460SArtem.Kachitchkin@Sun.COM 	}
38308460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
38318453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
38326512Ssowmini 
38335903Ssowmini 	free(dip);
38346512Ssowmini 	return (status);
38355903Ssowmini }
38365903Ssowmini 
38375903Ssowmini static dladm_status_t
38388460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
38398453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
38408453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
38415903Ssowmini {
38427663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
38436789Sam223141 	dld_ioc_macprop_t *dip = NULL;
38447663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
38455903Ssowmini 
38465903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
38475903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
38485903Ssowmini 		return (DLADM_STATUS_BADARG);
38495903Ssowmini 
38505903Ssowmini 	p = dladm_name2prop(prop_name);
38516789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
38525903Ssowmini 		return (DLADM_STATUS_BADARG);
38535903Ssowmini 
38545903Ssowmini 	/*
38555903Ssowmini 	 * private properties: all parsing is done in the kernel.
38565903Ssowmini 	 */
38577663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
38587663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
38595903Ssowmini 	if (dip == NULL)
38605903Ssowmini 		return (status);
38615903Ssowmini 
38628453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
38638453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
38648118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
38658275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
38668460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
38678460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
38688118SVasumathi.Sundaram@Sun.COM 		} else {
38698118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
38708118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
38718118SVasumathi.Sundaram@Sun.COM 		}
38725903Ssowmini 		*val_cnt = 1;
38738460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
38748460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
38758460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
38765903Ssowmini 	}
38776512Ssowmini 	free(dip);
38785903Ssowmini 	return (status);
38795903Ssowmini }
38806512Ssowmini 
38816512Ssowmini 
38826512Ssowmini static dladm_status_t
38838453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
38848453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
38856512Ssowmini {
38866512Ssowmini 	dladm_status_t status;
38876512Ssowmini 	char **prop_vals = NULL, *buf;
38886512Ssowmini 	size_t bufsize;
38896512Ssowmini 	uint_t cnt;
38906512Ssowmini 	int i;
38918118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
38926512Ssowmini 
38936512Ssowmini 	/*
38946512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
38956512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
38966512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
38976512Ssowmini 	 */
38986512Ssowmini 	bufsize =
38996512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
39006512Ssowmini 	buf = malloc(bufsize);
39016512Ssowmini 	prop_vals = (char **)(void *)buf;
39026512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
39036512Ssowmini 		prop_vals[i] = buf +
39046512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
39056512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
39066512Ssowmini 	}
39076768Sar224390 
39086768Sar224390 	/*
39097342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
39107342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
39117342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
39127342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
39137342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
39147342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
39157342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
39167342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
39176768Sar224390 	 */
39188453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
391911878SVenu.Iyer@Sun.COM 	    DLD_PROP_DEFAULT, &perm_flags);
39206512Ssowmini 	if (status == DLADM_STATUS_OK) {
39218118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
39228453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
39238453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
39248118SVasumathi.Sundaram@Sun.COM 		}
39258118SVasumathi.Sundaram@Sun.COM 		else
39268118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
39276512Ssowmini 	}
39286512Ssowmini 	free(buf);
39296512Ssowmini 	return (status);
39306512Ssowmini }
39317663SSowmini.Varadhan@Sun.COM 
393210491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
393310491SRishi.Srivatsavai@Sun.COM static dladm_status_t
393411878SVenu.Iyer@Sun.COM get_stp(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
393510491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
393610491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
393710491SRishi.Srivatsavai@Sun.COM {
393810491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
393910491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
394010491SRishi.Srivatsavai@Sun.COM 	int val, i;
394110491SRishi.Srivatsavai@Sun.COM 
394210491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
394310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
394410491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
394510491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
394610491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
394710491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
394810491SRishi.Srivatsavai@Sun.COM 			break;
394910491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
395010491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
395110491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
395210491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
395310491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
395410491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
395510491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
395610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
395710491SRishi.Srivatsavai@Sun.COM 	}
395810491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
395910491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
396010491SRishi.Srivatsavai@Sun.COM 		return (retv);
396110491SRishi.Srivatsavai@Sun.COM 	}
396210491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
396310491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
396410491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
396510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
396610491SRishi.Srivatsavai@Sun.COM 	}
396710491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
396810491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
396910491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
397010491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
397110491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
397210491SRishi.Srivatsavai@Sun.COM 		}
397310491SRishi.Srivatsavai@Sun.COM 	}
397410491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
397510491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
397610491SRishi.Srivatsavai@Sun.COM }
397710491SRishi.Srivatsavai@Sun.COM 
397810491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
397910491SRishi.Srivatsavai@Sun.COM static dladm_status_t
398010491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
398110491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
398210491SRishi.Srivatsavai@Sun.COM {
398310491SRishi.Srivatsavai@Sun.COM 	/*
398410491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
398510491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
398610491SRishi.Srivatsavai@Sun.COM 	 */
398710491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
398810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
398910491SRishi.Srivatsavai@Sun.COM 
399010491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
399110491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
399210491SRishi.Srivatsavai@Sun.COM }
399310491SRishi.Srivatsavai@Sun.COM 
399410491SRishi.Srivatsavai@Sun.COM /*
399510491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
399610491SRishi.Srivatsavai@Sun.COM  */
399710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
399810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
399910491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
400011878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
400111878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
400210491SRishi.Srivatsavai@Sun.COM {
400310491SRishi.Srivatsavai@Sun.COM 	char *cp;
400410491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
400510491SRishi.Srivatsavai@Sun.COM 
400610491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
400710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
400810491SRishi.Srivatsavai@Sun.COM 
400910491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
401010491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
401110491SRishi.Srivatsavai@Sun.COM 	} else {
401210491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
401310491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
401410491SRishi.Srivatsavai@Sun.COM 
401510491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
401610491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
401710491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
401810491SRishi.Srivatsavai@Sun.COM 		} else {
401910491SRishi.Srivatsavai@Sun.COM 			errno = 0;
402010491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
402110491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
402210491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
402310491SRishi.Srivatsavai@Sun.COM 		}
402410491SRishi.Srivatsavai@Sun.COM 	}
402510491SRishi.Srivatsavai@Sun.COM 
402610491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
402710491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
402810491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
402910491SRishi.Srivatsavai@Sun.COM 	} else {
403010491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
403110491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
403210491SRishi.Srivatsavai@Sun.COM 		/*
403310491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
403410491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
403510491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
403610491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
403710491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
403810491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
403910491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
404010491SRishi.Srivatsavai@Sun.COM 		 */
404110491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
404210491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
404310491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
404410491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
404510491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
404610491SRishi.Srivatsavai@Sun.COM 
404710491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
404810491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
404910491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
405010491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
405110491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
405210491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
405310491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
405410491SRishi.Srivatsavai@Sun.COM 		}
405510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
405610491SRishi.Srivatsavai@Sun.COM 	}
405710491SRishi.Srivatsavai@Sun.COM }
405810491SRishi.Srivatsavai@Sun.COM 
405910491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
406010491SRishi.Srivatsavai@Sun.COM static dladm_status_t
406110491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
406210491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
406310491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
406410491SRishi.Srivatsavai@Sun.COM {
406510491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
406610491SRishi.Srivatsavai@Sun.COM 	uint_t val;
406710491SRishi.Srivatsavai@Sun.COM 
406810491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
406910491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
407010491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
407110491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
407210491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
407310491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
407410491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
407510491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
407610491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
407710491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
407810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
407910491SRishi.Srivatsavai@Sun.COM 	}
408010491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
408110491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
408210491SRishi.Srivatsavai@Sun.COM 	else
408310491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
408410491SRishi.Srivatsavai@Sun.COM 	return (retv);
408510491SRishi.Srivatsavai@Sun.COM }
408610491SRishi.Srivatsavai@Sun.COM 
408710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
408810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
408910491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
409010491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
409110491SRishi.Srivatsavai@Sun.COM {
409210491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
409310491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
409410491SRishi.Srivatsavai@Sun.COM }
409510491SRishi.Srivatsavai@Sun.COM 
409610491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
409710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
409810491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
409910491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
410010491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
410110491SRishi.Srivatsavai@Sun.COM {
410210491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
410310491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
410410491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
410510491SRishi.Srivatsavai@Sun.COM 
410610491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
410710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
410810491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
410910491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
411010491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
411110491SRishi.Srivatsavai@Sun.COM 	    0, &status);
411210491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
411310491SRishi.Srivatsavai@Sun.COM 		return (status);
411410491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
411510491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
411610491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
411710491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
411810491SRishi.Srivatsavai@Sun.COM 	} else {
411910491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
412010491SRishi.Srivatsavai@Sun.COM 	}
412110491SRishi.Srivatsavai@Sun.COM 	free(dip);
412210491SRishi.Srivatsavai@Sun.COM 	return (status);
412310491SRishi.Srivatsavai@Sun.COM }
412410491SRishi.Srivatsavai@Sun.COM 
412510491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
412610491SRishi.Srivatsavai@Sun.COM static dladm_status_t
412710491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
412810491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
412910491SRishi.Srivatsavai@Sun.COM {
413010491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
413110491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
413210491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
413310491SRishi.Srivatsavai@Sun.COM 
413410491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
413510491SRishi.Srivatsavai@Sun.COM 	    0, &status);
413610491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
413710491SRishi.Srivatsavai@Sun.COM 		return (status);
413810491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
413910491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
414010491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
414110491SRishi.Srivatsavai@Sun.COM 	free(dip);
414210491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
414310491SRishi.Srivatsavai@Sun.COM 		return (status);
414410491SRishi.Srivatsavai@Sun.COM 
414510491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
414610491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
414710491SRishi.Srivatsavai@Sun.COM }
414810491SRishi.Srivatsavai@Sun.COM 
414910491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
415010491SRishi.Srivatsavai@Sun.COM static dladm_status_t
415110491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
415211878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
415311878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
415410491SRishi.Srivatsavai@Sun.COM {
415510491SRishi.Srivatsavai@Sun.COM 	char *cp;
415610491SRishi.Srivatsavai@Sun.COM 
415710491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
415810491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
415910491SRishi.Srivatsavai@Sun.COM 
416010491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
416110491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
416210491SRishi.Srivatsavai@Sun.COM 	} else {
416310491SRishi.Srivatsavai@Sun.COM 		errno = 0;
416410491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
416510491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
416610491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
416710491SRishi.Srivatsavai@Sun.COM 	}
416810491SRishi.Srivatsavai@Sun.COM 
416910491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
417010491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
417110491SRishi.Srivatsavai@Sun.COM }
417210491SRishi.Srivatsavai@Sun.COM 
41737663SSowmini.Varadhan@Sun.COM dladm_status_t
41748453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
41758453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
41767663SSowmini.Varadhan@Sun.COM {
41777663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
41787663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
41797663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
41807663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
41817663SSowmini.Varadhan@Sun.COM 	void			*dp;
41827663SSowmini.Varadhan@Sun.COM 
41838453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
41848453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
41857663SSowmini.Varadhan@Sun.COM 		return (status);
41867663SSowmini.Varadhan@Sun.COM 	}
41877663SSowmini.Varadhan@Sun.COM 
41887663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
41897663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
41907663SSowmini.Varadhan@Sun.COM 
41917663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
41927663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
41937663SSowmini.Varadhan@Sun.COM 
41947663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
41957663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
41967663SSowmini.Varadhan@Sun.COM 
41977663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
41987663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
41997663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
42007663SSowmini.Varadhan@Sun.COM 
42017663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
42027663SSowmini.Varadhan@Sun.COM 	if (set)
42037663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
42047663SSowmini.Varadhan@Sun.COM 
42058453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
420610191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
42077663SSowmini.Varadhan@Sun.COM 		if (!set)
42087663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
42097663SSowmini.Varadhan@Sun.COM 	}
42107663SSowmini.Varadhan@Sun.COM 
42117663SSowmini.Varadhan@Sun.COM 	free(dip);
42127663SSowmini.Varadhan@Sun.COM 	return (status);
42137663SSowmini.Varadhan@Sun.COM }
42147663SSowmini.Varadhan@Sun.COM 
42158275SEric Cheng dladm_status_t
42168275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
42178275SEric Cheng {
42188460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
42198275SEric Cheng }
42208275SEric Cheng 
42218275SEric Cheng /*
42228275SEric Cheng  * Retrieve the one link property from the database
42238275SEric Cheng  */
42248275SEric Cheng /*ARGSUSED*/
42258275SEric Cheng static int
42268453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
42278453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
42288275SEric Cheng {
42298275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
42308275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
42318275SEric Cheng 
42328275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
42338275SEric Cheng 	/*
42348275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
42358275SEric Cheng 	 * prop_table[n].pd_name.
42368275SEric Cheng 	 */
42378275SEric Cheng 	aip->ai_name = prop_name;
42388275SEric Cheng 
42398453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
42408453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
42418275SEric Cheng 
42428275SEric Cheng 	if (aip->ai_count != 0)
42438275SEric Cheng 		proplist->al_count++;
42448275SEric Cheng 
42458275SEric Cheng 	return (DLADM_WALK_CONTINUE);
42468275SEric Cheng }
42478275SEric Cheng 
42488275SEric Cheng 
42498275SEric Cheng /*
42508275SEric Cheng  * Retrieve all link properties for a link from the database and
42518275SEric Cheng  * return a property list.
42528275SEric Cheng  */
42538275SEric Cheng dladm_status_t
42548453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
42558453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
42568275SEric Cheng {
42578275SEric Cheng 	dladm_arg_list_t	*list;
42588275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
42598275SEric Cheng 
42608275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
42618275SEric Cheng 	if (list == NULL)
42628275SEric Cheng 		return (dladm_errno2status(errno));
42638275SEric Cheng 
42648453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
42658453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
42668275SEric Cheng 
42678275SEric Cheng 	*listp = list;
42688275SEric Cheng 	return (status);
42698275SEric Cheng }
42708275SEric Cheng 
42718275SEric Cheng /*
42728275SEric Cheng  * Retrieve the named property from a proplist, check the value and
42738275SEric Cheng  * convert to a kernel structure.
42748275SEric Cheng  */
42758275SEric Cheng static dladm_status_t
42768453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
427711878SVenu.Iyer@Sun.COM     dladm_arg_list_t *proplist, const char *name, uint_t flags, void *arg)
42788275SEric Cheng {
42798275SEric Cheng 	dladm_status_t		status;
42808275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
42818275SEric Cheng 	int			i, j;
42828275SEric Cheng 
42838275SEric Cheng 	/* Find named property in proplist */
42848275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
42858275SEric Cheng 		aip = &proplist->al_info[i];
42868275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
42878275SEric Cheng 			break;
42888275SEric Cheng 	}
42898275SEric Cheng 
42908275SEric Cheng 	/* Property not in list */
42918275SEric Cheng 	if (i == proplist->al_count)
42928275SEric Cheng 		return (DLADM_STATUS_OK);
42938275SEric Cheng 
42948275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
42958275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
42968275SEric Cheng 		val_desc_t	*vdp;
42978275SEric Cheng 
42988275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
42998275SEric Cheng 		if (vdp == NULL)
43008275SEric Cheng 			return (DLADM_STATUS_NOMEM);
43018275SEric Cheng 
43028275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
43038275SEric Cheng 			continue;
43048275SEric Cheng 
43058275SEric Cheng 		if (aip->ai_val == NULL)
43068275SEric Cheng 			return (DLADM_STATUS_BADARG);
43078275SEric Cheng 
43088275SEric Cheng 		/* Check property value */
43098275SEric Cheng 		if (pdp->pd_check != NULL) {
43108453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
431111878SVenu.Iyer@Sun.COM 			    aip->ai_count, flags, vdp, 0);
43128275SEric Cheng 		} else {
43138275SEric Cheng 			status = DLADM_STATUS_BADARG;
43148275SEric Cheng 		}
43158275SEric Cheng 
43168275SEric Cheng 		if (status != DLADM_STATUS_OK)
43178275SEric Cheng 			return (status);
43188275SEric Cheng 
43198275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
43208275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
43218275SEric Cheng 
43228275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
43238275SEric Cheng 				continue;
43248275SEric Cheng 
43258275SEric Cheng 			/* Extract kernel structure */
43268275SEric Cheng 			if (rpp->rp_extract != NULL) {
432710734SEric Cheng 				status = rpp->rp_extract(vdp,
432810734SEric Cheng 				    aip->ai_count, arg);
43298275SEric Cheng 			} else {
43308275SEric Cheng 				status = DLADM_STATUS_BADARG;
43318275SEric Cheng 			}
43328275SEric Cheng 			break;
43338275SEric Cheng 		}
43348275SEric Cheng 
43358275SEric Cheng 		if (status != DLADM_STATUS_OK)
43368275SEric Cheng 			return (status);
43378275SEric Cheng 
43388275SEric Cheng 		break;
43398275SEric Cheng 	}
43408275SEric Cheng 	return (status);
43418275SEric Cheng }
43428275SEric Cheng 
43438275SEric Cheng /*
43448275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
43458275SEric Cheng  */
43468275SEric Cheng dladm_status_t
43478453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
434811878SVenu.Iyer@Sun.COM     mac_resource_props_t *mrp, uint_t flags)
43498275SEric Cheng {
435010734SEric Cheng 	dladm_status_t	status;
435110734SEric Cheng 	int		i;
435210734SEric Cheng 
435310734SEric Cheng 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
435410734SEric Cheng 		status = i_dladm_link_proplist_extract_one(handle,
435511878SVenu.Iyer@Sun.COM 		    proplist, rsrc_prop_table[i].rp_name, flags, mrp);
435610734SEric Cheng 		if (status != DLADM_STATUS_OK)
435710734SEric Cheng 			return (status);
435810734SEric Cheng 	}
43598275SEric Cheng 	return (status);
43608275SEric Cheng }
43618275SEric Cheng 
43628275SEric Cheng static const char *
43638275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
43648275SEric Cheng {
43658275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
43668275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
43678275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
43688275SEric Cheng 	return (buf);
43698275SEric Cheng }
43708306SSowmini.Varadhan@Sun.COM 
43718306SSowmini.Varadhan@Sun.COM dladm_status_t
437211878SVenu.Iyer@Sun.COM dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
43738453SAnurag.Maskey@Sun.COM     link_state_t *state)
43748306SSowmini.Varadhan@Sun.COM {
43758306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
43768306SSowmini.Varadhan@Sun.COM 
437711878SVenu.Iyer@Sun.COM 	return (i_dladm_get_public_prop(handle, linkid, "state", 0,
437811878SVenu.Iyer@Sun.COM 	    &perms, state, sizeof (*state)));
43798306SSowmini.Varadhan@Sun.COM }
43808460SArtem.Kachitchkin@Sun.COM 
43818460SArtem.Kachitchkin@Sun.COM boolean_t
43828460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
43838460SArtem.Kachitchkin@Sun.COM {
43848460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
43858460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
43868460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
43878460SArtem.Kachitchkin@Sun.COM 		"name",
43888460SArtem.Kachitchkin@Sun.COM 		"class",
43898460SArtem.Kachitchkin@Sun.COM 		"media",
43908460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
43918460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
43928460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
43938460SArtem.Kachitchkin@Sun.COM 
43948460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
43958460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
43968460SArtem.Kachitchkin@Sun.COM 	};
43978460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
43988460SArtem.Kachitchkin@Sun.COM 	int		i;
43998460SArtem.Kachitchkin@Sun.COM 
44008460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
44018460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
44028460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
44038460SArtem.Kachitchkin@Sun.COM 			break;
44048460SArtem.Kachitchkin@Sun.COM 		}
44058460SArtem.Kachitchkin@Sun.COM 	}
44068460SArtem.Kachitchkin@Sun.COM 
44078460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
44088460SArtem.Kachitchkin@Sun.COM }
440911878SVenu.Iyer@Sun.COM 
441011878SVenu.Iyer@Sun.COM dladm_status_t
441111878SVenu.Iyer@Sun.COM dladm_linkprop_is_set(dladm_handle_t handle, datalink_id_t linkid,
441211878SVenu.Iyer@Sun.COM     dladm_prop_type_t type, const char *prop_name, boolean_t *is_set)
441311878SVenu.Iyer@Sun.COM {
441411878SVenu.Iyer@Sun.COM 	char		*buf, **propvals;
441511878SVenu.Iyer@Sun.COM 	uint_t		valcnt = DLADM_MAX_PROP_VALCNT;
441611878SVenu.Iyer@Sun.COM 	int		i;
441711878SVenu.Iyer@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
441811878SVenu.Iyer@Sun.COM 
441911878SVenu.Iyer@Sun.COM 	*is_set = B_FALSE;
442011878SVenu.Iyer@Sun.COM 
442111878SVenu.Iyer@Sun.COM 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
442211878SVenu.Iyer@Sun.COM 	    DLADM_MAX_PROP_VALCNT)) == NULL)
442311878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
442411878SVenu.Iyer@Sun.COM 
442511878SVenu.Iyer@Sun.COM 	propvals = (char **)(void *)buf;
442611878SVenu.Iyer@Sun.COM 	for (i = 0; i < valcnt; i++) {
442711878SVenu.Iyer@Sun.COM 		propvals[i] = buf +
442811878SVenu.Iyer@Sun.COM 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
442911878SVenu.Iyer@Sun.COM 		    i * DLADM_PROP_VAL_MAX;
443011878SVenu.Iyer@Sun.COM 	}
443111878SVenu.Iyer@Sun.COM 
443211878SVenu.Iyer@Sun.COM 	if (dladm_get_linkprop(handle, linkid, type, prop_name, propvals,
443311878SVenu.Iyer@Sun.COM 	    &valcnt) != DLADM_STATUS_OK) {
443411878SVenu.Iyer@Sun.COM 		goto done;
443511878SVenu.Iyer@Sun.COM 	}
443611878SVenu.Iyer@Sun.COM 
443711878SVenu.Iyer@Sun.COM 	if ((strcmp(prop_name, "pool") == 0) && (strlen(*propvals) != 0)) {
443811878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
443911878SVenu.Iyer@Sun.COM 	} else if ((strcmp(prop_name, "cpus") == 0) && (valcnt != 0)) {
444011878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
444111878SVenu.Iyer@Sun.COM 	} else if ((strcmp(prop_name, "_softmac") == 0) && (valcnt != 0) &&
444211878SVenu.Iyer@Sun.COM 	    (strcmp(propvals[0], "true") == 0)) {
444311878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
444411878SVenu.Iyer@Sun.COM 	}
444511878SVenu.Iyer@Sun.COM 
444611878SVenu.Iyer@Sun.COM done:
444711878SVenu.Iyer@Sun.COM 	if (buf != NULL)
444811878SVenu.Iyer@Sun.COM 		free(buf);
444911878SVenu.Iyer@Sun.COM 	return (status);
445011878SVenu.Iyer@Sun.COM }
445112163SRamaswamy.Tummala@Sun.COM 
445212163SRamaswamy.Tummala@Sun.COM /* ARGSUSED */
445312163SRamaswamy.Tummala@Sun.COM static dladm_status_t
445412163SRamaswamy.Tummala@Sun.COM get_linkmode_prop(dladm_handle_t handle, prop_desc_t *pdp,
445512163SRamaswamy.Tummala@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
445612163SRamaswamy.Tummala@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
445712163SRamaswamy.Tummala@Sun.COM {
445812163SRamaswamy.Tummala@Sun.COM 	char			*s;
445912163SRamaswamy.Tummala@Sun.COM 	uint32_t		v;
446012163SRamaswamy.Tummala@Sun.COM 	dladm_status_t		status;
446112163SRamaswamy.Tummala@Sun.COM 
446212163SRamaswamy.Tummala@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
446312163SRamaswamy.Tummala@Sun.COM 	    perm_flags, &v, sizeof (v));
446412163SRamaswamy.Tummala@Sun.COM 	if (status != DLADM_STATUS_OK)
446512163SRamaswamy.Tummala@Sun.COM 		return (status);
446612163SRamaswamy.Tummala@Sun.COM 
446712163SRamaswamy.Tummala@Sun.COM 	switch (v) {
4468*12303SRajkumar.Sivaprakasam@Sun.COM 	case DLADM_PART_CM_MODE:
446912163SRamaswamy.Tummala@Sun.COM 		s = "cm";
447012163SRamaswamy.Tummala@Sun.COM 		break;
4471*12303SRajkumar.Sivaprakasam@Sun.COM 	case DLADM_PART_UD_MODE:
447212163SRamaswamy.Tummala@Sun.COM 		s = "ud";
447312163SRamaswamy.Tummala@Sun.COM 		break;
447412163SRamaswamy.Tummala@Sun.COM 	default:
447512163SRamaswamy.Tummala@Sun.COM 		s = "";
447612163SRamaswamy.Tummala@Sun.COM 		break;
447712163SRamaswamy.Tummala@Sun.COM 	}
447812163SRamaswamy.Tummala@Sun.COM 	(void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s);
447912163SRamaswamy.Tummala@Sun.COM 
448012163SRamaswamy.Tummala@Sun.COM 	*val_cnt = 1;
448112163SRamaswamy.Tummala@Sun.COM 	return (DLADM_STATUS_OK);
448212163SRamaswamy.Tummala@Sun.COM }
4483