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 /*
22*11878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
233147Sxc151355  * Use is subject to license terms.
243147Sxc151355  */
253147Sxc151355 
263147Sxc151355 #include <stdlib.h>
273147Sxc151355 #include <strings.h>
283147Sxc151355 #include <errno.h>
293147Sxc151355 #include <ctype.h>
305895Syz147064 #include <stddef.h>
313448Sdh155122 #include <sys/types.h>
323147Sxc151355 #include <sys/stat.h>
333448Sdh155122 #include <sys/dld.h>
343448Sdh155122 #include <sys/zone.h>
353448Sdh155122 #include <fcntl.h>
363448Sdh155122 #include <unistd.h>
373448Sdh155122 #include <libdevinfo.h>
383448Sdh155122 #include <zone.h>
393871Syz147064 #include <libdllink.h>
403147Sxc151355 #include <libdladm_impl.h>
415895Syz147064 #include <libdlwlan_impl.h>
423871Syz147064 #include <libdlwlan.h>
435895Syz147064 #include <libdlvlan.h>
448275SEric Cheng #include <libdlvnic.h>
458275SEric Cheng #include <libintl.h>
463448Sdh155122 #include <dlfcn.h>
473448Sdh155122 #include <link.h>
485895Syz147064 #include <inet/wifi_ioctl.h>
495903Ssowmini #include <libdladm.h>
508275SEric Cheng #include <libdlstat.h>
515903Ssowmini #include <sys/param.h>
528275SEric Cheng #include <sys/debug.h>
538275SEric Cheng #include <sys/dld.h>
545903Ssowmini #include <inttypes.h>
555903Ssowmini #include <sys/ethernet.h>
5610616SSebastien.Roy@Sun.COM #include <inet/iptun.h>
577663SSowmini.Varadhan@Sun.COM #include <net/wpa.h>
587663SSowmini.Varadhan@Sun.COM #include <sys/sysmacros.h>
5910491SRishi.Srivatsavai@Sun.COM #include <sys/vlan.h>
6010491SRishi.Srivatsavai@Sun.COM #include <libdlbridge.h>
6110491SRishi.Srivatsavai@Sun.COM #include <stp_in.h>
62*11878SVenu.Iyer@Sun.COM #include <netinet/dhcp.h>
63*11878SVenu.Iyer@Sun.COM #include <netinet/dhcp6.h>
64*11878SVenu.Iyer@Sun.COM #include <net/if_types.h>
65*11878SVenu.Iyer@Sun.COM #include <libinetutil.h>
66*11878SVenu.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,
114*11878SVenu.Iyer@Sun.COM 			    uint_t flags, val_desc_t *propval,
115*11878SVenu.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 
123*11878SVenu.Iyer@Sun.COM typedef struct dladm_linkprop_args_s {
124*11878SVenu.Iyer@Sun.COM 	dladm_status_t	dla_status;
125*11878SVenu.Iyer@Sun.COM 	uint_t		dla_flags;
126*11878SVenu.Iyer@Sun.COM } dladm_linkprop_args_t;
127*11878SVenu.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 *);
132*11878SVenu.Iyer@Sun.COM static dladm_status_t	i_dladm_get_public_prop(dladm_handle_t, datalink_id_t,
133*11878SVenu.Iyer@Sun.COM 			    char *, uint_t, uint_t *, void *, size_t);
134*11878SVenu.Iyer@Sun.COM 
135*11878SVenu.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);
137*11878SVenu.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 *);
142*11878SVenu.Iyer@Sun.COM static link_attr_t	*dladm_name2prop(const char *);
143*11878SVenu.Iyer@Sun.COM static link_attr_t	*dladm_id2prop(mac_prop_id_t);
144*11878SVenu.Iyer@Sun.COM 
145*11878SVenu.Iyer@Sun.COM static pd_getf_t	get_zone, get_autopush, get_rate_mod, get_rate,
146*11878SVenu.Iyer@Sun.COM 			get_speed, get_channel, get_powermode, get_radio,
147*11878SVenu.Iyer@Sun.COM 			get_duplex, get_link_state, get_binary, get_uint32,
148*11878SVenu.Iyer@Sun.COM 			get_flowctl, get_maxbw, get_cpus, get_priority,
149*11878SVenu.Iyer@Sun.COM 			get_tagmode, get_range, get_stp, get_bridge_forward,
150*11878SVenu.Iyer@Sun.COM 			get_bridge_pvid, get_protection, get_rxrings,
151*11878SVenu.Iyer@Sun.COM 			get_txrings, get_cntavail,
152*11878SVenu.Iyer@Sun.COM 			get_allowedips, get_allowedcids, get_pool,
153*11878SVenu.Iyer@Sun.COM 			get_rings_range;
154*11878SVenu.Iyer@Sun.COM 
155*11878SVenu.Iyer@Sun.COM static pd_setf_t	set_zone, set_rate, set_powermode, set_radio,
156*11878SVenu.Iyer@Sun.COM 			set_public_prop, set_resource, set_stp_prop,
157*11878SVenu.Iyer@Sun.COM 			set_bridge_forward, set_bridge_pvid;
158*11878SVenu.Iyer@Sun.COM 
159*11878SVenu.Iyer@Sun.COM static pd_checkf_t	check_zone, check_autopush, check_rate, check_hoplimit,
160*11878SVenu.Iyer@Sun.COM 			check_encaplim, check_uint32, check_maxbw, check_cpus,
161*11878SVenu.Iyer@Sun.COM 			check_stp_prop, check_bridge_pvid, check_allowedips,
162*11878SVenu.Iyer@Sun.COM 			check_allowedcids, check_rings,
163*11878SVenu.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 
344*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RESOURCE,	sizeof (mac_resource_props_t),	"resource"},
345*11878SVenu.Iyer@Sun.COM 
346*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RESOURCE_EFF, sizeof (mac_resource_props_t),
347*11878SVenu.Iyer@Sun.COM 	    "resource-effective"},
348*11878SVenu.Iyer@Sun.COM 
349*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_RXRINGSRANGE, sizeof (mac_propval_range_t),	"rxrings"},
350*11878SVenu.Iyer@Sun.COM 
351*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_TXRINGSRANGE, sizeof (mac_propval_range_t),	"txrings"},
352*11878SVenu.Iyer@Sun.COM 
353*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_TX_RINGS_AVAIL,	sizeof (uint_t),
354*11878SVenu.Iyer@Sun.COM 	    "txrings-available"},
355*11878SVenu.Iyer@Sun.COM 
356*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_RX_RINGS_AVAIL,	sizeof (uint_t),
357*11878SVenu.Iyer@Sun.COM 	    "rxrings-available"},
358*11878SVenu.Iyer@Sun.COM 
359*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_RXHWCLNT_AVAIL,	sizeof (uint_t), "rxhwclnt-available"},
360*11878SVenu.Iyer@Sun.COM 
361*11878SVenu.Iyer@Sun.COM 	{ MAC_PROP_MAX_TXHWCLNT_AVAIL,	sizeof (uint_t), "txhwclnt-available"},
36210734SEric Cheng 
3637663SSowmini.Varadhan@Sun.COM 	{ MAC_PROP_PRIVATE,	0,			"driver-private"}
3645903Ssowmini };
3655903Ssowmini 
36610491SRishi.Srivatsavai@Sun.COM typedef struct bridge_public_prop_s {
36710491SRishi.Srivatsavai@Sun.COM 	const char	*bpp_name;
36810491SRishi.Srivatsavai@Sun.COM 	int		bpp_code;
36910491SRishi.Srivatsavai@Sun.COM } bridge_public_prop_t;
37010491SRishi.Srivatsavai@Sun.COM 
37110491SRishi.Srivatsavai@Sun.COM static const bridge_public_prop_t bridge_prop[] = {
37210491SRishi.Srivatsavai@Sun.COM 	{ "stp", PT_CFG_NON_STP },
37310491SRishi.Srivatsavai@Sun.COM 	{ "stp_priority", PT_CFG_PRIO },
37410491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", PT_CFG_COST },
37510491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", PT_CFG_EDGE },
37610491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", PT_CFG_P2P },
37710491SRishi.Srivatsavai@Sun.COM 	{ "stp_mcheck", PT_CFG_MCHECK },
37810491SRishi.Srivatsavai@Sun.COM 	{ NULL, 0 }
37910491SRishi.Srivatsavai@Sun.COM };
38010491SRishi.Srivatsavai@Sun.COM 
3815903Ssowmini static  val_desc_t	link_duplex_vals[] = {
3825903Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
3835903Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
3845903Ssowmini };
3855903Ssowmini static  val_desc_t	link_status_vals[] = {
3865903Ssowmini 	{ "up",		LINK_STATE_UP		},
3875903Ssowmini 	{ "down",	LINK_STATE_DOWN		}
3885903Ssowmini };
3895903Ssowmini static  val_desc_t	link_01_vals[] = {
3905903Ssowmini 	{ "1",		1			},
3915903Ssowmini 	{ "0",		0			}
3925903Ssowmini };
3935903Ssowmini static  val_desc_t	link_flow_vals[] = {
3945903Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
3955903Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
3965903Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
3975903Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
3985903Ssowmini };
3998275SEric Cheng static  val_desc_t	link_priority_vals[] = {
4008275SEric Cheng 	{ "low",	MPL_LOW	},
4018275SEric Cheng 	{ "medium",	MPL_MEDIUM	},
4028275SEric Cheng 	{ "high",	MPL_HIGH	}
4038275SEric Cheng };
4045903Ssowmini 
4058874SSebastien.Roy@Sun.COM static val_desc_t	link_tagmode_vals[] = {
4068874SSebastien.Roy@Sun.COM 	{ "normal",	LINK_TAGMODE_NORMAL	},
4078874SSebastien.Roy@Sun.COM 	{ "vlanonly",	LINK_TAGMODE_VLANONLY	}
4088874SSebastien.Roy@Sun.COM };
4098874SSebastien.Roy@Sun.COM 
41010734SEric Cheng static  val_desc_t	link_protect_vals[] = {
41110734SEric Cheng 	{ "mac-nospoof",	MPT_MACNOSPOOF	},
412*11878SVenu.Iyer@Sun.COM 	{ "restricted",		MPT_RESTRICTED	},
41310734SEric Cheng 	{ "ip-nospoof",		MPT_IPNOSPOOF	},
414*11878SVenu.Iyer@Sun.COM 	{ "dhcp-nospoof",	MPT_DHCPNOSPOOF	},
41510734SEric Cheng };
41610734SEric Cheng 
4175895Syz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
4185895Syz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
4195895Syz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
4205895Syz147064 };
4215895Syz147064 
4225895Syz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
4235895Syz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
4245895Syz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
4255895Syz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
4265895Syz147064 };
4275895Syz147064 
42810491SRishi.Srivatsavai@Sun.COM static  val_desc_t	stp_p2p_vals[] = {
42910491SRishi.Srivatsavai@Sun.COM 	{ "true",	P2P_FORCE_TRUE		},
43010491SRishi.Srivatsavai@Sun.COM 	{ "false",	P2P_FORCE_FALSE		},
43110491SRishi.Srivatsavai@Sun.COM 	{ "auto",	P2P_AUTO		}
43210491SRishi.Srivatsavai@Sun.COM };
43310491SRishi.Srivatsavai@Sun.COM 
4348275SEric Cheng #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
4358275SEric Cheng #define	RESET_VAL	((uintptr_t)-1)
436*11878SVenu.Iyer@Sun.COM #define	UNSPEC_VAL	((uintptr_t)-2)
4378275SEric Cheng 
4383448Sdh155122 static prop_desc_t	prop_table[] = {
4395903Ssowmini 	{ "channel",	{ NULL, 0 },
4405903Ssowmini 	    NULL, 0, NULL, NULL,
441*11878SVenu.Iyer@Sun.COM 	    get_channel, NULL, 0,
4425903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4435895Syz147064 
4445895Syz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
4455895Syz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
446*11878SVenu.Iyer@Sun.COM 	    set_powermode, NULL,
447*11878SVenu.Iyer@Sun.COM 	    get_powermode, NULL, 0,
4485903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4495895Syz147064 
4505895Syz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
4515895Syz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
452*11878SVenu.Iyer@Sun.COM 	    set_radio, NULL,
453*11878SVenu.Iyer@Sun.COM 	    get_radio, NULL, 0,
4545903Ssowmini 	    DATALINK_CLASS_PHYS, DL_WIFI },
4555895Syz147064 
4565895Syz147064 	{ "speed",	{ "", 0 }, NULL, 0,
457*11878SVenu.Iyer@Sun.COM 	    set_rate, get_rate_mod,
458*11878SVenu.Iyer@Sun.COM 	    get_rate, check_rate, 0,
4595960Ssowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
4605895Syz147064 
4616512Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
462*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL,
463*11878SVenu.Iyer@Sun.COM 	    get_autopush, check_autopush, PD_CHECK_ALLOC,
4645903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4655895Syz147064 
4666512Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
467*11878SVenu.Iyer@Sun.COM 	    set_zone, NULL,
468*11878SVenu.Iyer@Sun.COM 	    get_zone, check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
4695903Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4705903Ssowmini 
4718275SEric Cheng 	{ "duplex",	{ "", 0 },
4725903Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
473*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_duplex, NULL,
4745903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4755903Ssowmini 
4768275SEric Cheng 	{ "state",	{ "up", LINK_STATE_UP },
4775903Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
478*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_link_state, NULL,
4796512Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
4805903Ssowmini 
48110191SSowmini.Varadhan@Sun.COM 	{ "adv_autoneg_cap", { "", 0 },
4825903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
483*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
4845903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4855903Ssowmini 
4866512Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
487*11878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range,
488*11878SVenu.Iyer@Sun.COM 	    get_uint32, check_uint32, 0, DATALINK_CLASS_ALL,
4897342SAruna.Ramakrishna@Sun.COM 	    DATALINK_ANY_MEDIATYPE },
4905903Ssowmini 
4916512Ssowmini 	{ "flowctrl", { "", 0 },
4925903Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
493*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_flowctl, NULL,
4945903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
4955903Ssowmini 
4969449Sxiuyan.wang@Sun.COM 	{ "adv_10gfdx_cap", { "", 0 },
4979449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
498*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
4999449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5009449Sxiuyan.wang@Sun.COM 
5019449Sxiuyan.wang@Sun.COM 	{ "en_10gfdx_cap", { "", 0 },
5029449Sxiuyan.wang@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
503*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5049449Sxiuyan.wang@Sun.COM 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5059449Sxiuyan.wang@Sun.COM 
5066512Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
5076512Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
508*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5095903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5105903Ssowmini 
5116512Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
5125903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
513*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5145903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5155903Ssowmini 
5166512Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
5175903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
518*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5195903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5205903Ssowmini 
5216512Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
5225903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
523*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5245903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5255903Ssowmini 
5266512Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
5275903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
528*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5295903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5305903Ssowmini 
5316512Ssowmini 	{ "en_100fdx_cap", { "", 0 },
5325903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
533*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5345903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5355903Ssowmini 
5366512Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
5375903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
538*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5395903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5405903Ssowmini 
5416512Ssowmini 	{ "en_100hdx_cap", { "", 0 },
5425903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
543*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5445903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5455903Ssowmini 
5466512Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
5475903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
548*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5495903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5505903Ssowmini 
5516512Ssowmini 	{ "en_10fdx_cap", { "", 0 },
5525903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
553*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5545903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5555903Ssowmini 
5566512Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
5575903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
558*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_binary, NULL,
5595903Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5605903Ssowmini 
5616512Ssowmini 	{ "en_10hdx_cap", { "", 0 },
5625903Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
563*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_binary, NULL,
5648275SEric Cheng 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
5658275SEric Cheng 
5668275SEric Cheng 	{ "maxbw", { "--", RESET_VAL }, NULL, 0,
567*11878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
568*11878SVenu.Iyer@Sun.COM 	    get_maxbw, check_maxbw, PD_CHECK_ALLOC,
5698275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5708275SEric Cheng 
5718275SEric Cheng 	{ "cpus", { "--", RESET_VAL }, NULL, 0,
572*11878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
573*11878SVenu.Iyer@Sun.COM 	    get_cpus, check_cpus, 0,
574*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
575*11878SVenu.Iyer@Sun.COM 
576*11878SVenu.Iyer@Sun.COM 	{ "cpus-effective", { "--", 0 },
577*11878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
578*11878SVenu.Iyer@Sun.COM 	    get_cpus, 0, 0,
5798275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5808275SEric Cheng 
581*11878SVenu.Iyer@Sun.COM 	{ "pool", { "--", RESET_VAL }, NULL, 0,
582*11878SVenu.Iyer@Sun.COM 	    set_resource, NULL,
583*11878SVenu.Iyer@Sun.COM 	    get_pool, check_pool, 0,
584*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
585*11878SVenu.Iyer@Sun.COM 
586*11878SVenu.Iyer@Sun.COM 	{ "pool-effective", { "--", 0 },
587*11878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
588*11878SVenu.Iyer@Sun.COM 	    get_pool, 0, 0,
589*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
590*11878SVenu.Iyer@Sun.COM 
591*11878SVenu.Iyer@Sun.COM 	{ "priority", { "high", MPL_RESET },
592*11878SVenu.Iyer@Sun.COM 	    link_priority_vals, VALCNT(link_priority_vals), set_resource,
593*11878SVenu.Iyer@Sun.COM 	    NULL, get_priority, check_prop, 0,
5948275SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
5958874SSebastien.Roy@Sun.COM 
5968874SSebastien.Roy@Sun.COM 	{ "tagmode", { "vlanonly", LINK_TAGMODE_VLANONLY },
5978874SSebastien.Roy@Sun.COM 	    link_tagmode_vals, VALCNT(link_tagmode_vals),
598*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_tagmode,
5998874SSebastien.Roy@Sun.COM 	    NULL, 0,
6008874SSebastien.Roy@Sun.COM 	    DATALINK_CLASS_PHYS | DATALINK_CLASS_AGGR | DATALINK_CLASS_VNIC,
60110491SRishi.Srivatsavai@Sun.COM 	    DL_ETHER },
60210491SRishi.Srivatsavai@Sun.COM 
60310616SSebastien.Roy@Sun.COM 	{ "hoplimit", { "", 0 }, NULL, 0,
604*11878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range, get_uint32,
605*11878SVenu.Iyer@Sun.COM 	    check_hoplimit, 0, DATALINK_CLASS_IPTUN, DATALINK_ANY_MEDIATYPE},
60610616SSebastien.Roy@Sun.COM 
60710616SSebastien.Roy@Sun.COM 	{ "encaplimit", { "", 0 }, NULL, 0,
608*11878SVenu.Iyer@Sun.COM 	    set_public_prop, get_range, get_uint32,
609*11878SVenu.Iyer@Sun.COM 	    check_encaplim, 0, DATALINK_CLASS_IPTUN, DL_IPV6},
61010616SSebastien.Roy@Sun.COM 
61110491SRishi.Srivatsavai@Sun.COM 	{ "forward", { "1", 1 },
61210491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
61310491SRishi.Srivatsavai@Sun.COM 	    set_bridge_forward, NULL, get_bridge_forward, NULL, PD_AFTER_PERM,
61410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ALL & ~DATALINK_CLASS_VNIC, DL_ETHER },
61510491SRishi.Srivatsavai@Sun.COM 
61610491SRishi.Srivatsavai@Sun.COM 	{ "default_tag", { "1", 1 }, NULL, 0,
61710491SRishi.Srivatsavai@Sun.COM 	    set_bridge_pvid, NULL, get_bridge_pvid, check_bridge_pvid,
61810491SRishi.Srivatsavai@Sun.COM 	    0, DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
61910491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
62010491SRishi.Srivatsavai@Sun.COM 
62110491SRishi.Srivatsavai@Sun.COM 	{ "learn_limit", { "1000", 1000 }, NULL, 0,
622*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_uint32,
623*11878SVenu.Iyer@Sun.COM 	    check_uint32, 0,
62410491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
62510491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
62610491SRishi.Srivatsavai@Sun.COM 
62710491SRishi.Srivatsavai@Sun.COM 	{ "learn_decay", { "200", 200 }, NULL, 0,
628*11878SVenu.Iyer@Sun.COM 	    set_public_prop, NULL, get_uint32,
629*11878SVenu.Iyer@Sun.COM 	    check_uint32, 0,
63010491SRishi.Srivatsavai@Sun.COM 	    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 	{ "stp", { "1", 1 },
63410491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
635*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
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 	{ "stp_priority", { "128", 128 }, NULL, 0,
640*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
64110491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
64210491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
64310491SRishi.Srivatsavai@Sun.COM 
64410491SRishi.Srivatsavai@Sun.COM 	{ "stp_cost", { "auto", 0 }, NULL, 0,
645*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, PD_AFTER_PERM,
64610491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
64710491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
64810491SRishi.Srivatsavai@Sun.COM 
64910491SRishi.Srivatsavai@Sun.COM 	{ "stp_edge", { "1", 1 },
65010491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
651*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, PD_AFTER_PERM,
65210491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_PHYS|DATALINK_CLASS_AGGR|
65310491SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_ETHERSTUB|DATALINK_CLASS_SIMNET, DL_ETHER },
65410491SRishi.Srivatsavai@Sun.COM 
65510491SRishi.Srivatsavai@Sun.COM 	{ "stp_p2p", { "auto", P2P_AUTO },
65610491SRishi.Srivatsavai@Sun.COM 	    stp_p2p_vals, VALCNT(stp_p2p_vals),
657*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, NULL, 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_mcheck", { "0", 0 },
66210491SRishi.Srivatsavai@Sun.COM 	    link_01_vals, VALCNT(link_01_vals),
663*11878SVenu.Iyer@Sun.COM 	    set_stp_prop, NULL, get_stp, check_stp_prop, 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 },
66610734SEric Cheng 
66710734SEric Cheng 	{ "protection", { "--", RESET_VAL },
66810734SEric Cheng 	    link_protect_vals, VALCNT(link_protect_vals),
669*11878SVenu.Iyer@Sun.COM 	    set_resource, NULL, get_protection, check_prop, 0,
67010734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
67110734SEric Cheng 
67210734SEric Cheng 	{ "allowed-ips", { "--", 0 },
673*11878SVenu.Iyer@Sun.COM 	    NULL, 0, set_resource, NULL,
674*11878SVenu.Iyer@Sun.COM 	    get_allowedips, check_allowedips, PD_CHECK_ALLOC,
675*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
676*11878SVenu.Iyer@Sun.COM 
677*11878SVenu.Iyer@Sun.COM 	{ "allowed-dhcp-cids", { "--", 0 },
678*11878SVenu.Iyer@Sun.COM 	    NULL, 0, set_resource, NULL,
679*11878SVenu.Iyer@Sun.COM 	    get_allowedcids, check_allowedcids, PD_CHECK_ALLOC,
680*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
681*11878SVenu.Iyer@Sun.COM 
682*11878SVenu.Iyer@Sun.COM 	{ "rxrings", { "--", RESET_VAL }, NULL, 0,
683*11878SVenu.Iyer@Sun.COM 	    set_resource, get_rings_range, get_rxrings, check_rings, 0,
684*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
685*11878SVenu.Iyer@Sun.COM 
686*11878SVenu.Iyer@Sun.COM 	{ "rxrings-effective", { "--", 0 },
687*11878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
688*11878SVenu.Iyer@Sun.COM 	    get_rxrings, NULL, 0,
689*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
690*11878SVenu.Iyer@Sun.COM 
691*11878SVenu.Iyer@Sun.COM 	{ "txrings", { "--", RESET_VAL }, NULL, 0,
692*11878SVenu.Iyer@Sun.COM 	    set_resource, get_rings_range, get_txrings, check_rings, 0,
69310734SEric Cheng 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
694*11878SVenu.Iyer@Sun.COM 
695*11878SVenu.Iyer@Sun.COM 	{ "txrings-effective", { "--", 0 },
696*11878SVenu.Iyer@Sun.COM 	    NULL, 0, NULL, NULL,
697*11878SVenu.Iyer@Sun.COM 	    get_txrings, NULL, 0,
698*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
699*11878SVenu.Iyer@Sun.COM 
700*11878SVenu.Iyer@Sun.COM 	{ "txrings-available", { "", 0 }, NULL, 0,
701*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
702*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
703*11878SVenu.Iyer@Sun.COM 
704*11878SVenu.Iyer@Sun.COM 	{ "rxrings-available", { "", 0 }, NULL, 0,
705*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
706*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
707*11878SVenu.Iyer@Sun.COM 
708*11878SVenu.Iyer@Sun.COM 	{ "rxhwclnt-available", { "", 0 }, NULL, 0,
709*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
710*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
711*11878SVenu.Iyer@Sun.COM 
712*11878SVenu.Iyer@Sun.COM 	{ "txhwclnt-available", { "", 0 }, NULL, 0,
713*11878SVenu.Iyer@Sun.COM 	    NULL, NULL, get_cntavail, NULL, 0,
714*11878SVenu.Iyer@Sun.COM 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
715*11878SVenu.Iyer@Sun.COM 
7163448Sdh155122 };
7173448Sdh155122 
7185895Syz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
7195895Syz147064 
7208275SEric Cheng static resource_prop_t rsrc_prop_table[] = {
721*11878SVenu.Iyer@Sun.COM 	{"maxbw",		extract_maxbw},
722*11878SVenu.Iyer@Sun.COM 	{"priority",		extract_priority},
723*11878SVenu.Iyer@Sun.COM 	{"cpus",		extract_cpus},
724*11878SVenu.Iyer@Sun.COM 	{"cpus-effective",	extract_cpus},
725*11878SVenu.Iyer@Sun.COM 	{"pool",		extract_pool},
726*11878SVenu.Iyer@Sun.COM 	{"pool-effective",	extract_pool},
727*11878SVenu.Iyer@Sun.COM 	{"protection",		extract_protection},
728*11878SVenu.Iyer@Sun.COM 	{"allowed-ips",		extract_allowedips},
729*11878SVenu.Iyer@Sun.COM 	{"allowed-dhcp-cids",	extract_allowedcids},
730*11878SVenu.Iyer@Sun.COM 	{"rxrings",		extract_rxrings},
731*11878SVenu.Iyer@Sun.COM 	{"rxrings-effective",	extract_rxrings},
732*11878SVenu.Iyer@Sun.COM 	{"txrings",		extract_txrings},
733*11878SVenu.Iyer@Sun.COM 	{"txrings-effective",	extract_txrings}
7348275SEric Cheng };
7358275SEric Cheng #define	DLADM_MAX_RSRC_PROP (sizeof (rsrc_prop_table) / \
7368275SEric Cheng 	sizeof (resource_prop_t))
7378275SEric Cheng 
7387663SSowmini.Varadhan@Sun.COM /*
7397663SSowmini.Varadhan@Sun.COM  * when retrieving  private properties, we pass down a buffer with
7407663SSowmini.Varadhan@Sun.COM  * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value.
7417663SSowmini.Varadhan@Sun.COM  */
7427663SSowmini.Varadhan@Sun.COM #define	DLADM_PROP_BUF_CHUNK	1024
7437663SSowmini.Varadhan@Sun.COM 
7448453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop_db(dladm_handle_t, datalink_id_t,
7458453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t);
7468453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_get_linkprop_db(dladm_handle_t, datalink_id_t,
7478453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t *);
7488460SArtem.Kachitchkin@Sun.COM static dladm_status_t	i_dladm_walk_linkprop_priv_db(dladm_handle_t,
7498460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, void *, int (*)(dladm_handle_t,
7508460SArtem.Kachitchkin@Sun.COM 			    datalink_id_t, const char *, void *));
7518453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_single_prop(dladm_handle_t, datalink_id_t,
7528453SAnurag.Maskey@Sun.COM 			    datalink_class_t, uint32_t, prop_desc_t *, char **,
7538453SAnurag.Maskey@Sun.COM 			    uint_t, uint_t);
7548453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_set_linkprop(dladm_handle_t, datalink_id_t,
7558453SAnurag.Maskey@Sun.COM 			    const char *, char **, uint_t, uint_t);
7568453SAnurag.Maskey@Sun.COM static dladm_status_t	i_dladm_getset_defval(dladm_handle_t, prop_desc_t *,
7578453SAnurag.Maskey@Sun.COM 			    datalink_id_t, datalink_media_t, uint_t);
7588275SEric Cheng 
7595895Syz147064 /*
7605895Syz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
7615895Syz147064  * rates to be retrieved. However, we cannot increase it at this
7625895Syz147064  * time because it will break binary compatibility with unbundled
7635895Syz147064  * WiFi drivers and utilities. So for now we define an additional
7645895Syz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
7655895Syz147064  */
7665895Syz147064 #define	MAX_SUPPORT_RATES	64
7675895Syz147064 
7685895Syz147064 #define	AP_ANCHOR	"[anchor]"
7695895Syz147064 #define	AP_DELIMITER	'.'
7705895Syz147064 
77110734SEric Cheng /* ARGSUSED */
7725895Syz147064 static dladm_status_t
773*11878SVenu.Iyer@Sun.COM check_prop(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
774*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
775*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
7765895Syz147064 {
7775895Syz147064 	int		i, j;
7783147Sxc151355 
7795895Syz147064 	for (j = 0; j < val_cnt; j++) {
7805895Syz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
78110734SEric Cheng 			if (strcasecmp(prop_val[j],
7825895Syz147064 			    pdp->pd_optval[i].vd_name) == 0) {
7835895Syz147064 				break;
7845895Syz147064 			}
7855895Syz147064 		}
78610734SEric Cheng 		if (i == pdp->pd_noptval)
78710734SEric Cheng 			return (DLADM_STATUS_BADVAL);
78810734SEric Cheng 
78910734SEric Cheng 		(void) memcpy(&vdp[j], &pdp->pd_optval[i], sizeof (val_desc_t));
7905895Syz147064 	}
79110734SEric Cheng 	return (DLADM_STATUS_OK);
7925895Syz147064 }
7935895Syz147064 
7945895Syz147064 static dladm_status_t
7958453SAnurag.Maskey@Sun.COM i_dladm_set_single_prop(dladm_handle_t handle, datalink_id_t linkid,
7968453SAnurag.Maskey@Sun.COM     datalink_class_t class, uint32_t media, prop_desc_t *pdp, char **prop_val,
7978453SAnurag.Maskey@Sun.COM     uint_t val_cnt, uint_t flags)
7983147Sxc151355 {
7995895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
8005895Syz147064 	val_desc_t	*vdp = NULL;
8015895Syz147064 	boolean_t	needfree = B_FALSE;
8025895Syz147064 	uint_t		cnt, i;
8033147Sxc151355 
8045895Syz147064 	if (!(pdp->pd_class & class))
8055895Syz147064 		return (DLADM_STATUS_BADARG);
8065895Syz147064 
8075895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
8083147Sxc151355 		return (DLADM_STATUS_BADARG);
8093147Sxc151355 
8105895Syz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
8115895Syz147064 		return (DLADM_STATUS_TEMPONLY);
8125895Syz147064 
8135895Syz147064 	if (!(flags & DLADM_OPT_ACTIVE))
8145895Syz147064 		return (DLADM_STATUS_OK);
8155895Syz147064 
8165895Syz147064 	if (pdp->pd_set == NULL)
8175895Syz147064 		return (DLADM_STATUS_PROPRDONLY);
8183448Sdh155122 
8195895Syz147064 	if (prop_val != NULL) {
820*11878SVenu.Iyer@Sun.COM 		vdp = calloc(val_cnt, sizeof (val_desc_t));
8215895Syz147064 		if (vdp == NULL)
8225895Syz147064 			return (DLADM_STATUS_NOMEM);
8235895Syz147064 
8245895Syz147064 		if (pdp->pd_check != NULL) {
8258275SEric Cheng 			needfree = ((pdp->pd_flags & PD_CHECK_ALLOC) != 0);
8268453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, linkid, prop_val,
827*11878SVenu.Iyer@Sun.COM 			    val_cnt, flags, vdp, media);
8285895Syz147064 		} else if (pdp->pd_optval != NULL) {
829*11878SVenu.Iyer@Sun.COM 			status = check_prop(handle, pdp, linkid, prop_val,
830*11878SVenu.Iyer@Sun.COM 			    val_cnt, flags, vdp, media);
8315895Syz147064 		} else {
8323448Sdh155122 			status = DLADM_STATUS_BADARG;
8333147Sxc151355 		}
8345895Syz147064 
8353147Sxc151355 		if (status != DLADM_STATUS_OK)
8365895Syz147064 			goto done;
8375895Syz147064 
8385895Syz147064 		cnt = val_cnt;
8395895Syz147064 	} else {
8408275SEric Cheng 		boolean_t	defval = B_FALSE;
8418275SEric Cheng 
8425895Syz147064 		if (pdp->pd_defval.vd_name == NULL)
8435895Syz147064 			return (DLADM_STATUS_NOTSUP);
8445895Syz147064 
8457342SAruna.Ramakrishna@Sun.COM 		cnt = 1;
8468275SEric Cheng 		defval = (strlen(pdp->pd_defval.vd_name) > 0);
8478275SEric Cheng 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 || defval) {
848*11878SVenu.Iyer@Sun.COM 			if ((vdp = calloc(1, sizeof (val_desc_t))) == NULL)
8496512Ssowmini 				return (DLADM_STATUS_NOMEM);
8507342SAruna.Ramakrishna@Sun.COM 
8518275SEric Cheng 			if (defval) {
8528275SEric Cheng 				(void) memcpy(vdp, &pdp->pd_defval,
8538275SEric Cheng 				    sizeof (val_desc_t));
8548275SEric Cheng 			} else if (pdp->pd_check != NULL) {
8558453SAnurag.Maskey@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
856*11878SVenu.Iyer@Sun.COM 				    prop_val, cnt, flags, vdp, media);
8577342SAruna.Ramakrishna@Sun.COM 				if (status != DLADM_STATUS_OK)
8587342SAruna.Ramakrishna@Sun.COM 					goto done;
8597342SAruna.Ramakrishna@Sun.COM 			}
8606512Ssowmini 		} else {
8618453SAnurag.Maskey@Sun.COM 			status = i_dladm_getset_defval(handle, pdp, linkid,
8626512Ssowmini 			    media, flags);
8636512Ssowmini 			return (status);
8646512Ssowmini 		}
8655895Syz147064 	}
86610491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_AFTER_PERM)
86710491SRishi.Srivatsavai@Sun.COM 		status = (flags & DLADM_OPT_PERSIST) ? DLADM_STATUS_OK :
86810491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_PERMONLY;
86910491SRishi.Srivatsavai@Sun.COM 	else
87010491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_set(handle, pdp, linkid, vdp, cnt, flags,
87110491SRishi.Srivatsavai@Sun.COM 		    media);
8725895Syz147064 	if (needfree) {
8735895Syz147064 		for (i = 0; i < cnt; i++)
8745903Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
8753147Sxc151355 	}
8765895Syz147064 done:
8775895Syz147064 	free(vdp);
8785895Syz147064 	return (status);
8795895Syz147064 }
8805895Syz147064 
8815895Syz147064 static dladm_status_t
8828453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
8838453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
8845895Syz147064 {
8855895Syz147064 	int			i;
8865895Syz147064 	boolean_t		found = B_FALSE;
8875895Syz147064 	datalink_class_t	class;
8885895Syz147064 	uint32_t		media;
8895895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
8905895Syz147064 
8918453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
8928453SAnurag.Maskey@Sun.COM 	    NULL, 0);
8935895Syz147064 	if (status != DLADM_STATUS_OK)
8945895Syz147064 		return (status);
8955895Syz147064 
8965895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
8975895Syz147064 		prop_desc_t	*pdp = &prop_table[i];
8985895Syz147064 		dladm_status_t	s;
8995895Syz147064 
9005895Syz147064 		if (prop_name != NULL &&
9015895Syz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
9025895Syz147064 			continue;
9035895Syz147064 		found = B_TRUE;
9048453SAnurag.Maskey@Sun.COM 		s = i_dladm_set_single_prop(handle, linkid, class, media, pdp,
9058453SAnurag.Maskey@Sun.COM 		    prop_val, val_cnt, flags);
9063448Sdh155122 
9075895Syz147064 		if (prop_name != NULL) {
9085895Syz147064 			status = s;
9095895Syz147064 			break;
9105895Syz147064 		} else {
9115895Syz147064 			if (s != DLADM_STATUS_OK &&
9125895Syz147064 			    s != DLADM_STATUS_NOTSUP)
9135895Syz147064 				status = s;
9145895Syz147064 		}
9155895Syz147064 	}
9165903Ssowmini 	if (!found) {
9175903Ssowmini 		if (prop_name[0] == '_') {
9185903Ssowmini 			/* other private properties */
9199692SRishi.Srivatsavai@Sun.COM 			status = i_dladm_set_private_prop(handle, linkid,
9209692SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cnt, flags);
9215903Ssowmini 		} else  {
9225903Ssowmini 			status = DLADM_STATUS_NOTFOUND;
9235903Ssowmini 		}
9245903Ssowmini 	}
9255895Syz147064 	return (status);
9265895Syz147064 }
9275895Syz147064 
9285895Syz147064 /*
9295895Syz147064  * Set/reset link property for specific link
9305895Syz147064  */
9315895Syz147064 dladm_status_t
9328453SAnurag.Maskey@Sun.COM dladm_set_linkprop(dladm_handle_t handle, datalink_id_t linkid,
9338453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
9345895Syz147064 {
9355895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
9365895Syz147064 
9375895Syz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
9385895Syz147064 	    (prop_val == NULL && val_cnt > 0) ||
9395895Syz147064 	    (prop_val != NULL && val_cnt == 0) ||
9405895Syz147064 	    (prop_name == NULL && prop_val != NULL)) {
9415895Syz147064 		return (DLADM_STATUS_BADARG);
9425895Syz147064 	}
9435895Syz147064 
9449692SRishi.Srivatsavai@Sun.COM 	/*
9459692SRishi.Srivatsavai@Sun.COM 	 * Check for valid link property against the flags passed
9469692SRishi.Srivatsavai@Sun.COM 	 * and set the link property when active flag is passed.
9479692SRishi.Srivatsavai@Sun.COM 	 */
9488453SAnurag.Maskey@Sun.COM 	status = i_dladm_set_linkprop(handle, linkid, prop_name, prop_val,
9495895Syz147064 	    val_cnt, flags);
9505895Syz147064 	if (status != DLADM_STATUS_OK)
9515895Syz147064 		return (status);
9525895Syz147064 
9535895Syz147064 	if (flags & DLADM_OPT_PERSIST) {
9548453SAnurag.Maskey@Sun.COM 		status = i_dladm_set_linkprop_db(handle, linkid, prop_name,
9553147Sxc151355 		    prop_val, val_cnt);
95610491SRishi.Srivatsavai@Sun.COM 
95710491SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
95810491SRishi.Srivatsavai@Sun.COM 			prop_desc_t *pdp = prop_table;
95910491SRishi.Srivatsavai@Sun.COM 			int i;
96010491SRishi.Srivatsavai@Sun.COM 
96110491SRishi.Srivatsavai@Sun.COM 			for (i = 0; i < DLADM_MAX_PROPS; i++, pdp++) {
96210491SRishi.Srivatsavai@Sun.COM 				if (!(pdp->pd_flags & PD_AFTER_PERM))
96310491SRishi.Srivatsavai@Sun.COM 					continue;
96410491SRishi.Srivatsavai@Sun.COM 				if (prop_name != NULL &&
96510491SRishi.Srivatsavai@Sun.COM 				    strcasecmp(prop_name, pdp->pd_name) != 0)
96610491SRishi.Srivatsavai@Sun.COM 					continue;
96710491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_set(handle, pdp, linkid, NULL,
96810491SRishi.Srivatsavai@Sun.COM 				    0, flags, 0);
96910491SRishi.Srivatsavai@Sun.COM 			}
97010491SRishi.Srivatsavai@Sun.COM 		}
9713147Sxc151355 	}
9723147Sxc151355 	return (status);
9733147Sxc151355 }
9743147Sxc151355 
9755895Syz147064 /*
9768460SArtem.Kachitchkin@Sun.COM  * Walk all link properties of the given specific link.
9778460SArtem.Kachitchkin@Sun.COM  *
9788460SArtem.Kachitchkin@Sun.COM  * Note: this function currently lacks the ability to walk _all_ private
9798460SArtem.Kachitchkin@Sun.COM  * properties if the link, because there is no kernel interface to
9808460SArtem.Kachitchkin@Sun.COM  * retrieve all known private property names. Once such an interface
9818460SArtem.Kachitchkin@Sun.COM  * is added, this function should be fixed accordingly.
9825895Syz147064  */
9833147Sxc151355 dladm_status_t
9848453SAnurag.Maskey@Sun.COM dladm_walk_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg,
9858453SAnurag.Maskey@Sun.COM     int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
9863147Sxc151355 {
9875895Syz147064 	dladm_status_t		status;
9885895Syz147064 	datalink_class_t	class;
9895895Syz147064 	uint_t			media;
9905895Syz147064 	int			i;
9915895Syz147064 
9925895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
9935895Syz147064 		return (DLADM_STATUS_BADARG);
9945895Syz147064 
9958453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
9968453SAnurag.Maskey@Sun.COM 	    NULL, 0);
9975895Syz147064 	if (status != DLADM_STATUS_OK)
9985895Syz147064 		return (status);
9995895Syz147064 
10008460SArtem.Kachitchkin@Sun.COM 	/* public */
10015895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
10025895Syz147064 		if (!(prop_table[i].pd_class & class))
10035895Syz147064 			continue;
10045895Syz147064 
10055895Syz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
10065895Syz147064 			continue;
10075895Syz147064 
10088453SAnurag.Maskey@Sun.COM 		if (func(handle, linkid, prop_table[i].pd_name, arg) ==
10095895Syz147064 		    DLADM_WALK_TERMINATE) {
10105895Syz147064 			break;
10115895Syz147064 		}
10125895Syz147064 	}
10135895Syz147064 
10148460SArtem.Kachitchkin@Sun.COM 	/* private */
10158460SArtem.Kachitchkin@Sun.COM 	status = i_dladm_walk_linkprop_priv_db(handle, linkid, arg, func);
10168460SArtem.Kachitchkin@Sun.COM 
10178460SArtem.Kachitchkin@Sun.COM 	return (status);
10185895Syz147064 }
10193448Sdh155122 
10205895Syz147064 /*
10215895Syz147064  * Get linkprop of the given specific link.
10225895Syz147064  */
10235895Syz147064 dladm_status_t
10248453SAnurag.Maskey@Sun.COM dladm_get_linkprop(dladm_handle_t handle, datalink_id_t linkid,
10258453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, const char *prop_name, char **prop_val,
10268453SAnurag.Maskey@Sun.COM     uint_t *val_cntp)
10275895Syz147064 {
10285895Syz147064 	dladm_status_t		status = DLADM_STATUS_OK;
10295895Syz147064 	datalink_class_t	class;
10305895Syz147064 	uint_t			media;
10315895Syz147064 	prop_desc_t		*pdp;
10326512Ssowmini 	uint_t			cnt, dld_flags = 0;
10335895Syz147064 	int			i;
10348118SVasumathi.Sundaram@Sun.COM 	uint_t			perm_flags;
10355895Syz147064 
10366512Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
1037*11878SVenu.Iyer@Sun.COM 		dld_flags |= DLD_PROP_DEFAULT;
10389514SGirish.Moodalbail@Sun.COM 	else if (type == DLADM_PROP_VAL_MODIFIABLE)
1039*11878SVenu.Iyer@Sun.COM 		dld_flags |= DLD_PROP_POSSIBLE;
10406512Ssowmini 
10415895Syz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
10425895Syz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
10435895Syz147064 		return (DLADM_STATUS_BADARG);
10445895Syz147064 
10455895Syz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
10465895Syz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
10475895Syz147064 			break;
10485895Syz147064 
10495903Ssowmini 	if (i == DLADM_MAX_PROPS) {
10505903Ssowmini 		if (prop_name[0] == '_') {
10515903Ssowmini 			/*
10525903Ssowmini 			 * private property.
10535903Ssowmini 			 */
10548460SArtem.Kachitchkin@Sun.COM 			if (type == DLADM_PROP_VAL_PERSISTENT)
10558460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_linkprop_db(handle, linkid,
10568460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp));
10578460SArtem.Kachitchkin@Sun.COM 			else
10588460SArtem.Kachitchkin@Sun.COM 				return (i_dladm_get_priv_prop(handle, linkid,
10598460SArtem.Kachitchkin@Sun.COM 				    prop_name, prop_val, val_cntp, type,
10608460SArtem.Kachitchkin@Sun.COM 				    dld_flags));
10615903Ssowmini 		} else {
10625903Ssowmini 			return (DLADM_STATUS_NOTFOUND);
10635903Ssowmini 		}
10645903Ssowmini 	}
10655895Syz147064 
10665895Syz147064 	pdp = &prop_table[i];
10675895Syz147064 
10688453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
10698453SAnurag.Maskey@Sun.COM 	    NULL, 0);
10705895Syz147064 	if (status != DLADM_STATUS_OK)
10715895Syz147064 		return (status);
10725895Syz147064 
10735895Syz147064 	if (!(pdp->pd_class & class))
10745895Syz147064 		return (DLADM_STATUS_BADARG);
10755895Syz147064 
10765895Syz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
10773147Sxc151355 		return (DLADM_STATUS_BADARG);
10783147Sxc151355 
10795895Syz147064 	switch (type) {
10805895Syz147064 	case DLADM_PROP_VAL_CURRENT:
10818453SAnurag.Maskey@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
10828453SAnurag.Maskey@Sun.COM 		    media, dld_flags, &perm_flags);
10838118SVasumathi.Sundaram@Sun.COM 		break;
10848118SVasumathi.Sundaram@Sun.COM 
10858118SVasumathi.Sundaram@Sun.COM 	case DLADM_PROP_VAL_PERM:
10868118SVasumathi.Sundaram@Sun.COM 		if (pdp->pd_set == NULL) {
10878118SVasumathi.Sundaram@Sun.COM 			perm_flags = MAC_PROP_PERM_READ;
10888118SVasumathi.Sundaram@Sun.COM 		} else {
10898453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
10908453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
10918118SVasumathi.Sundaram@Sun.COM 		}
10928118SVasumathi.Sundaram@Sun.COM 
10938118SVasumathi.Sundaram@Sun.COM 		*prop_val[0] = '\0';
10949055SMichael.Lim@Sun.COM 		*val_cntp = 1;
10958275SEric Cheng 		if (status == DLADM_STATUS_OK)
10968275SEric Cheng 			(void) dladm_perm2str(perm_flags, *prop_val);
10975895Syz147064 		break;
10985895Syz147064 
10995895Syz147064 	case DLADM_PROP_VAL_DEFAULT:
11006768Sar224390 		/*
11016768Sar224390 		 * If defaults are not defined for the property,
11026768Sar224390 		 * pd_defval.vd_name should be null. If the driver
11036768Sar224390 		 * has to be contacted for the value, vd_name should
11046768Sar224390 		 * be the empty string (""). Otherwise, dladm will
11056768Sar224390 		 * just print whatever is in the table.
11066768Sar224390 		 */
11075895Syz147064 		if (pdp->pd_defval.vd_name == NULL) {
11085895Syz147064 			status = DLADM_STATUS_NOTSUP;
11095895Syz147064 			break;
11105895Syz147064 		}
11116512Ssowmini 
11126512Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
11138453SAnurag.Maskey@Sun.COM 			status = pdp->pd_get(handle, pdp, linkid, prop_val,
11148453SAnurag.Maskey@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
11156512Ssowmini 		} else {
11166512Ssowmini 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
11176512Ssowmini 		}
11185895Syz147064 		*val_cntp = 1;
11195895Syz147064 		break;
11203448Sdh155122 
11215895Syz147064 	case DLADM_PROP_VAL_MODIFIABLE:
11225895Syz147064 		if (pdp->pd_getmod != NULL) {
11238453SAnurag.Maskey@Sun.COM 			status = pdp->pd_getmod(handle, pdp, linkid, prop_val,
11248118SVasumathi.Sundaram@Sun.COM 			    val_cntp, media, dld_flags, &perm_flags);
11255895Syz147064 			break;
11265895Syz147064 		}
11275895Syz147064 		cnt = pdp->pd_noptval;
11285895Syz147064 		if (cnt == 0) {
11295895Syz147064 			status = DLADM_STATUS_NOTSUP;
11305895Syz147064 		} else if (cnt > *val_cntp) {
11315895Syz147064 			status = DLADM_STATUS_TOOSMALL;
11325895Syz147064 		} else {
11335895Syz147064 			for (i = 0; i < cnt; i++) {
11345895Syz147064 				(void) strcpy(prop_val[i],
11355895Syz147064 				    pdp->pd_optval[i].vd_name);
11365895Syz147064 			}
11375895Syz147064 			*val_cntp = cnt;
11385895Syz147064 		}
11395895Syz147064 		break;
11405895Syz147064 	case DLADM_PROP_VAL_PERSISTENT:
11415895Syz147064 		if (pdp->pd_flags & PD_TEMPONLY)
11425895Syz147064 			return (DLADM_STATUS_TEMPONLY);
11438453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_linkprop_db(handle, linkid, prop_name,
11445895Syz147064 		    prop_val, val_cntp);
11455895Syz147064 		break;
11465895Syz147064 	default:
11475895Syz147064 		status = DLADM_STATUS_BADARG;
11485895Syz147064 		break;
11493147Sxc151355 	}
11503448Sdh155122 
11515895Syz147064 	return (status);
11525895Syz147064 }
11535895Syz147064 
115410491SRishi.Srivatsavai@Sun.COM /*
115510491SRishi.Srivatsavai@Sun.COM  * Get linkprop of the given specific link and run any possible conversion
115610491SRishi.Srivatsavai@Sun.COM  * of the values using the check function for the property. Fails if the
115710491SRishi.Srivatsavai@Sun.COM  * check function doesn't succeed for the property value.
115810491SRishi.Srivatsavai@Sun.COM  */
115910491SRishi.Srivatsavai@Sun.COM dladm_status_t
116010491SRishi.Srivatsavai@Sun.COM dladm_get_linkprop_values(dladm_handle_t handle, datalink_id_t linkid,
116110491SRishi.Srivatsavai@Sun.COM     dladm_prop_type_t type, const char *prop_name, uint_t *ret_val,
116210491SRishi.Srivatsavai@Sun.COM     uint_t *val_cntp)
116310491SRishi.Srivatsavai@Sun.COM {
116410491SRishi.Srivatsavai@Sun.COM 	dladm_status_t		status;
116510491SRishi.Srivatsavai@Sun.COM 	datalink_class_t	class;
116610491SRishi.Srivatsavai@Sun.COM 	uint_t			media;
116710491SRishi.Srivatsavai@Sun.COM 	prop_desc_t		*pdp;
116810491SRishi.Srivatsavai@Sun.COM 	uint_t			dld_flags;
116910491SRishi.Srivatsavai@Sun.COM 	int			valc, i;
117010491SRishi.Srivatsavai@Sun.COM 	char			**prop_val;
117110491SRishi.Srivatsavai@Sun.COM 	uint_t			perm_flags;
117210491SRishi.Srivatsavai@Sun.COM 
117310491SRishi.Srivatsavai@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
117410491SRishi.Srivatsavai@Sun.COM 	    ret_val == NULL || val_cntp == NULL || *val_cntp == 0)
117510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
117610491SRishi.Srivatsavai@Sun.COM 
117710491SRishi.Srivatsavai@Sun.COM 	for (pdp = prop_table; pdp < prop_table + DLADM_MAX_PROPS; pdp++)
117810491SRishi.Srivatsavai@Sun.COM 		if (strcasecmp(prop_name, pdp->pd_name) == 0)
117910491SRishi.Srivatsavai@Sun.COM 			break;
118010491SRishi.Srivatsavai@Sun.COM 
118110491SRishi.Srivatsavai@Sun.COM 	if (pdp == prop_table + DLADM_MAX_PROPS)
118210491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
118310491SRishi.Srivatsavai@Sun.COM 
118410491SRishi.Srivatsavai@Sun.COM 	if (pdp->pd_flags & PD_CHECK_ALLOC)
118510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
118610491SRishi.Srivatsavai@Sun.COM 
118710491SRishi.Srivatsavai@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, &media,
118810491SRishi.Srivatsavai@Sun.COM 	    NULL, 0);
118910491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
119010491SRishi.Srivatsavai@Sun.COM 		return (status);
119110491SRishi.Srivatsavai@Sun.COM 
119210491SRishi.Srivatsavai@Sun.COM 	if (!(pdp->pd_class & class))
119310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
119410491SRishi.Srivatsavai@Sun.COM 
119510491SRishi.Srivatsavai@Sun.COM 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
119610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
119710491SRishi.Srivatsavai@Sun.COM 
119810491SRishi.Srivatsavai@Sun.COM 	prop_val = malloc(*val_cntp * sizeof (*prop_val) +
119910491SRishi.Srivatsavai@Sun.COM 	    *val_cntp * DLADM_PROP_VAL_MAX);
120010491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL)
120110491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOMEM);
120210491SRishi.Srivatsavai@Sun.COM 	for (valc = 0; valc < *val_cntp; valc++)
120310491SRishi.Srivatsavai@Sun.COM 		prop_val[valc] = (char *)(prop_val + *val_cntp) +
120410491SRishi.Srivatsavai@Sun.COM 		    valc * DLADM_PROP_VAL_MAX;
120510491SRishi.Srivatsavai@Sun.COM 
1206*11878SVenu.Iyer@Sun.COM 	dld_flags = (type == DLADM_PROP_VAL_DEFAULT) ? DLD_PROP_DEFAULT : 0;
120710491SRishi.Srivatsavai@Sun.COM 
120810491SRishi.Srivatsavai@Sun.COM 	switch (type) {
120910491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_CURRENT:
121010491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
121110491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
121210491SRishi.Srivatsavai@Sun.COM 		break;
121310491SRishi.Srivatsavai@Sun.COM 
121410491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_DEFAULT:
121510491SRishi.Srivatsavai@Sun.COM 		/*
121610491SRishi.Srivatsavai@Sun.COM 		 * If defaults are not defined for the property,
121710491SRishi.Srivatsavai@Sun.COM 		 * pd_defval.vd_name should be null. If the driver
121810491SRishi.Srivatsavai@Sun.COM 		 * has to be contacted for the value, vd_name should
121910491SRishi.Srivatsavai@Sun.COM 		 * be the empty string (""). Otherwise, dladm will
122010491SRishi.Srivatsavai@Sun.COM 		 * just print whatever is in the table.
122110491SRishi.Srivatsavai@Sun.COM 		 */
122210491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name == NULL) {
122310491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_NOTSUP;
122410491SRishi.Srivatsavai@Sun.COM 			break;
122510491SRishi.Srivatsavai@Sun.COM 		}
122610491SRishi.Srivatsavai@Sun.COM 
122710491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_defval.vd_name[0] != '\0') {
122810491SRishi.Srivatsavai@Sun.COM 			*val_cntp = 1;
122910491SRishi.Srivatsavai@Sun.COM 			*ret_val = pdp->pd_defval.vd_val;
123010491SRishi.Srivatsavai@Sun.COM 			free(prop_val);
123110491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
123210491SRishi.Srivatsavai@Sun.COM 		}
123310491SRishi.Srivatsavai@Sun.COM 		status = pdp->pd_get(handle, pdp, linkid, prop_val, val_cntp,
123410491SRishi.Srivatsavai@Sun.COM 		    media, dld_flags, &perm_flags);
123510491SRishi.Srivatsavai@Sun.COM 		break;
123610491SRishi.Srivatsavai@Sun.COM 
123710491SRishi.Srivatsavai@Sun.COM 	case DLADM_PROP_VAL_PERSISTENT:
123810491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_flags & PD_TEMPONLY)
123910491SRishi.Srivatsavai@Sun.COM 			status = DLADM_STATUS_TEMPONLY;
124010491SRishi.Srivatsavai@Sun.COM 		else
124110491SRishi.Srivatsavai@Sun.COM 			status = i_dladm_get_linkprop_db(handle, linkid,
124210491SRishi.Srivatsavai@Sun.COM 			    prop_name, prop_val, val_cntp);
124310491SRishi.Srivatsavai@Sun.COM 		break;
124410491SRishi.Srivatsavai@Sun.COM 
124510491SRishi.Srivatsavai@Sun.COM 	default:
124610491SRishi.Srivatsavai@Sun.COM 		status = DLADM_STATUS_BADARG;
124710491SRishi.Srivatsavai@Sun.COM 		break;
124810491SRishi.Srivatsavai@Sun.COM 	}
124910491SRishi.Srivatsavai@Sun.COM 
125010491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
125110491SRishi.Srivatsavai@Sun.COM 		if (pdp->pd_check != NULL) {
125210491SRishi.Srivatsavai@Sun.COM 			val_desc_t *vdp;
125310491SRishi.Srivatsavai@Sun.COM 
125410491SRishi.Srivatsavai@Sun.COM 			vdp = malloc(sizeof (val_desc_t) * *val_cntp);
125510491SRishi.Srivatsavai@Sun.COM 			if (vdp == NULL)
125610491SRishi.Srivatsavai@Sun.COM 				status = DLADM_STATUS_NOMEM;
125710491SRishi.Srivatsavai@Sun.COM 			else
125810491SRishi.Srivatsavai@Sun.COM 				status = pdp->pd_check(handle, pdp, linkid,
1259*11878SVenu.Iyer@Sun.COM 				    prop_val, *val_cntp, 0, vdp, media);
126010491SRishi.Srivatsavai@Sun.COM 			if (status == DLADM_STATUS_OK) {
126110491SRishi.Srivatsavai@Sun.COM 				for (valc = 0; valc < *val_cntp; valc++)
126210491SRishi.Srivatsavai@Sun.COM 					ret_val[valc] = vdp[valc].vd_val;
126310491SRishi.Srivatsavai@Sun.COM 			}
126410491SRishi.Srivatsavai@Sun.COM 			free(vdp);
126510491SRishi.Srivatsavai@Sun.COM 		} else {
126610491SRishi.Srivatsavai@Sun.COM 			for (valc = 0; valc < *val_cntp; valc++) {
126710491SRishi.Srivatsavai@Sun.COM 				for (i = 0; i < pdp->pd_noptval; i++) {
126810491SRishi.Srivatsavai@Sun.COM 					if (strcmp(pdp->pd_optval[i].vd_name,
126910491SRishi.Srivatsavai@Sun.COM 					    prop_val[valc]) == 0) {
127010491SRishi.Srivatsavai@Sun.COM 						ret_val[valc] =
127110491SRishi.Srivatsavai@Sun.COM 						    pdp->pd_optval[i].vd_val;
127210491SRishi.Srivatsavai@Sun.COM 						break;
127310491SRishi.Srivatsavai@Sun.COM 					}
127410491SRishi.Srivatsavai@Sun.COM 				}
127510491SRishi.Srivatsavai@Sun.COM 				if (i == pdp->pd_noptval) {
127610491SRishi.Srivatsavai@Sun.COM 					status = DLADM_STATUS_FAILED;
127710491SRishi.Srivatsavai@Sun.COM 					break;
127810491SRishi.Srivatsavai@Sun.COM 				}
127910491SRishi.Srivatsavai@Sun.COM 			}
128010491SRishi.Srivatsavai@Sun.COM 		}
128110491SRishi.Srivatsavai@Sun.COM 	}
128210491SRishi.Srivatsavai@Sun.COM 
128310491SRishi.Srivatsavai@Sun.COM 	free(prop_val);
128410491SRishi.Srivatsavai@Sun.COM 
128510491SRishi.Srivatsavai@Sun.COM 	return (status);
128610491SRishi.Srivatsavai@Sun.COM }
128710491SRishi.Srivatsavai@Sun.COM 
12885895Syz147064 /*ARGSUSED*/
12895895Syz147064 static int
12908453SAnurag.Maskey@Sun.COM i_dladm_init_one_prop(dladm_handle_t handle, datalink_id_t linkid,
12918453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
12925895Syz147064 {
1293*11878SVenu.Iyer@Sun.COM 	char			*buf, **propvals;
1294*11878SVenu.Iyer@Sun.COM 	uint_t			i, valcnt = DLADM_MAX_PROP_VALCNT;
1295*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
1296*11878SVenu.Iyer@Sun.COM 	dladm_linkprop_args_t	*dla = arg;
12975895Syz147064 
12985895Syz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
12995895Syz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
13005895Syz147064 		return (DLADM_WALK_CONTINUE);
13015895Syz147064 	}
13025895Syz147064 
13035895Syz147064 	propvals = (char **)(void *)buf;
13045895Syz147064 	for (i = 0; i < valcnt; i++) {
13055895Syz147064 		propvals[i] = buf +
13065895Syz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
13075895Syz147064 		    i * DLADM_PROP_VAL_MAX;
13085895Syz147064 	}
13095895Syz147064 
13108453SAnurag.Maskey@Sun.COM 	if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
13118453SAnurag.Maskey@Sun.COM 	    prop_name, propvals, &valcnt) != DLADM_STATUS_OK) {
13125895Syz147064 		goto done;
13135895Syz147064 	}
13145895Syz147064 
131511021SEric.Cheng@Sun.COM 	status = dladm_set_linkprop(handle, linkid, prop_name, propvals,
1316*11878SVenu.Iyer@Sun.COM 	    valcnt, dla->dla_flags | DLADM_OPT_ACTIVE);
1317*11878SVenu.Iyer@Sun.COM 
131811021SEric.Cheng@Sun.COM 	if (status != DLADM_STATUS_OK)
1319*11878SVenu.Iyer@Sun.COM 		dla->dla_status = status;
13205895Syz147064 
13215895Syz147064 done:
13225895Syz147064 	if (buf != NULL)
13235895Syz147064 		free(buf);
13245895Syz147064 
13255895Syz147064 	return (DLADM_WALK_CONTINUE);
13265895Syz147064 }
13275895Syz147064 
13285895Syz147064 /*ARGSUSED*/
13295895Syz147064 static int
13308453SAnurag.Maskey@Sun.COM i_dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid, void *arg)
13315895Syz147064 {
13328275SEric Cheng 	datalink_class_t	class;
13338275SEric Cheng 	dladm_status_t		status;
13348275SEric Cheng 
13358453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
13368453SAnurag.Maskey@Sun.COM 	    NULL, 0);
13378275SEric Cheng 	if (status != DLADM_STATUS_OK)
13388275SEric Cheng 		return (DLADM_WALK_TERMINATE);
13398275SEric Cheng 
13408275SEric Cheng 	if ((class & (DATALINK_CLASS_VNIC | DATALINK_CLASS_VLAN)) == 0)
13418453SAnurag.Maskey@Sun.COM 		(void) dladm_init_linkprop(handle, linkid, B_TRUE);
13428275SEric Cheng 
13435895Syz147064 	return (DLADM_WALK_CONTINUE);
13445895Syz147064 }
13455895Syz147064 
13465895Syz147064 dladm_status_t
13478453SAnurag.Maskey@Sun.COM dladm_init_linkprop(dladm_handle_t handle, datalink_id_t linkid,
13488453SAnurag.Maskey@Sun.COM     boolean_t any_media)
13495895Syz147064 {
135011021SEric.Cheng@Sun.COM 	dladm_status_t		status = DLADM_STATUS_OK;
13516916Sartem 	datalink_media_t	dmedia;
13526916Sartem 	uint32_t		media;
1353*11878SVenu.Iyer@Sun.COM 	dladm_linkprop_args_t	*dla;
13546916Sartem 
13556916Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
13566916Sartem 
1357*11878SVenu.Iyer@Sun.COM 	dla = malloc(sizeof (dladm_linkprop_args_t));
1358*11878SVenu.Iyer@Sun.COM 	if (dla == NULL)
1359*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
1360*11878SVenu.Iyer@Sun.COM 	dla->dla_flags = DLADM_OPT_BOOT;
1361*11878SVenu.Iyer@Sun.COM 	dla->dla_status = DLADM_STATUS_OK;
1362*11878SVenu.Iyer@Sun.COM 
13635895Syz147064 	if (linkid == DATALINK_ALL_LINKID) {
13648453SAnurag.Maskey@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, handle,
13658453SAnurag.Maskey@Sun.COM 		    NULL, DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
13668453SAnurag.Maskey@Sun.COM 	} else if (any_media ||
13678453SAnurag.Maskey@Sun.COM 	    ((dladm_datalink_id2info(handle, linkid, NULL, NULL, &media, NULL,
13688453SAnurag.Maskey@Sun.COM 	    0) == DLADM_STATUS_OK) &&
13696916Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
1370*11878SVenu.Iyer@Sun.COM 		(void) dladm_walk_linkprop(handle, linkid, (void *)dla,
13718453SAnurag.Maskey@Sun.COM 		    i_dladm_init_one_prop);
1372*11878SVenu.Iyer@Sun.COM 		status = dla->dla_status;
13733448Sdh155122 	}
1374*11878SVenu.Iyer@Sun.COM 	free(dla);
137511021SEric.Cheng@Sun.COM 	return (status);
13763147Sxc151355 }
13773147Sxc151355 
13785903Ssowmini /* ARGSUSED */
13795895Syz147064 static dladm_status_t
1380*11878SVenu.Iyer@Sun.COM get_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
13818275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
13828275SEric Cheng     uint_t flags, uint_t *perm_flags)
13833147Sxc151355 {
13848275SEric Cheng 	char			zone_name[ZONENAME_MAX];
13858275SEric Cheng 	zoneid_t		zid;
13868275SEric Cheng 	dladm_status_t		status;
13873147Sxc151355 
13886512Ssowmini 	if (flags != 0)
13896512Ssowmini 		return (DLADM_STATUS_NOTSUP);
13906512Ssowmini 
1391*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1392*11878SVenu.Iyer@Sun.COM 	    perm_flags, &zid, sizeof (zid));
13935895Syz147064 	if (status != DLADM_STATUS_OK)
13943448Sdh155122 		return (status);
13953448Sdh155122 
13965895Syz147064 	*val_cnt = 1;
13975895Syz147064 	if (zid != GLOBAL_ZONEID) {
13988118SVasumathi.Sundaram@Sun.COM 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) {
13995895Syz147064 			return (dladm_errno2status(errno));
14008118SVasumathi.Sundaram@Sun.COM 		}
14013147Sxc151355 
14025895Syz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
14033147Sxc151355 	} else {
14045895Syz147064 		*prop_val[0] = '\0';
14053147Sxc151355 	}
14063147Sxc151355 
14073448Sdh155122 	return (DLADM_STATUS_OK);
14083448Sdh155122 }
14093448Sdh155122 
14103448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
14113448Sdh155122 
14123448Sdh155122 static int
14133448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
14143448Sdh155122 {
14153448Sdh155122 	char			root[MAXPATHLEN];
14163448Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
14173448Sdh155122 	void			*dlhandle;
14183448Sdh155122 	void			*sym;
14193448Sdh155122 	int			ret;
14203448Sdh155122 
14213448Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
14223448Sdh155122 		return (-1);
14233448Sdh155122 
14243448Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
14253448Sdh155122 		(void) dlclose(dlhandle);
14263448Sdh155122 		return (-1);
14273448Sdh155122 	}
14283448Sdh155122 
14293448Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
14303448Sdh155122 
14313448Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
14323448Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
14333448Sdh155122 	(void) dlclose(dlhandle);
14343448Sdh155122 	return (ret);
14353448Sdh155122 }
14363448Sdh155122 
14373448Sdh155122 static dladm_status_t
14388453SAnurag.Maskey@Sun.COM i_dladm_update_deventry(dladm_handle_t handle, zoneid_t zid,
14398453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, boolean_t add)
14403448Sdh155122 {
14413448Sdh155122 	char		path[MAXPATHLEN];
14425895Syz147064 	char		name[MAXLINKNAMELEN];
14433448Sdh155122 	di_prof_t	prof = NULL;
14443448Sdh155122 	char		zone_name[ZONENAME_MAX];
14453448Sdh155122 	dladm_status_t	status;
14465895Syz147064 	int		ret;
14473448Sdh155122 
14483448Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
14493448Sdh155122 		return (dladm_errno2status(errno));
14503448Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
14513448Sdh155122 		return (dladm_errno2status(errno));
14523448Sdh155122 	if (di_prof_init(path, &prof) != 0)
14533448Sdh155122 		return (dladm_errno2status(errno));
14543448Sdh155122 
14558453SAnurag.Maskey@Sun.COM 	status = dladm_linkid2legacyname(handle, linkid, name, MAXLINKNAMELEN);
14565895Syz147064 	if (status != DLADM_STATUS_OK)
14575895Syz147064 		goto cleanup;
14585895Syz147064 
14595895Syz147064 	if (add)
14605895Syz147064 		ret = di_prof_add_dev(prof, name);
14615895Syz147064 	else
14625895Syz147064 		ret = di_prof_add_exclude(prof, name);
14635895Syz147064 
14645895Syz147064 	if (ret != 0) {
14653448Sdh155122 		status = dladm_errno2status(errno);
14663448Sdh155122 		goto cleanup;
14673448Sdh155122 	}
14683448Sdh155122 
14693448Sdh155122 	if (di_prof_commit(prof) != 0)
14703448Sdh155122 		status = dladm_errno2status(errno);
14713448Sdh155122 cleanup:
14723448Sdh155122 	if (prof)
14733448Sdh155122 		di_prof_fini(prof);
14743448Sdh155122 
14753448Sdh155122 	return (status);
14763448Sdh155122 }
14773448Sdh155122 
14785903Ssowmini /* ARGSUSED */
14793448Sdh155122 static dladm_status_t
1480*11878SVenu.Iyer@Sun.COM set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
14818453SAnurag.Maskey@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
14823448Sdh155122 {
14838275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
14848275SEric Cheng 	zoneid_t		zid_old, zid_new;
14857342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t		*dzp;
14863448Sdh155122 
14873448Sdh155122 	if (val_cnt != 1)
14883448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
14893448Sdh155122 
14907342SAruna.Ramakrishna@Sun.COM 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
14917342SAruna.Ramakrishna@Sun.COM 
1492*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
1493*11878SVenu.Iyer@Sun.COM 	    NULL, &zid_old, sizeof (zid_old));
14948275SEric Cheng 	if (status != DLADM_STATUS_OK)
14958275SEric Cheng 		return (status);
14968275SEric Cheng 
14977342SAruna.Ramakrishna@Sun.COM 	zid_new = dzp->diz_zid;
14983448Sdh155122 	if (zid_new == zid_old)
149910616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_OK);
150010616SSebastien.Roy@Sun.COM 
1501*11878SVenu.Iyer@Sun.COM 	if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt,
150210616SSebastien.Roy@Sun.COM 	    flags, media)) != DLADM_STATUS_OK)
15035895Syz147064 		return (status);
15045895Syz147064 
150510616SSebastien.Roy@Sun.COM 	/*
150610616SSebastien.Roy@Sun.COM 	 * It is okay to fail to update the /dev entry (some vanity-named
150710616SSebastien.Roy@Sun.COM 	 * links do not have a /dev entry).
150810616SSebastien.Roy@Sun.COM 	 */
15093448Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
15108453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_old, linkid,
15118453SAnurag.Maskey@Sun.COM 		    B_FALSE);
15125895Syz147064 	}
151310616SSebastien.Roy@Sun.COM 	if (zid_new != GLOBAL_ZONEID)
15148453SAnurag.Maskey@Sun.COM 		(void) i_dladm_update_deventry(handle, zid_new, linkid, B_TRUE);
15153448Sdh155122 
15163448Sdh155122 	return (DLADM_STATUS_OK);
15173448Sdh155122 }
15183448Sdh155122 
15193448Sdh155122 /* ARGSUSED */
15203448Sdh155122 static dladm_status_t
1521*11878SVenu.Iyer@Sun.COM check_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1522*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
1523*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
15243448Sdh155122 {
15257342SAruna.Ramakrishna@Sun.COM 	char		*zone_name;
15267342SAruna.Ramakrishna@Sun.COM 	zoneid_t	zoneid;
15277342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
15287342SAruna.Ramakrishna@Sun.COM 	dld_ioc_zid_t	*dzp;
15293448Sdh155122 
15303448Sdh155122 	if (val_cnt != 1)
15313448Sdh155122 		return (DLADM_STATUS_BADVALCNT);
15323448Sdh155122 
15337342SAruna.Ramakrishna@Sun.COM 	dzp = malloc(sizeof (dld_ioc_zid_t));
15347342SAruna.Ramakrishna@Sun.COM 	if (dzp == NULL)
15357342SAruna.Ramakrishna@Sun.COM 		return (DLADM_STATUS_NOMEM);
15363448Sdh155122 
15378275SEric Cheng 	zone_name = (prop_val != NULL) ? *prop_val : GLOBAL_ZONENAME;
15387342SAruna.Ramakrishna@Sun.COM 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
15397342SAruna.Ramakrishna@Sun.COM 		status = DLADM_STATUS_BADVAL;
15407342SAruna.Ramakrishna@Sun.COM 		goto done;
15417342SAruna.Ramakrishna@Sun.COM 	}
15427342SAruna.Ramakrishna@Sun.COM 
15437342SAruna.Ramakrishna@Sun.COM 	if (zoneid != GLOBAL_ZONEID) {
15443448Sdh155122 		ushort_t	flags;
15453448Sdh155122 
15467342SAruna.Ramakrishna@Sun.COM 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
15473448Sdh155122 		    sizeof (flags)) < 0) {
15487342SAruna.Ramakrishna@Sun.COM 			status = dladm_errno2status(errno);
15497342SAruna.Ramakrishna@Sun.COM 			goto done;
15503448Sdh155122 		}
15513448Sdh155122 
15523448Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
15537342SAruna.Ramakrishna@Sun.COM 			status = DLADM_STATUS_BADVAL;
15547342SAruna.Ramakrishna@Sun.COM 			goto done;
15553448Sdh155122 		}
15563448Sdh155122 	}
15573448Sdh155122 
15587342SAruna.Ramakrishna@Sun.COM 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
15597342SAruna.Ramakrishna@Sun.COM 
15607342SAruna.Ramakrishna@Sun.COM 	dzp->diz_zid = zoneid;
156110616SSebastien.Roy@Sun.COM 	dzp->diz_linkid = linkid;
15627342SAruna.Ramakrishna@Sun.COM 
15637342SAruna.Ramakrishna@Sun.COM 	vdp->vd_val = (uintptr_t)dzp;
15645895Syz147064 	return (DLADM_STATUS_OK);
15657342SAruna.Ramakrishna@Sun.COM done:
15667342SAruna.Ramakrishna@Sun.COM 	free(dzp);
15677342SAruna.Ramakrishna@Sun.COM 	return (status);
15685895Syz147064 }
15695895Syz147064 
15705903Ssowmini /* ARGSUSED */
15715895Syz147064 static dladm_status_t
1572*11878SVenu.Iyer@Sun.COM get_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
15738275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
15748275SEric Cheng     uint_t flags, uint_t *perm_flags)
15758275SEric Cheng {
15768275SEric Cheng 	mac_resource_props_t	mrp;
15778275SEric Cheng 	dladm_status_t		status;
15788275SEric Cheng 
1579*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
1580*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
1581*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
15828275SEric Cheng 		return (status);
15838275SEric Cheng 
15848275SEric Cheng 	if ((mrp.mrp_mask & MRP_MAXBW) == 0) {
1585*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
1586*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
15878275SEric Cheng 	}
1588*11878SVenu.Iyer@Sun.COM 
1589*11878SVenu.Iyer@Sun.COM 	(void) dladm_bw2str(mrp.mrp_maxbw, prop_val[0]);
15908275SEric Cheng 	*val_cnt = 1;
15918275SEric Cheng 	return (DLADM_STATUS_OK);
15928275SEric Cheng }
15938275SEric Cheng 
15948275SEric Cheng /* ARGSUSED */
15958275SEric Cheng static dladm_status_t
1596*11878SVenu.Iyer@Sun.COM check_maxbw(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1597*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
1598*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
15998275SEric Cheng {
16008275SEric Cheng 	uint64_t	*maxbw;
16018275SEric Cheng 	dladm_status_t	status = DLADM_STATUS_OK;
16028275SEric Cheng 
16038275SEric Cheng 	if (val_cnt != 1)
16048275SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
16058275SEric Cheng 
16068275SEric Cheng 	maxbw = malloc(sizeof (uint64_t));
16078275SEric Cheng 	if (maxbw == NULL)
16088275SEric Cheng 		return (DLADM_STATUS_NOMEM);
16098275SEric Cheng 
16108275SEric Cheng 	status = dladm_str2bw(*prop_val, maxbw);
16118275SEric Cheng 	if (status != DLADM_STATUS_OK) {
16128275SEric Cheng 		free(maxbw);
16138275SEric Cheng 		return (status);
16148275SEric Cheng 	}
16158275SEric Cheng 
16168275SEric Cheng 	if ((*maxbw < MRP_MAXBW_MINVAL) && (*maxbw != 0)) {
16178275SEric Cheng 		free(maxbw);
16188275SEric Cheng 		return (DLADM_STATUS_MINMAXBW);
16198275SEric Cheng 	}
16208275SEric Cheng 
16218275SEric Cheng 	vdp->vd_val = (uintptr_t)maxbw;
16228275SEric Cheng 	return (DLADM_STATUS_OK);
16238275SEric Cheng }
16248275SEric Cheng 
16258275SEric Cheng /* ARGSUSED */
16268275SEric Cheng dladm_status_t
1627*11878SVenu.Iyer@Sun.COM extract_maxbw(val_desc_t *vdp, uint_t cnt, void *arg)
16288275SEric Cheng {
162910734SEric Cheng 	mac_resource_props_t *mrp = arg;
16308275SEric Cheng 
1631*11878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL) {
1632*11878SVenu.Iyer@Sun.COM 		mrp->mrp_maxbw = MRP_MAXBW_RESETVAL;
1633*11878SVenu.Iyer@Sun.COM 	} else {
1634*11878SVenu.Iyer@Sun.COM 		bcopy((char *)vdp->vd_val, &mrp->mrp_maxbw, sizeof (uint64_t));
1635*11878SVenu.Iyer@Sun.COM 	}
16368275SEric Cheng 	mrp->mrp_mask |= MRP_MAXBW;
16378275SEric Cheng 
16388275SEric Cheng 	return (DLADM_STATUS_OK);
16398275SEric Cheng }
16408275SEric Cheng 
16418275SEric Cheng /* ARGSUSED */
16428275SEric Cheng static dladm_status_t
1643*11878SVenu.Iyer@Sun.COM get_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
16448275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
16458275SEric Cheng     uint_t flags, uint_t *perm_flags)
16468275SEric Cheng {
1647*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
16488275SEric Cheng 	mac_resource_props_t	mrp;
16498275SEric Cheng 	int			i;
16508275SEric Cheng 	uint32_t		ncpus;
1651*11878SVenu.Iyer@Sun.COM 
1652*11878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "cpus-effective") == 0) {
1653*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
1654*11878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
1655*11878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
1656*11878SVenu.Iyer@Sun.COM 	} else {
1657*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
1658*11878SVenu.Iyer@Sun.COM 		    "resource", flags, perm_flags, &mrp, sizeof (mrp));
1659*11878SVenu.Iyer@Sun.COM 	}
1660*11878SVenu.Iyer@Sun.COM 
1661*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
16628275SEric Cheng 		return (status);
16638275SEric Cheng 
16648275SEric Cheng 	ncpus = mrp.mrp_ncpus;
16658275SEric Cheng 	if (ncpus > *val_cnt)
16668275SEric Cheng 		return (DLADM_STATUS_TOOSMALL);
16678275SEric Cheng 
16688275SEric Cheng 	if (ncpus == 0) {
1669*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
16708275SEric Cheng 		return (DLADM_STATUS_OK);
16718275SEric Cheng 	}
16728275SEric Cheng 
16738275SEric Cheng 	*val_cnt = ncpus;
16748275SEric Cheng 	for (i = 0; i < ncpus; i++) {
16758275SEric Cheng 		(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
16768275SEric Cheng 		    "%u", mrp.mrp_cpu[i]);
16778275SEric Cheng 	}
16788275SEric Cheng 	return (DLADM_STATUS_OK);
16798275SEric Cheng }
16808275SEric Cheng 
16818275SEric Cheng /* ARGSUSED */
16828275SEric Cheng static dladm_status_t
1683*11878SVenu.Iyer@Sun.COM check_cpus(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1684*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
1685*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
16868275SEric Cheng {
1687*11878SVenu.Iyer@Sun.COM 	uint32_t		cpuid;
1688*11878SVenu.Iyer@Sun.COM 	int			i, j, rc;
1689*11878SVenu.Iyer@Sun.COM 	char			*endp;
1690*11878SVenu.Iyer@Sun.COM 	long			nproc = sysconf(_SC_NPROCESSORS_CONF);
16918275SEric Cheng 	mac_resource_props_t	mrp;
1692*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
1693*11878SVenu.Iyer@Sun.COM 	uint_t			perm_flags;
1694*11878SVenu.Iyer@Sun.COM 
1695*11878SVenu.Iyer@Sun.COM 	/* Get the current pool property */
1696*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1697*11878SVenu.Iyer@Sun.COM 	    &perm_flags, &mrp, sizeof (mrp));
1698*11878SVenu.Iyer@Sun.COM 
1699*11878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_OK) {
1700*11878SVenu.Iyer@Sun.COM 		/* Can't set cpus if a pool is set */
1701*11878SVenu.Iyer@Sun.COM 		if (strlen(mrp.mrp_pool) != 0)
1702*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_POOLCPU);
1703*11878SVenu.Iyer@Sun.COM 	}
17048275SEric Cheng 
17058275SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
1706*11878SVenu.Iyer@Sun.COM 
1707*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
1708*11878SVenu.Iyer@Sun.COM 		errno = 0;
1709*11878SVenu.Iyer@Sun.COM 		cpuid = strtol(prop_val[i], &endp, 10);
1710*11878SVenu.Iyer@Sun.COM 		if (errno != 0 || *endp != '\0')
1711*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
1712*11878SVenu.Iyer@Sun.COM 
1713*11878SVenu.Iyer@Sun.COM 		if (cpuid >= nproc)
1714*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUMAX);
1715*11878SVenu.Iyer@Sun.COM 
1716*11878SVenu.Iyer@Sun.COM 		rc = p_online(cpuid, P_STATUS);
1717*11878SVenu.Iyer@Sun.COM 		if (rc < 1)
1718*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUERR);
1719*11878SVenu.Iyer@Sun.COM 
1720*11878SVenu.Iyer@Sun.COM 		if (rc != P_ONLINE)
1721*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_CPUNOTONLINE);
1722*11878SVenu.Iyer@Sun.COM 
1723*11878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)cpuid;
1724*11878SVenu.Iyer@Sun.COM 	}
1725*11878SVenu.Iyer@Sun.COM 
1726*11878SVenu.Iyer@Sun.COM 	/* Check for duplicates */
1727*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
1728*11878SVenu.Iyer@Sun.COM 		for (j = 0; j < val_cnt; j++) {
1729*11878SVenu.Iyer@Sun.COM 			if (i != j && vdp[i].vd_val == vdp[j].vd_val)
1730*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADVAL);
17318275SEric Cheng 		}
17328275SEric Cheng 	}
1733*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
1734*11878SVenu.Iyer@Sun.COM }
1735*11878SVenu.Iyer@Sun.COM 
1736*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
1737*11878SVenu.Iyer@Sun.COM dladm_status_t
1738*11878SVenu.Iyer@Sun.COM extract_cpus(val_desc_t *vdp, uint_t cnt, void *arg)
1739*11878SVenu.Iyer@Sun.COM {
1740*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = arg;
1741*11878SVenu.Iyer@Sun.COM 	int			i;
1742*11878SVenu.Iyer@Sun.COM 
1743*11878SVenu.Iyer@Sun.COM 	if (vdp[0].vd_val == RESET_VAL) {
1744*11878SVenu.Iyer@Sun.COM 		bzero(&mrp->mrp_cpus, sizeof (mac_cpus_t));
1745*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask |= MRP_CPUS;
1746*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
1747*11878SVenu.Iyer@Sun.COM 	}
1748*11878SVenu.Iyer@Sun.COM 
1749*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < cnt; i++)
1750*11878SVenu.Iyer@Sun.COM 		mrp->mrp_cpu[i] = (uint32_t)vdp[i].vd_val;
1751*11878SVenu.Iyer@Sun.COM 
1752*11878SVenu.Iyer@Sun.COM 	mrp->mrp_ncpus = cnt;
1753*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= (MRP_CPUS|MRP_CPUS_USERSPEC);
1754*11878SVenu.Iyer@Sun.COM 	mrp->mrp_fanout_mode = MCM_CPUS;
1755*11878SVenu.Iyer@Sun.COM 	mrp->mrp_rx_intr_cpu = -1;
1756*11878SVenu.Iyer@Sun.COM 
1757*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
1758*11878SVenu.Iyer@Sun.COM }
1759*11878SVenu.Iyer@Sun.COM 
1760*11878SVenu.Iyer@Sun.COM /*
1761*11878SVenu.Iyer@Sun.COM  * Get the pool datalink property from the kernel.  This is used
1762*11878SVenu.Iyer@Sun.COM  * for both the user specified pool and effective pool properties.
1763*11878SVenu.Iyer@Sun.COM  */
1764*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
1765*11878SVenu.Iyer@Sun.COM static dladm_status_t
1766*11878SVenu.Iyer@Sun.COM get_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1767*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
1768*11878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
1769*11878SVenu.Iyer@Sun.COM {
1770*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
1771*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
1772*11878SVenu.Iyer@Sun.COM 
1773*11878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "pool-effective") == 0) {
1774*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
1775*11878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
1776*11878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
1777*11878SVenu.Iyer@Sun.COM 	} else {
1778*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
1779*11878SVenu.Iyer@Sun.COM 		    "resource", flags, perm_flags, &mrp, sizeof (mrp));
1780*11878SVenu.Iyer@Sun.COM 	}
1781*11878SVenu.Iyer@Sun.COM 
1782*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
1783*11878SVenu.Iyer@Sun.COM 		return (status);
1784*11878SVenu.Iyer@Sun.COM 
1785*11878SVenu.Iyer@Sun.COM 	if (strlen(mrp.mrp_pool) == 0) {
1786*11878SVenu.Iyer@Sun.COM 		(*prop_val)[0] = '\0';
1787*11878SVenu.Iyer@Sun.COM 	} else {
1788*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
1789*11878SVenu.Iyer@Sun.COM 		    "%s", mrp.mrp_pool);
1790*11878SVenu.Iyer@Sun.COM 	}
1791*11878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
1792*11878SVenu.Iyer@Sun.COM 
1793*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
17948275SEric Cheng }
17958275SEric Cheng 
17968275SEric Cheng /* ARGSUSED */
17978275SEric Cheng static dladm_status_t
1798*11878SVenu.Iyer@Sun.COM check_pool(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
1799*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
1800*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
18018275SEric Cheng {
1802*11878SVenu.Iyer@Sun.COM 	pool_conf_t		*poolconf;
1803*11878SVenu.Iyer@Sun.COM 	pool_t			*pool;
18048275SEric Cheng 	mac_resource_props_t	mrp;
18058275SEric Cheng 	dladm_status_t		status;
1806*11878SVenu.Iyer@Sun.COM 	uint_t			perm_flags;
1807*11878SVenu.Iyer@Sun.COM 	char			*poolname;
1808*11878SVenu.Iyer@Sun.COM 
1809*11878SVenu.Iyer@Sun.COM 	/* Get the current cpus property */
1810*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", 0,
1811*11878SVenu.Iyer@Sun.COM 	    &perm_flags, &mrp, sizeof (mrp));
1812*11878SVenu.Iyer@Sun.COM 
1813*11878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_OK) {
1814*11878SVenu.Iyer@Sun.COM 		/* Can't set pool if cpus are set */
1815*11878SVenu.Iyer@Sun.COM 		if (mrp.mrp_ncpus != 0)
1816*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_POOLCPU);
18178275SEric Cheng 	}
18188275SEric Cheng 
1819*11878SVenu.Iyer@Sun.COM 	poolname = malloc(sizeof (mrp.mrp_pool));
1820*11878SVenu.Iyer@Sun.COM 	if (poolname == NULL)
18218275SEric Cheng 		return (DLADM_STATUS_NOMEM);
18228275SEric Cheng 
1823*11878SVenu.Iyer@Sun.COM 	/* Check for pool's availability if not booting */
1824*11878SVenu.Iyer@Sun.COM 	if ((flags & DLADM_OPT_BOOT) == 0) {
1825*11878SVenu.Iyer@Sun.COM 
1826*11878SVenu.Iyer@Sun.COM 		/* Allocate and open pool configuration */
1827*11878SVenu.Iyer@Sun.COM 		if ((poolconf = pool_conf_alloc()) == NULL)
1828*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
1829*11878SVenu.Iyer@Sun.COM 
1830*11878SVenu.Iyer@Sun.COM 		if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY)
1831*11878SVenu.Iyer@Sun.COM 		    != PO_SUCCESS) {
1832*11878SVenu.Iyer@Sun.COM 			pool_conf_free(poolconf);
1833*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
18348275SEric Cheng 		}
1835*11878SVenu.Iyer@Sun.COM 
1836*11878SVenu.Iyer@Sun.COM 		/* Look for pool name */
1837*11878SVenu.Iyer@Sun.COM 		if ((pool = pool_get_pool(poolconf, *prop_val)) == NULL) {
1838*11878SVenu.Iyer@Sun.COM 			pool_conf_free(poolconf);
1839*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
18408275SEric Cheng 		}
1841*11878SVenu.Iyer@Sun.COM 
1842*11878SVenu.Iyer@Sun.COM 		pool_conf_free(poolconf);
1843*11878SVenu.Iyer@Sun.COM 		free(pool);
18448275SEric Cheng 	}
1845*11878SVenu.Iyer@Sun.COM 
1846*11878SVenu.Iyer@Sun.COM 	(void) strlcpy(poolname, *prop_val, sizeof (mrp.mrp_pool));
1847*11878SVenu.Iyer@Sun.COM 	vdp->vd_val = (uintptr_t)poolname;
18488275SEric Cheng 
18498275SEric Cheng 	return (DLADM_STATUS_OK);
18508275SEric Cheng }
18518275SEric Cheng 
18528275SEric Cheng /* ARGSUSED */
18538275SEric Cheng dladm_status_t
1854*11878SVenu.Iyer@Sun.COM extract_pool(val_desc_t *vdp, uint_t cnt, void *arg)
18558275SEric Cheng {
1856*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
1857*11878SVenu.Iyer@Sun.COM 
1858*11878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL) {
1859*11878SVenu.Iyer@Sun.COM 		bzero(&mrp->mrp_pool, sizeof (mrp->mrp_pool));
1860*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask |= MRP_POOL;
1861*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
18628275SEric Cheng 	}
1863*11878SVenu.Iyer@Sun.COM 
1864*11878SVenu.Iyer@Sun.COM 	(void) strlcpy(mrp->mrp_pool, (char *)vdp->vd_val,
1865*11878SVenu.Iyer@Sun.COM 	    sizeof (mrp->mrp_pool));
1866*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_POOL;
1867*11878SVenu.Iyer@Sun.COM 	/*
1868*11878SVenu.Iyer@Sun.COM 	 * Use MCM_CPUS since the fanout count is not user specified
1869*11878SVenu.Iyer@Sun.COM 	 * and will be determined by the cpu list generated from the
1870*11878SVenu.Iyer@Sun.COM 	 * pool.
1871*11878SVenu.Iyer@Sun.COM 	 */
18728275SEric Cheng 	mrp->mrp_fanout_mode = MCM_CPUS;
18738275SEric Cheng 
18748275SEric Cheng 	return (DLADM_STATUS_OK);
18758275SEric Cheng }
18768275SEric Cheng 
18778275SEric Cheng /* ARGSUSED */
18788275SEric Cheng static dladm_status_t
1879*11878SVenu.Iyer@Sun.COM get_priority(dladm_handle_t handle, prop_desc_t *pdp,
18808460SArtem.Kachitchkin@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
18818460SArtem.Kachitchkin@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
18828275SEric Cheng {
18838275SEric Cheng 	mac_resource_props_t	mrp;
18848275SEric Cheng 	mac_priority_level_t	pri;
18858275SEric Cheng 	dladm_status_t		status;
18868275SEric Cheng 
1887*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
1888*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
1889*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
18908275SEric Cheng 		return (status);
18918275SEric Cheng 
18928275SEric Cheng 	pri = ((mrp.mrp_mask & MRP_PRIORITY) == 0) ? MPL_HIGH :
18938275SEric Cheng 	    mrp.mrp_priority;
18948275SEric Cheng 
18958275SEric Cheng 	(void) dladm_pri2str(pri, prop_val[0]);
18968275SEric Cheng 	*val_cnt = 1;
18978275SEric Cheng 	return (DLADM_STATUS_OK);
18988275SEric Cheng }
18998275SEric Cheng 
19008275SEric Cheng /* ARGSUSED */
1901*11878SVenu.Iyer@Sun.COM dladm_status_t
1902*11878SVenu.Iyer@Sun.COM extract_priority(val_desc_t *vdp, uint_t cnt, void *arg)
1903*11878SVenu.Iyer@Sun.COM {
1904*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t *mrp = arg;
1905*11878SVenu.Iyer@Sun.COM 
1906*11878SVenu.Iyer@Sun.COM 	if (cnt != 1)
1907*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVAL);
1908*11878SVenu.Iyer@Sun.COM 
1909*11878SVenu.Iyer@Sun.COM 	mrp->mrp_priority = (mac_priority_level_t)vdp->vd_val;
1910*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_PRIORITY;
1911*11878SVenu.Iyer@Sun.COM 
1912*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
1913*11878SVenu.Iyer@Sun.COM }
1914*11878SVenu.Iyer@Sun.COM 
1915*11878SVenu.Iyer@Sun.COM /*
1916*11878SVenu.Iyer@Sun.COM  * Determines the size of the structure that needs to be sent to drivers
1917*11878SVenu.Iyer@Sun.COM  * for retrieving the property range values.
1918*11878SVenu.Iyer@Sun.COM  */
1919*11878SVenu.Iyer@Sun.COM static int
1920*11878SVenu.Iyer@Sun.COM i_dladm_range_size(mac_propval_range_t *r, size_t *sz)
19218275SEric Cheng {
1922*11878SVenu.Iyer@Sun.COM 	uint_t count = r->mpr_count;
1923*11878SVenu.Iyer@Sun.COM 
1924*11878SVenu.Iyer@Sun.COM 	*sz = sizeof (mac_propval_range_t);
1925*11878SVenu.Iyer@Sun.COM 	--count;
1926*11878SVenu.Iyer@Sun.COM 
1927*11878SVenu.Iyer@Sun.COM 	switch (r->mpr_type) {
1928*11878SVenu.Iyer@Sun.COM 	case MAC_PROPVAL_UINT32:
1929*11878SVenu.Iyer@Sun.COM 		*sz += (count * sizeof (mac_propval_uint32_range_t));
1930*11878SVenu.Iyer@Sun.COM 		return (0);
1931*11878SVenu.Iyer@Sun.COM 	default:
1932*11878SVenu.Iyer@Sun.COM 		break;
1933*11878SVenu.Iyer@Sun.COM 	}
1934*11878SVenu.Iyer@Sun.COM 	*sz = 0;
1935*11878SVenu.Iyer@Sun.COM 	return (EINVAL);
1936*11878SVenu.Iyer@Sun.COM }
1937*11878SVenu.Iyer@Sun.COM 
1938*11878SVenu.Iyer@Sun.COM 
1939*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
1940*11878SVenu.Iyer@Sun.COM static dladm_status_t
1941*11878SVenu.Iyer@Sun.COM check_rings(dladm_handle_t handle, prop_desc_t *pdp,
1942*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
1943*11878SVenu.Iyer@Sun.COM     val_desc_t *v, datalink_media_t media)
1944*11878SVenu.Iyer@Sun.COM {
19458275SEric Cheng 	if (val_cnt != 1)
1946*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVAL);
1947*11878SVenu.Iyer@Sun.COM 	if (strncasecmp(prop_val[0], "hw", strlen("hw")) == 0) {
1948*11878SVenu.Iyer@Sun.COM 		v->vd_val = UNSPEC_VAL;
1949*11878SVenu.Iyer@Sun.COM 	} else if (strncasecmp(prop_val[0], "sw", strlen("sw")) == 0) {
1950*11878SVenu.Iyer@Sun.COM 		v->vd_val = 0;
1951*11878SVenu.Iyer@Sun.COM 	} else {
1952*11878SVenu.Iyer@Sun.COM 		v->vd_val = strtoul(prop_val[0], NULL, 0);
1953*11878SVenu.Iyer@Sun.COM 		if (v->vd_val == 0)
1954*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADVAL);
1955*11878SVenu.Iyer@Sun.COM 	}
1956*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
1957*11878SVenu.Iyer@Sun.COM }
1958*11878SVenu.Iyer@Sun.COM 
1959*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
1960*11878SVenu.Iyer@Sun.COM static dladm_status_t
1961*11878SVenu.Iyer@Sun.COM get_rings_range(dladm_handle_t handle, prop_desc_t *pdp,
1962*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
1963*11878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
1964*11878SVenu.Iyer@Sun.COM {
1965*11878SVenu.Iyer@Sun.COM 	dld_ioc_macprop_t *dip;
1966*11878SVenu.Iyer@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
1967*11878SVenu.Iyer@Sun.COM 	mac_propval_range_t *rangep;
1968*11878SVenu.Iyer@Sun.COM 	size_t	sz;
1969*11878SVenu.Iyer@Sun.COM 	mac_propval_uint32_range_t *ur;
1970*11878SVenu.Iyer@Sun.COM 
1971*11878SVenu.Iyer@Sun.COM 	sz = sizeof (mac_propval_range_t);
1972*11878SVenu.Iyer@Sun.COM 
1973*11878SVenu.Iyer@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
1974*11878SVenu.Iyer@Sun.COM 	    &status)) == NULL)
1975*11878SVenu.Iyer@Sun.COM 		return (status);
1976*11878SVenu.Iyer@Sun.COM 
1977*11878SVenu.Iyer@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
1978*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
19798275SEric Cheng 		return (status);
1980*11878SVenu.Iyer@Sun.COM 
1981*11878SVenu.Iyer@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
1982*11878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
1983*11878SVenu.Iyer@Sun.COM 	ur = &rangep->mpr_range_uint32[0];
1984*11878SVenu.Iyer@Sun.COM 	/* This is the case where the dev doesn't have any rings/groups */
1985*11878SVenu.Iyer@Sun.COM 	if (rangep->mpr_count == 0) {
1986*11878SVenu.Iyer@Sun.COM 		(*prop_val)[0] = '\0';
1987*11878SVenu.Iyer@Sun.COM 	/*
1988*11878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings, but static
1989*11878SVenu.Iyer@Sun.COM 	 * grouping.
1990*11878SVenu.Iyer@Sun.COM 	 */
1991*11878SVenu.Iyer@Sun.COM 	} else if (ur->mpur_min == ur->mpur_max &&
1992*11878SVenu.Iyer@Sun.COM 	    ur->mpur_max == 0) {
1993*11878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw");
1994*11878SVenu.Iyer@Sun.COM 	/*
1995*11878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings and dynamic
1996*11878SVenu.Iyer@Sun.COM 	 * grouping, but has only one value (say 2 rings and 2 groups).
1997*11878SVenu.Iyer@Sun.COM 	 */
1998*11878SVenu.Iyer@Sun.COM 	} else if (ur->mpur_min == ur->mpur_max) {
1999*11878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "sw,hw,%d",
2000*11878SVenu.Iyer@Sun.COM 		    ur->mpur_min);
2001*11878SVenu.Iyer@Sun.COM 	/*
2002*11878SVenu.Iyer@Sun.COM 	 * This is the case where the dev supports rings and dynamic
2003*11878SVenu.Iyer@Sun.COM 	 * grouping and has a range of rings.
2004*11878SVenu.Iyer@Sun.COM 	 */
2005*11878SVenu.Iyer@Sun.COM 	} else {
2006*11878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX,
2007*11878SVenu.Iyer@Sun.COM 		    "sw,hw,<%ld-%ld>", ur->mpur_min, ur->mpur_max);
20088275SEric Cheng 	}
2009*11878SVenu.Iyer@Sun.COM 	free(dip);
2010*11878SVenu.Iyer@Sun.COM 	return (status);
2011*11878SVenu.Iyer@Sun.COM }
2012*11878SVenu.Iyer@Sun.COM 
2013*11878SVenu.Iyer@Sun.COM 
2014*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2015*11878SVenu.Iyer@Sun.COM static dladm_status_t
2016*11878SVenu.Iyer@Sun.COM get_rxrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2017*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2018*11878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
2019*11878SVenu.Iyer@Sun.COM {
2020*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
2021*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
2022*11878SVenu.Iyer@Sun.COM 	uint32_t		nrings = 0;
2023*11878SVenu.Iyer@Sun.COM 
2024*11878SVenu.Iyer@Sun.COM 	/*
2025*11878SVenu.Iyer@Sun.COM 	 * Get the number of (effective-)rings from the resource property.
2026*11878SVenu.Iyer@Sun.COM 	 */
2027*11878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "rxrings-effective") == 0) {
2028*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
2029*11878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
2030*11878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
2031*11878SVenu.Iyer@Sun.COM 	} else {
2032*11878SVenu.Iyer@Sun.COM 		/*
2033*11878SVenu.Iyer@Sun.COM 		 * Get the permissions from the "rxrings" property.
2034*11878SVenu.Iyer@Sun.COM 		 */
2035*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "rxrings",
2036*11878SVenu.Iyer@Sun.COM 		    flags, perm_flags, NULL, 0);
2037*11878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
2038*11878SVenu.Iyer@Sun.COM 			return (status);
2039*11878SVenu.Iyer@Sun.COM 
2040*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
2041*11878SVenu.Iyer@Sun.COM 		    "resource", flags, NULL, &mrp, sizeof (mrp));
20428275SEric Cheng 	}
20438275SEric Cheng 
2044*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2045*11878SVenu.Iyer@Sun.COM 		return (status);
2046*11878SVenu.Iyer@Sun.COM 
2047*11878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_RX_RINGS) == 0) {
2048*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
2049*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
2050*11878SVenu.Iyer@Sun.COM 	}
2051*11878SVenu.Iyer@Sun.COM 	nrings = mrp.mrp_nrxrings;
2052*11878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
2053*11878SVenu.Iyer@Sun.COM 	if (mrp.mrp_mask & MRP_RXRINGS_UNSPEC)
2054*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2055*11878SVenu.Iyer@Sun.COM 	else if (nrings == 0)
2056*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2057*11878SVenu.Iyer@Sun.COM 	else
2058*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
20598275SEric Cheng 	return (DLADM_STATUS_OK);
20608275SEric Cheng }
20618275SEric Cheng 
20628275SEric Cheng /* ARGSUSED */
20638275SEric Cheng dladm_status_t
2064*11878SVenu.Iyer@Sun.COM extract_rxrings(val_desc_t *vdp, uint_t cnt, void *arg)
20658275SEric Cheng {
2066*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
2067*11878SVenu.Iyer@Sun.COM 
2068*11878SVenu.Iyer@Sun.COM 	mrp->mrp_nrxrings = 0;
2069*11878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL)
2070*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RINGS_RESET;
2071*11878SVenu.Iyer@Sun.COM 	else if (vdp->vd_val == UNSPEC_VAL)
2072*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RXRINGS_UNSPEC;
2073*11878SVenu.Iyer@Sun.COM 	else
2074*11878SVenu.Iyer@Sun.COM 		mrp->mrp_nrxrings = vdp->vd_val;
2075*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_RX_RINGS;
20768275SEric Cheng 
20778275SEric Cheng 	return (DLADM_STATUS_OK);
20788275SEric Cheng }
20798275SEric Cheng 
20808275SEric Cheng /* ARGSUSED */
20818275SEric Cheng static dladm_status_t
2082*11878SVenu.Iyer@Sun.COM get_txrings(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2083*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media,
2084*11878SVenu.Iyer@Sun.COM     uint_t flags, uint_t *perm_flags)
2085*11878SVenu.Iyer@Sun.COM {
2086*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
2087*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
2088*11878SVenu.Iyer@Sun.COM 	uint32_t		nrings = 0;
2089*11878SVenu.Iyer@Sun.COM 
2090*11878SVenu.Iyer@Sun.COM 
2091*11878SVenu.Iyer@Sun.COM 	/*
2092*11878SVenu.Iyer@Sun.COM 	 * Get the number of (effective-)rings from the resource property.
2093*11878SVenu.Iyer@Sun.COM 	 */
2094*11878SVenu.Iyer@Sun.COM 	if (strcmp(pdp->pd_name, "txrings-effective") == 0) {
2095*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid,
2096*11878SVenu.Iyer@Sun.COM 		    "resource-effective", flags, perm_flags, &mrp,
2097*11878SVenu.Iyer@Sun.COM 		    sizeof (mrp));
2098*11878SVenu.Iyer@Sun.COM 	} else {
2099*11878SVenu.Iyer@Sun.COM 		/*
2100*11878SVenu.Iyer@Sun.COM 		 * Get the permissions from the "txrings" property.
2101*11878SVenu.Iyer@Sun.COM 		 */
2102*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "txrings",
2103*11878SVenu.Iyer@Sun.COM 		    flags, perm_flags, NULL, 0);
2104*11878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
2105*11878SVenu.Iyer@Sun.COM 			return (status);
2106*11878SVenu.Iyer@Sun.COM 
2107*11878SVenu.Iyer@Sun.COM 		/*
2108*11878SVenu.Iyer@Sun.COM 		 * Get the number of rings from the "resource" property.
2109*11878SVenu.Iyer@Sun.COM 		 */
2110*11878SVenu.Iyer@Sun.COM 		status = i_dladm_get_public_prop(handle, linkid, "resource",
2111*11878SVenu.Iyer@Sun.COM 		    flags, NULL, &mrp, sizeof (mrp));
2112*11878SVenu.Iyer@Sun.COM 	}
2113*11878SVenu.Iyer@Sun.COM 
2114*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2115*11878SVenu.Iyer@Sun.COM 		return (status);
2116*11878SVenu.Iyer@Sun.COM 
2117*11878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_TX_RINGS) == 0) {
2118*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
2119*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
2120*11878SVenu.Iyer@Sun.COM 	}
2121*11878SVenu.Iyer@Sun.COM 	nrings = mrp.mrp_ntxrings;
2122*11878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
2123*11878SVenu.Iyer@Sun.COM 	if (mrp.mrp_mask & MRP_TXRINGS_UNSPEC)
2124*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "hw");
2125*11878SVenu.Iyer@Sun.COM 	else if (nrings == 0)
2126*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "sw");
2127*11878SVenu.Iyer@Sun.COM 	else
2128*11878SVenu.Iyer@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", nrings);
2129*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2130*11878SVenu.Iyer@Sun.COM }
2131*11878SVenu.Iyer@Sun.COM 
2132*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2133*11878SVenu.Iyer@Sun.COM dladm_status_t
2134*11878SVenu.Iyer@Sun.COM extract_txrings(val_desc_t *vdp, uint_t cnt, void *arg)
2135*11878SVenu.Iyer@Sun.COM {
2136*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = (mac_resource_props_t *)arg;
2137*11878SVenu.Iyer@Sun.COM 
2138*11878SVenu.Iyer@Sun.COM 	mrp->mrp_ntxrings = 0;
2139*11878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == RESET_VAL)
2140*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_RINGS_RESET;
2141*11878SVenu.Iyer@Sun.COM 	else if (vdp->vd_val == UNSPEC_VAL)
2142*11878SVenu.Iyer@Sun.COM 		mrp->mrp_mask = MRP_TXRINGS_UNSPEC;
2143*11878SVenu.Iyer@Sun.COM 	else
2144*11878SVenu.Iyer@Sun.COM 		mrp->mrp_ntxrings = vdp->vd_val;
2145*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_TX_RINGS;
2146*11878SVenu.Iyer@Sun.COM 
2147*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2148*11878SVenu.Iyer@Sun.COM }
2149*11878SVenu.Iyer@Sun.COM 
2150*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2151*11878SVenu.Iyer@Sun.COM static dladm_status_t
2152*11878SVenu.Iyer@Sun.COM get_cntavail(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2153*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
2154*11878SVenu.Iyer@Sun.COM     uint_t *perm_flags)
2155*11878SVenu.Iyer@Sun.COM {
2156*11878SVenu.Iyer@Sun.COM 	if (flags & DLD_PROP_DEFAULT)
2157*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
2158*11878SVenu.Iyer@Sun.COM 
2159*11878SVenu.Iyer@Sun.COM 	return (get_uint32(handle, pdp, linkid, prop_val, val_cnt, media,
2160*11878SVenu.Iyer@Sun.COM 	    flags, perm_flags));
2161*11878SVenu.Iyer@Sun.COM }
2162*11878SVenu.Iyer@Sun.COM 
2163*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2164*11878SVenu.Iyer@Sun.COM static dladm_status_t
2165*11878SVenu.Iyer@Sun.COM set_resource(dladm_handle_t handle, prop_desc_t *pdp,
216610734SEric Cheng     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt,
216710734SEric Cheng     uint_t flags, datalink_media_t media)
216810734SEric Cheng {
216910734SEric Cheng 	mac_resource_props_t	mrp;
217010734SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
217110734SEric Cheng 	dld_ioc_macprop_t	*dip;
2172*11878SVenu.Iyer@Sun.COM 	int			i;
217310734SEric Cheng 
217410734SEric Cheng 	bzero(&mrp, sizeof (mac_resource_props_t));
2175*11878SVenu.Iyer@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, "resource",
217610734SEric Cheng 	    flags, &status);
217710734SEric Cheng 
217810734SEric Cheng 	if (dip == NULL)
217910734SEric Cheng 		return (status);
218010734SEric Cheng 
2181*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
2182*11878SVenu.Iyer@Sun.COM 		resource_prop_t	*rp = &rsrc_prop_table[i];
2183*11878SVenu.Iyer@Sun.COM 
2184*11878SVenu.Iyer@Sun.COM 		if (strcmp(pdp->pd_name, rp->rp_name) != 0)
2185*11878SVenu.Iyer@Sun.COM 			continue;
2186*11878SVenu.Iyer@Sun.COM 
2187*11878SVenu.Iyer@Sun.COM 		status = rp->rp_extract(vdp, val_cnt, &mrp);
218810734SEric Cheng 		if (status != DLADM_STATUS_OK)
218910734SEric Cheng 			goto done;
219010734SEric Cheng 
2191*11878SVenu.Iyer@Sun.COM 		break;
219210734SEric Cheng 	}
219310734SEric Cheng 
219410734SEric Cheng 	(void) memcpy(dip->pr_val, &mrp, dip->pr_valsize);
219510734SEric Cheng 	status = i_dladm_macprop(handle, dip, B_TRUE);
219610734SEric Cheng 
219710734SEric Cheng done:
219810734SEric Cheng 	free(dip);
219910734SEric Cheng 	return (status);
220010734SEric Cheng }
220110734SEric Cheng 
220210734SEric Cheng /* ARGSUSED */
220310734SEric Cheng static dladm_status_t
2204*11878SVenu.Iyer@Sun.COM get_protection(dladm_handle_t handle, prop_desc_t *pdp,
220510734SEric Cheng     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
220610734SEric Cheng     datalink_media_t media, uint_t flags, uint_t *perm_flags)
220710734SEric Cheng {
2208*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
2209*11878SVenu.Iyer@Sun.COM 	mac_protect_t		*p;
2210*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
2211*11878SVenu.Iyer@Sun.COM 	uint32_t		i, cnt = 0, setbits[32];
2212*11878SVenu.Iyer@Sun.COM 
2213*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2214*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
2215*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2216*11878SVenu.Iyer@Sun.COM 		return (status);
2217*11878SVenu.Iyer@Sun.COM 
2218*11878SVenu.Iyer@Sun.COM 	p = &mrp.mrp_protect;
2219*11878SVenu.Iyer@Sun.COM 	if ((mrp.mrp_mask & MRP_PROTECT) == 0) {
2220*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
2221*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
2222*11878SVenu.Iyer@Sun.COM 	}
2223*11878SVenu.Iyer@Sun.COM 	dladm_find_setbits32(p->mp_types, setbits, &cnt);
2224*11878SVenu.Iyer@Sun.COM 	if (cnt > *val_cnt)
2225*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2226*11878SVenu.Iyer@Sun.COM 
2227*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < cnt; i++)
2228*11878SVenu.Iyer@Sun.COM 		(void) dladm_protect2str(setbits[i], prop_val[i]);
2229*11878SVenu.Iyer@Sun.COM 
2230*11878SVenu.Iyer@Sun.COM 	*val_cnt = cnt;
2231*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2232*11878SVenu.Iyer@Sun.COM }
2233*11878SVenu.Iyer@Sun.COM 
2234*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2235*11878SVenu.Iyer@Sun.COM static dladm_status_t
2236*11878SVenu.Iyer@Sun.COM get_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2237*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2238*11878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
2239*11878SVenu.Iyer@Sun.COM {
224010734SEric Cheng 	mac_resource_props_t	mrp;
224110734SEric Cheng 	mac_protect_t		*p;
224210734SEric Cheng 	dladm_status_t		status;
224310734SEric Cheng 	int			i;
224410734SEric Cheng 
2245*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2246*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
2247*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
224810734SEric Cheng 		return (status);
224910734SEric Cheng 
225010734SEric Cheng 	p = &mrp.mrp_protect;
2251*11878SVenu.Iyer@Sun.COM 	if (p->mp_ipaddrcnt == 0) {
2252*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
225310734SEric Cheng 		return (DLADM_STATUS_OK);
225410734SEric Cheng 	}
2255*11878SVenu.Iyer@Sun.COM 	if (p->mp_ipaddrcnt > *val_cnt)
2256*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2257*11878SVenu.Iyer@Sun.COM 
2258*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < p->mp_ipaddrcnt; i++) {
2259*11878SVenu.Iyer@Sun.COM 		if (p->mp_ipaddrs[i].ip_version == IPV4_VERSION) {
2260*11878SVenu.Iyer@Sun.COM 			ipaddr_t	v4addr;
2261*11878SVenu.Iyer@Sun.COM 
2262*11878SVenu.Iyer@Sun.COM 			v4addr = V4_PART_OF_V6(p->mp_ipaddrs[i].ip_addr);
2263*11878SVenu.Iyer@Sun.COM 			(void) dladm_ipv4addr2str(&v4addr, prop_val[i]);
2264*11878SVenu.Iyer@Sun.COM 		} else {
2265*11878SVenu.Iyer@Sun.COM 			(void) dladm_ipv6addr2str(&p->mp_ipaddrs[i].ip_addr,
226610734SEric Cheng 			    prop_val[i]);
226710734SEric Cheng 		}
226810734SEric Cheng 	}
2269*11878SVenu.Iyer@Sun.COM 	*val_cnt = p->mp_ipaddrcnt;
227010734SEric Cheng 	return (DLADM_STATUS_OK);
227110734SEric Cheng }
227210734SEric Cheng 
227310734SEric Cheng dladm_status_t
2274*11878SVenu.Iyer@Sun.COM extract_protection(val_desc_t *vdp, uint_t cnt, void *arg)
227510734SEric Cheng {
227610734SEric Cheng 	mac_resource_props_t	*mrp = arg;
227710734SEric Cheng 	uint32_t		types = 0;
227810734SEric Cheng 	int			i;
227910734SEric Cheng 
228010734SEric Cheng 	for (i = 0; i < cnt; i++)
228110734SEric Cheng 		types |= (uint32_t)vdp[i].vd_val;
228210734SEric Cheng 
228310734SEric Cheng 	mrp->mrp_protect.mp_types = types;
228410734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
228510734SEric Cheng 	return (DLADM_STATUS_OK);
228610734SEric Cheng }
228710734SEric Cheng 
228810734SEric Cheng dladm_status_t
2289*11878SVenu.Iyer@Sun.COM extract_allowedips(val_desc_t *vdp, uint_t cnt, void *arg)
229010734SEric Cheng {
229110734SEric Cheng 	mac_resource_props_t	*mrp = arg;
229210734SEric Cheng 	mac_protect_t		*p = &mrp->mrp_protect;
229310734SEric Cheng 	int			i;
229410734SEric Cheng 
229510734SEric Cheng 	if (vdp->vd_val == 0) {
229610734SEric Cheng 		cnt = (uint_t)-1;
229710734SEric Cheng 	} else {
2298*11878SVenu.Iyer@Sun.COM 		for (i = 0; i < cnt; i++) {
2299*11878SVenu.Iyer@Sun.COM 			bcopy((void *)vdp[i].vd_val, &p->mp_ipaddrs[i],
2300*11878SVenu.Iyer@Sun.COM 			    sizeof (mac_ipaddr_t));
2301*11878SVenu.Iyer@Sun.COM 		}
230210734SEric Cheng 	}
230310734SEric Cheng 	p->mp_ipaddrcnt = cnt;
230410734SEric Cheng 	mrp->mrp_mask |= MRP_PROTECT;
230510734SEric Cheng 	return (DLADM_STATUS_OK);
230610734SEric Cheng }
230710734SEric Cheng 
2308*11878SVenu.Iyer@Sun.COM static dladm_status_t
2309*11878SVenu.Iyer@Sun.COM check_single_ip(char *buf, mac_ipaddr_t *addr)
2310*11878SVenu.Iyer@Sun.COM {
2311*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
2312*11878SVenu.Iyer@Sun.COM 	ipaddr_t	v4addr;
2313*11878SVenu.Iyer@Sun.COM 	in6_addr_t	v6addr;
2314*11878SVenu.Iyer@Sun.COM 	boolean_t	isv4 = B_TRUE;
2315*11878SVenu.Iyer@Sun.COM 
2316*11878SVenu.Iyer@Sun.COM 	status = dladm_str2ipv4addr(buf, &v4addr);
2317*11878SVenu.Iyer@Sun.COM 	if (status == DLADM_STATUS_INVALID_IP) {
2318*11878SVenu.Iyer@Sun.COM 		status = dladm_str2ipv6addr(buf, &v6addr);
2319*11878SVenu.Iyer@Sun.COM 		if (status == DLADM_STATUS_OK)
2320*11878SVenu.Iyer@Sun.COM 			isv4 = B_FALSE;
2321*11878SVenu.Iyer@Sun.COM 	}
2322*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2323*11878SVenu.Iyer@Sun.COM 		return (status);
2324*11878SVenu.Iyer@Sun.COM 
2325*11878SVenu.Iyer@Sun.COM 	if (isv4) {
2326*11878SVenu.Iyer@Sun.COM 		if (v4addr == INADDR_ANY)
2327*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_INVALID_IP);
2328*11878SVenu.Iyer@Sun.COM 
2329*11878SVenu.Iyer@Sun.COM 		IN6_IPADDR_TO_V4MAPPED(v4addr, &addr->ip_addr);
2330*11878SVenu.Iyer@Sun.COM 		addr->ip_version = IPV4_VERSION;
2331*11878SVenu.Iyer@Sun.COM 	} else {
2332*11878SVenu.Iyer@Sun.COM 		if (IN6_IS_ADDR_UNSPECIFIED(&v6addr))
2333*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_INVALID_IP);
2334*11878SVenu.Iyer@Sun.COM 
2335*11878SVenu.Iyer@Sun.COM 		addr->ip_addr = v6addr;
2336*11878SVenu.Iyer@Sun.COM 		addr->ip_version = IPV6_VERSION;
2337*11878SVenu.Iyer@Sun.COM 	}
2338*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2339*11878SVenu.Iyer@Sun.COM }
2340*11878SVenu.Iyer@Sun.COM 
234110734SEric Cheng /* ARGSUSED */
234210734SEric Cheng static dladm_status_t
2343*11878SVenu.Iyer@Sun.COM check_allowedips(dladm_handle_t handle, prop_desc_t *pdp,
2344*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
234510734SEric Cheng     val_desc_t *vdp, datalink_media_t media)
234610734SEric Cheng {
234710734SEric Cheng 	dladm_status_t	status;
2348*11878SVenu.Iyer@Sun.COM 	mac_ipaddr_t	*addr;
234910734SEric Cheng 	int		i;
235010734SEric Cheng 
235110734SEric Cheng 	if (val_cnt > MPT_MAXIPADDR)
235210734SEric Cheng 		return (DLADM_STATUS_BADVALCNT);
235310734SEric Cheng 
235410734SEric Cheng 	for (i = 0; i < val_cnt; i++) {
2355*11878SVenu.Iyer@Sun.COM 		if ((addr = calloc(1, sizeof (mac_ipaddr_t))) == NULL) {
2356*11878SVenu.Iyer@Sun.COM 			status = DLADM_STATUS_NOMEM;
2357*11878SVenu.Iyer@Sun.COM 			goto fail;
2358*11878SVenu.Iyer@Sun.COM 		}
2359*11878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)addr;
2360*11878SVenu.Iyer@Sun.COM 
2361*11878SVenu.Iyer@Sun.COM 		status = check_single_ip(prop_val[i], addr);
236210734SEric Cheng 		if (status != DLADM_STATUS_OK)
2363*11878SVenu.Iyer@Sun.COM 			goto fail;
2364*11878SVenu.Iyer@Sun.COM 	}
2365*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2366*11878SVenu.Iyer@Sun.COM 
2367*11878SVenu.Iyer@Sun.COM fail:
2368*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
2369*11878SVenu.Iyer@Sun.COM 		free((void *)vdp[i].vd_val);
2370*11878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = NULL;
2371*11878SVenu.Iyer@Sun.COM 	}
2372*11878SVenu.Iyer@Sun.COM 	return (status);
2373*11878SVenu.Iyer@Sun.COM }
2374*11878SVenu.Iyer@Sun.COM 
2375*11878SVenu.Iyer@Sun.COM static void
2376*11878SVenu.Iyer@Sun.COM dladm_cid2str(mac_dhcpcid_t *cid, char *buf)
2377*11878SVenu.Iyer@Sun.COM {
2378*11878SVenu.Iyer@Sun.COM 	char	tmp_buf[DLADM_STRSIZE];
2379*11878SVenu.Iyer@Sun.COM 	uint_t	hexlen;
2380*11878SVenu.Iyer@Sun.COM 
2381*11878SVenu.Iyer@Sun.COM 	switch (cid->dc_form) {
2382*11878SVenu.Iyer@Sun.COM 	case CIDFORM_TYPED: {
2383*11878SVenu.Iyer@Sun.COM 		uint16_t	duidtype, hwtype;
2384*11878SVenu.Iyer@Sun.COM 		uint32_t	timestamp, ennum;
2385*11878SVenu.Iyer@Sun.COM 		char		*lladdr;
2386*11878SVenu.Iyer@Sun.COM 
2387*11878SVenu.Iyer@Sun.COM 		if (cid->dc_len < sizeof (duidtype))
2388*11878SVenu.Iyer@Sun.COM 			goto fail;
2389*11878SVenu.Iyer@Sun.COM 
2390*11878SVenu.Iyer@Sun.COM 		bcopy(cid->dc_id, &duidtype, sizeof (duidtype));
2391*11878SVenu.Iyer@Sun.COM 		duidtype = ntohs(duidtype);
2392*11878SVenu.Iyer@Sun.COM 		switch (duidtype) {
2393*11878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LLT: {
2394*11878SVenu.Iyer@Sun.COM 			duid_llt_t	llt;
2395*11878SVenu.Iyer@Sun.COM 
2396*11878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (llt))
2397*11878SVenu.Iyer@Sun.COM 				goto fail;
2398*11878SVenu.Iyer@Sun.COM 
2399*11878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &llt, sizeof (llt));
2400*11878SVenu.Iyer@Sun.COM 			hwtype = ntohs(llt.dllt_hwtype);
2401*11878SVenu.Iyer@Sun.COM 			timestamp = ntohl(llt.dllt_time);
2402*11878SVenu.Iyer@Sun.COM 			lladdr = _link_ntoa(cid->dc_id + sizeof (llt),
2403*11878SVenu.Iyer@Sun.COM 			    NULL, cid->dc_len - sizeof (llt), IFT_OTHER);
2404*11878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
2405*11878SVenu.Iyer@Sun.COM 				goto fail;
2406*11878SVenu.Iyer@Sun.COM 
2407*11878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%d.%s",
2408*11878SVenu.Iyer@Sun.COM 			    duidtype, hwtype, timestamp, lladdr);
2409*11878SVenu.Iyer@Sun.COM 			free(lladdr);
2410*11878SVenu.Iyer@Sun.COM 			break;
2411*11878SVenu.Iyer@Sun.COM 		}
2412*11878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_EN: {
2413*11878SVenu.Iyer@Sun.COM 			duid_en_t	en;
2414*11878SVenu.Iyer@Sun.COM 
2415*11878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (en))
2416*11878SVenu.Iyer@Sun.COM 				goto fail;
2417*11878SVenu.Iyer@Sun.COM 
2418*11878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &en, sizeof (en));
2419*11878SVenu.Iyer@Sun.COM 			ennum = DHCPV6_GET_ENTNUM(&en);
2420*11878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
2421*11878SVenu.Iyer@Sun.COM 			if (octet_to_hexascii(cid->dc_id + sizeof (en),
2422*11878SVenu.Iyer@Sun.COM 			    cid->dc_len - sizeof (en), tmp_buf, &hexlen) != 0)
2423*11878SVenu.Iyer@Sun.COM 				goto fail;
2424*11878SVenu.Iyer@Sun.COM 
2425*11878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2426*11878SVenu.Iyer@Sun.COM 			    duidtype, ennum, tmp_buf);
2427*11878SVenu.Iyer@Sun.COM 			break;
2428*11878SVenu.Iyer@Sun.COM 		}
2429*11878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LL: {
2430*11878SVenu.Iyer@Sun.COM 			duid_ll_t	ll;
2431*11878SVenu.Iyer@Sun.COM 
2432*11878SVenu.Iyer@Sun.COM 			if (cid->dc_len < sizeof (ll))
2433*11878SVenu.Iyer@Sun.COM 				goto fail;
2434*11878SVenu.Iyer@Sun.COM 
2435*11878SVenu.Iyer@Sun.COM 			bcopy(cid->dc_id, &ll, sizeof (ll));
2436*11878SVenu.Iyer@Sun.COM 			hwtype = ntohs(ll.dll_hwtype);
2437*11878SVenu.Iyer@Sun.COM 			lladdr = _link_ntoa(cid->dc_id + sizeof (ll),
2438*11878SVenu.Iyer@Sun.COM 			    NULL, cid->dc_len - sizeof (ll), IFT_OTHER);
2439*11878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
2440*11878SVenu.Iyer@Sun.COM 				goto fail;
2441*11878SVenu.Iyer@Sun.COM 
2442*11878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%d.%s",
2443*11878SVenu.Iyer@Sun.COM 			    duidtype, hwtype, lladdr);
2444*11878SVenu.Iyer@Sun.COM 			free(lladdr);
2445*11878SVenu.Iyer@Sun.COM 			break;
2446*11878SVenu.Iyer@Sun.COM 		}
2447*11878SVenu.Iyer@Sun.COM 		default: {
2448*11878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
2449*11878SVenu.Iyer@Sun.COM 			if (octet_to_hexascii(cid->dc_id + sizeof (duidtype),
2450*11878SVenu.Iyer@Sun.COM 			    cid->dc_len - sizeof (duidtype),
2451*11878SVenu.Iyer@Sun.COM 			    tmp_buf, &hexlen) != 0)
2452*11878SVenu.Iyer@Sun.COM 				goto fail;
2453*11878SVenu.Iyer@Sun.COM 
2454*11878SVenu.Iyer@Sun.COM 			(void) snprintf(buf, DLADM_STRSIZE, "%d.%s",
2455*11878SVenu.Iyer@Sun.COM 			    duidtype, tmp_buf);
2456*11878SVenu.Iyer@Sun.COM 		}
2457*11878SVenu.Iyer@Sun.COM 		}
2458*11878SVenu.Iyer@Sun.COM 		break;
2459*11878SVenu.Iyer@Sun.COM 	}
2460*11878SVenu.Iyer@Sun.COM 	case CIDFORM_HEX: {
2461*11878SVenu.Iyer@Sun.COM 		hexlen = sizeof (tmp_buf);
2462*11878SVenu.Iyer@Sun.COM 		if (octet_to_hexascii(cid->dc_id, cid->dc_len,
2463*11878SVenu.Iyer@Sun.COM 		    tmp_buf, &hexlen) != 0)
2464*11878SVenu.Iyer@Sun.COM 			goto fail;
2465*11878SVenu.Iyer@Sun.COM 
2466*11878SVenu.Iyer@Sun.COM 		(void) snprintf(buf, DLADM_STRSIZE, "0x%s", tmp_buf);
2467*11878SVenu.Iyer@Sun.COM 		break;
2468*11878SVenu.Iyer@Sun.COM 	}
2469*11878SVenu.Iyer@Sun.COM 	case CIDFORM_STR: {
2470*11878SVenu.Iyer@Sun.COM 		int	i;
2471*11878SVenu.Iyer@Sun.COM 
2472*11878SVenu.Iyer@Sun.COM 		for (i = 0; i < cid->dc_len; i++) {
2473*11878SVenu.Iyer@Sun.COM 			if (!isprint(cid->dc_id[i]))
2474*11878SVenu.Iyer@Sun.COM 				goto fail;
2475*11878SVenu.Iyer@Sun.COM 		}
2476*11878SVenu.Iyer@Sun.COM 		(void) snprintf(buf, DLADM_STRSIZE, "%s", cid->dc_id);
2477*11878SVenu.Iyer@Sun.COM 		break;
2478*11878SVenu.Iyer@Sun.COM 	}
2479*11878SVenu.Iyer@Sun.COM 	default:
2480*11878SVenu.Iyer@Sun.COM 		goto fail;
248110734SEric Cheng 	}
2482*11878SVenu.Iyer@Sun.COM 	return;
2483*11878SVenu.Iyer@Sun.COM 
2484*11878SVenu.Iyer@Sun.COM fail:
2485*11878SVenu.Iyer@Sun.COM 	(void) snprintf(buf, DLADM_STRSIZE, "<unknown>");
2486*11878SVenu.Iyer@Sun.COM }
2487*11878SVenu.Iyer@Sun.COM 
2488*11878SVenu.Iyer@Sun.COM static dladm_status_t
2489*11878SVenu.Iyer@Sun.COM dladm_str2cid(char *buf, mac_dhcpcid_t *cid)
2490*11878SVenu.Iyer@Sun.COM {
2491*11878SVenu.Iyer@Sun.COM 	char	*ptr = buf;
2492*11878SVenu.Iyer@Sun.COM 	char	tmp_buf[DLADM_STRSIZE];
2493*11878SVenu.Iyer@Sun.COM 	uint_t	hexlen, cidlen;
2494*11878SVenu.Iyer@Sun.COM 
2495*11878SVenu.Iyer@Sun.COM 	bzero(cid, sizeof (*cid));
2496*11878SVenu.Iyer@Sun.COM 	if (isdigit(*ptr) &&
2497*11878SVenu.Iyer@Sun.COM 	    ptr[strspn(ptr, "0123456789")] == '.') {
2498*11878SVenu.Iyer@Sun.COM 		char	*cp;
2499*11878SVenu.Iyer@Sun.COM 		ulong_t	duidtype;
2500*11878SVenu.Iyer@Sun.COM 		ulong_t	subtype;
2501*11878SVenu.Iyer@Sun.COM 		ulong_t	timestamp;
2502*11878SVenu.Iyer@Sun.COM 		uchar_t	*lladdr;
2503*11878SVenu.Iyer@Sun.COM 		int	addrlen;
2504*11878SVenu.Iyer@Sun.COM 
2505*11878SVenu.Iyer@Sun.COM 		errno = 0;
2506*11878SVenu.Iyer@Sun.COM 		duidtype = strtoul(ptr, &cp, 0);
2507*11878SVenu.Iyer@Sun.COM 		if (ptr == cp || errno != 0 || *cp != '.' ||
2508*11878SVenu.Iyer@Sun.COM 		    duidtype > USHRT_MAX)
2509*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADARG);
2510*11878SVenu.Iyer@Sun.COM 		ptr = cp + 1;
2511*11878SVenu.Iyer@Sun.COM 
2512*11878SVenu.Iyer@Sun.COM 		if (duidtype != 0 && duidtype <= DHCPV6_DUID_LL) {
2513*11878SVenu.Iyer@Sun.COM 			errno = 0;
2514*11878SVenu.Iyer@Sun.COM 			subtype = strtoul(ptr, &cp, 0);
2515*11878SVenu.Iyer@Sun.COM 			if (ptr == cp || errno != 0 || *cp != '.')
2516*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
2517*11878SVenu.Iyer@Sun.COM 			ptr = cp + 1;
2518*11878SVenu.Iyer@Sun.COM 		}
2519*11878SVenu.Iyer@Sun.COM 		switch (duidtype) {
2520*11878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LLT: {
2521*11878SVenu.Iyer@Sun.COM 			duid_llt_t	llt;
2522*11878SVenu.Iyer@Sun.COM 
2523*11878SVenu.Iyer@Sun.COM 			errno = 0;
2524*11878SVenu.Iyer@Sun.COM 			timestamp = strtoul(ptr, &cp, 0);
2525*11878SVenu.Iyer@Sun.COM 			if (ptr == cp || errno != 0 || *cp != '.')
2526*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
2527*11878SVenu.Iyer@Sun.COM 
2528*11878SVenu.Iyer@Sun.COM 			ptr = cp + 1;
2529*11878SVenu.Iyer@Sun.COM 			lladdr = _link_aton(ptr, &addrlen);
2530*11878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
2531*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
2532*11878SVenu.Iyer@Sun.COM 
2533*11878SVenu.Iyer@Sun.COM 			cidlen = sizeof (llt) + addrlen;
2534*11878SVenu.Iyer@Sun.COM 			if (cidlen > sizeof (cid->dc_id)) {
2535*11878SVenu.Iyer@Sun.COM 				free(lladdr);
2536*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_TOOSMALL);
2537*11878SVenu.Iyer@Sun.COM 			}
2538*11878SVenu.Iyer@Sun.COM 			llt.dllt_dutype = htons(duidtype);
2539*11878SVenu.Iyer@Sun.COM 			llt.dllt_hwtype = htons(subtype);
2540*11878SVenu.Iyer@Sun.COM 			llt.dllt_time = htonl(timestamp);
2541*11878SVenu.Iyer@Sun.COM 			bcopy(&llt, cid->dc_id, sizeof (llt));
2542*11878SVenu.Iyer@Sun.COM 			bcopy(lladdr, cid->dc_id + sizeof (llt), addrlen);
2543*11878SVenu.Iyer@Sun.COM 			free(lladdr);
2544*11878SVenu.Iyer@Sun.COM 			break;
2545*11878SVenu.Iyer@Sun.COM 		}
2546*11878SVenu.Iyer@Sun.COM 		case DHCPV6_DUID_LL: {
2547*11878SVenu.Iyer@Sun.COM 			duid_ll_t	ll;
2548*11878SVenu.Iyer@Sun.COM 
2549*11878SVenu.Iyer@Sun.COM 			lladdr = _link_aton(ptr, &addrlen);
2550*11878SVenu.Iyer@Sun.COM 			if (lladdr == NULL)
2551*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
2552*11878SVenu.Iyer@Sun.COM 
2553*11878SVenu.Iyer@Sun.COM 			cidlen = sizeof (ll) + addrlen;
2554*11878SVenu.Iyer@Sun.COM 			if (cidlen > sizeof (cid->dc_id)) {
2555*11878SVenu.Iyer@Sun.COM 				free(lladdr);
2556*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_TOOSMALL);
2557*11878SVenu.Iyer@Sun.COM 			}
2558*11878SVenu.Iyer@Sun.COM 			ll.dll_dutype = htons(duidtype);
2559*11878SVenu.Iyer@Sun.COM 			ll.dll_hwtype = htons(subtype);
2560*11878SVenu.Iyer@Sun.COM 			bcopy(&ll, cid->dc_id, sizeof (ll));
2561*11878SVenu.Iyer@Sun.COM 			bcopy(lladdr, cid->dc_id + sizeof (ll), addrlen);
2562*11878SVenu.Iyer@Sun.COM 			free(lladdr);
2563*11878SVenu.Iyer@Sun.COM 			break;
2564*11878SVenu.Iyer@Sun.COM 		}
2565*11878SVenu.Iyer@Sun.COM 		default: {
2566*11878SVenu.Iyer@Sun.COM 			hexlen = sizeof (tmp_buf);
2567*11878SVenu.Iyer@Sun.COM 			if (hexascii_to_octet(ptr, strlen(ptr),
2568*11878SVenu.Iyer@Sun.COM 			    tmp_buf, &hexlen) != 0)
2569*11878SVenu.Iyer@Sun.COM 				return (DLADM_STATUS_BADARG);
2570*11878SVenu.Iyer@Sun.COM 
2571*11878SVenu.Iyer@Sun.COM 			if (duidtype == DHCPV6_DUID_EN) {
2572*11878SVenu.Iyer@Sun.COM 				duid_en_t	en;
2573*11878SVenu.Iyer@Sun.COM 
2574*11878SVenu.Iyer@Sun.COM 				en.den_dutype = htons(duidtype);
2575*11878SVenu.Iyer@Sun.COM 				DHCPV6_SET_ENTNUM(&en, subtype);
2576*11878SVenu.Iyer@Sun.COM 
2577*11878SVenu.Iyer@Sun.COM 				cidlen = sizeof (en) + hexlen;
2578*11878SVenu.Iyer@Sun.COM 				if (cidlen > sizeof (cid->dc_id))
2579*11878SVenu.Iyer@Sun.COM 					return (DLADM_STATUS_TOOSMALL);
2580*11878SVenu.Iyer@Sun.COM 
2581*11878SVenu.Iyer@Sun.COM 				bcopy(&en, cid->dc_id, sizeof (en));
2582*11878SVenu.Iyer@Sun.COM 				bcopy(tmp_buf, cid->dc_id + sizeof (en),
2583*11878SVenu.Iyer@Sun.COM 				    hexlen);
2584*11878SVenu.Iyer@Sun.COM 			} else {
2585*11878SVenu.Iyer@Sun.COM 				uint16_t	dutype = htons(duidtype);
2586*11878SVenu.Iyer@Sun.COM 
2587*11878SVenu.Iyer@Sun.COM 				cidlen = sizeof (dutype) + hexlen;
2588*11878SVenu.Iyer@Sun.COM 				if (cidlen > sizeof (cid->dc_id))
2589*11878SVenu.Iyer@Sun.COM 					return (DLADM_STATUS_TOOSMALL);
2590*11878SVenu.Iyer@Sun.COM 
2591*11878SVenu.Iyer@Sun.COM 				bcopy(&dutype, cid->dc_id, sizeof (dutype));
2592*11878SVenu.Iyer@Sun.COM 				bcopy(tmp_buf, cid->dc_id + sizeof (dutype),
2593*11878SVenu.Iyer@Sun.COM 				    hexlen);
2594*11878SVenu.Iyer@Sun.COM 			}
2595*11878SVenu.Iyer@Sun.COM 			break;
2596*11878SVenu.Iyer@Sun.COM 		}
2597*11878SVenu.Iyer@Sun.COM 		}
2598*11878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_TYPED;
2599*11878SVenu.Iyer@Sun.COM 	} else if (strncasecmp("0x", ptr, 2) == 0 && ptr[2] != '\0') {
2600*11878SVenu.Iyer@Sun.COM 		ptr += 2;
2601*11878SVenu.Iyer@Sun.COM 		hexlen = sizeof (tmp_buf);
2602*11878SVenu.Iyer@Sun.COM 		if (hexascii_to_octet(ptr, strlen(ptr), tmp_buf,
2603*11878SVenu.Iyer@Sun.COM 		    &hexlen) != 0) {
2604*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_BADARG);
2605*11878SVenu.Iyer@Sun.COM 		}
2606*11878SVenu.Iyer@Sun.COM 		cidlen = hexlen;
2607*11878SVenu.Iyer@Sun.COM 		if (cidlen > sizeof (cid->dc_id))
2608*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_TOOSMALL);
2609*11878SVenu.Iyer@Sun.COM 
2610*11878SVenu.Iyer@Sun.COM 		bcopy(tmp_buf, cid->dc_id, cidlen);
2611*11878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_HEX;
2612*11878SVenu.Iyer@Sun.COM 	} else {
2613*11878SVenu.Iyer@Sun.COM 		cidlen = strlen(ptr);
2614*11878SVenu.Iyer@Sun.COM 		if (cidlen > sizeof (cid->dc_id))
2615*11878SVenu.Iyer@Sun.COM 			return (DLADM_STATUS_TOOSMALL);
2616*11878SVenu.Iyer@Sun.COM 
2617*11878SVenu.Iyer@Sun.COM 		bcopy(ptr, cid->dc_id, cidlen);
2618*11878SVenu.Iyer@Sun.COM 		cid->dc_form = CIDFORM_STR;
2619*11878SVenu.Iyer@Sun.COM 	}
2620*11878SVenu.Iyer@Sun.COM 	cid->dc_len = cidlen;
262110734SEric Cheng 	return (DLADM_STATUS_OK);
262210734SEric Cheng }
262310734SEric Cheng 
262410734SEric Cheng /* ARGSUSED */
262510734SEric Cheng static dladm_status_t
2626*11878SVenu.Iyer@Sun.COM get_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2627*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
2628*11878SVenu.Iyer@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
2629*11878SVenu.Iyer@Sun.COM {
2630*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	mrp;
2631*11878SVenu.Iyer@Sun.COM 	mac_protect_t		*p;
2632*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
2633*11878SVenu.Iyer@Sun.COM 	int			i;
2634*11878SVenu.Iyer@Sun.COM 
2635*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, "resource", flags,
2636*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mrp, sizeof (mrp));
2637*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2638*11878SVenu.Iyer@Sun.COM 		return (status);
2639*11878SVenu.Iyer@Sun.COM 
2640*11878SVenu.Iyer@Sun.COM 	p = &mrp.mrp_protect;
2641*11878SVenu.Iyer@Sun.COM 	if (p->mp_cidcnt == 0) {
2642*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
2643*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_OK);
2644*11878SVenu.Iyer@Sun.COM 	}
2645*11878SVenu.Iyer@Sun.COM 	if (p->mp_cidcnt > *val_cnt)
2646*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2647*11878SVenu.Iyer@Sun.COM 
2648*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < p->mp_cidcnt; i++) {
2649*11878SVenu.Iyer@Sun.COM 		mac_dhcpcid_t	*cid = &p->mp_cids[i];
2650*11878SVenu.Iyer@Sun.COM 
2651*11878SVenu.Iyer@Sun.COM 		dladm_cid2str(cid, prop_val[i]);
2652*11878SVenu.Iyer@Sun.COM 	}
2653*11878SVenu.Iyer@Sun.COM 	*val_cnt = p->mp_cidcnt;
2654*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2655*11878SVenu.Iyer@Sun.COM }
2656*11878SVenu.Iyer@Sun.COM 
2657*11878SVenu.Iyer@Sun.COM dladm_status_t
2658*11878SVenu.Iyer@Sun.COM extract_allowedcids(val_desc_t *vdp, uint_t cnt, void *arg)
2659*11878SVenu.Iyer@Sun.COM {
2660*11878SVenu.Iyer@Sun.COM 	mac_resource_props_t	*mrp = arg;
2661*11878SVenu.Iyer@Sun.COM 	mac_protect_t		*p = &mrp->mrp_protect;
2662*11878SVenu.Iyer@Sun.COM 	int			i;
2663*11878SVenu.Iyer@Sun.COM 
2664*11878SVenu.Iyer@Sun.COM 	if (vdp->vd_val == 0) {
2665*11878SVenu.Iyer@Sun.COM 		cnt = (uint_t)-1;
2666*11878SVenu.Iyer@Sun.COM 	} else {
2667*11878SVenu.Iyer@Sun.COM 		for (i = 0; i < cnt; i++) {
2668*11878SVenu.Iyer@Sun.COM 			bcopy((void *)vdp[i].vd_val, &p->mp_cids[i],
2669*11878SVenu.Iyer@Sun.COM 			    sizeof (mac_dhcpcid_t));
2670*11878SVenu.Iyer@Sun.COM 		}
2671*11878SVenu.Iyer@Sun.COM 	}
2672*11878SVenu.Iyer@Sun.COM 	p->mp_cidcnt = cnt;
2673*11878SVenu.Iyer@Sun.COM 	mrp->mrp_mask |= MRP_PROTECT;
2674*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2675*11878SVenu.Iyer@Sun.COM }
2676*11878SVenu.Iyer@Sun.COM 
2677*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2678*11878SVenu.Iyer@Sun.COM static dladm_status_t
2679*11878SVenu.Iyer@Sun.COM check_allowedcids(dladm_handle_t handle, prop_desc_t *pdp,
2680*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt,
2681*11878SVenu.Iyer@Sun.COM     uint_t flags, val_desc_t *vdp, datalink_media_t media)
2682*11878SVenu.Iyer@Sun.COM {
2683*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
2684*11878SVenu.Iyer@Sun.COM 	mac_dhcpcid_t	*cid;
2685*11878SVenu.Iyer@Sun.COM 	int		i;
2686*11878SVenu.Iyer@Sun.COM 
2687*11878SVenu.Iyer@Sun.COM 	if (val_cnt > MPT_MAXCID)
2688*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
2689*11878SVenu.Iyer@Sun.COM 
2690*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
2691*11878SVenu.Iyer@Sun.COM 		if ((cid = calloc(1, sizeof (mac_dhcpcid_t))) == NULL) {
2692*11878SVenu.Iyer@Sun.COM 			status = DLADM_STATUS_NOMEM;
2693*11878SVenu.Iyer@Sun.COM 			goto fail;
2694*11878SVenu.Iyer@Sun.COM 		}
2695*11878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = (uintptr_t)cid;
2696*11878SVenu.Iyer@Sun.COM 
2697*11878SVenu.Iyer@Sun.COM 		status = dladm_str2cid(prop_val[i], cid);
2698*11878SVenu.Iyer@Sun.COM 		if (status != DLADM_STATUS_OK)
2699*11878SVenu.Iyer@Sun.COM 			goto fail;
2700*11878SVenu.Iyer@Sun.COM 	}
2701*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
2702*11878SVenu.Iyer@Sun.COM 
2703*11878SVenu.Iyer@Sun.COM fail:
2704*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < val_cnt; i++) {
2705*11878SVenu.Iyer@Sun.COM 		free((void *)vdp[i].vd_val);
2706*11878SVenu.Iyer@Sun.COM 		vdp[i].vd_val = NULL;
2707*11878SVenu.Iyer@Sun.COM 	}
2708*11878SVenu.Iyer@Sun.COM 	return (status);
2709*11878SVenu.Iyer@Sun.COM }
2710*11878SVenu.Iyer@Sun.COM 
2711*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
2712*11878SVenu.Iyer@Sun.COM static dladm_status_t
2713*11878SVenu.Iyer@Sun.COM get_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
27148275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
27158275SEric Cheng     uint_t flags, uint_t *perm_flags)
27165895Syz147064 {
27177342SAruna.Ramakrishna@Sun.COM 	struct		dlautopush dlap;
27187342SAruna.Ramakrishna@Sun.COM 	int		i, len;
27197342SAruna.Ramakrishna@Sun.COM 	dladm_status_t	status;
2720*11878SVenu.Iyer@Sun.COM 
2721*11878SVenu.Iyer@Sun.COM 	if (flags & DLD_PROP_DEFAULT)
27227776SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOTDEFINED);
27236512Ssowmini 
2724*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
2725*11878SVenu.Iyer@Sun.COM 	    perm_flags, &dlap, sizeof (dlap));
2726*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
2727*11878SVenu.Iyer@Sun.COM 		return (status);
2728*11878SVenu.Iyer@Sun.COM 
2729*11878SVenu.Iyer@Sun.COM 	if (dlap.dap_npush == 0) {
2730*11878SVenu.Iyer@Sun.COM 		*val_cnt = 0;
27318275SEric Cheng 		return (DLADM_STATUS_OK);
27325895Syz147064 	}
27337342SAruna.Ramakrishna@Sun.COM 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
27345895Syz147064 		if (i != 0) {
27355895Syz147064 			(void) snprintf(*prop_val + len,
27365895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
27375895Syz147064 			len += 1;
27385895Syz147064 		}
27395895Syz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
27407342SAruna.Ramakrishna@Sun.COM 		    "%s", dlap.dap_aplist[i]);
27417342SAruna.Ramakrishna@Sun.COM 		len += strlen(dlap.dap_aplist[i]);
27427342SAruna.Ramakrishna@Sun.COM 		if (dlap.dap_anchor - 1 == i) {
27435895Syz147064 			(void) snprintf(*prop_val + len,
27445895Syz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
27455895Syz147064 			    AP_ANCHOR);
27465895Syz147064 			len += (strlen(AP_ANCHOR) + 1);
27475895Syz147064 		}
27485895Syz147064 	}
2749*11878SVenu.Iyer@Sun.COM 	*val_cnt = 1;
27505895Syz147064 	return (DLADM_STATUS_OK);
27515895Syz147064 }
27525895Syz147064 
27535895Syz147064 /*
27545895Syz147064  * Add the specified module to the dlautopush structure; returns a
27555895Syz147064  * DLADM_STATUS_* code.
27565895Syz147064  */
27575895Syz147064 dladm_status_t
27585895Syz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
27595895Syz147064 {
27605895Syz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
27615895Syz147064 		return (DLADM_STATUS_BADVAL);
27625895Syz147064 
27635895Syz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
27645895Syz147064 		/*
27655895Syz147064 		 * We don't allow multiple anchors, and the anchor must
27665895Syz147064 		 * be after at least one module.
27675895Syz147064 		 */
27685895Syz147064 		if (dlap->dap_anchor != 0)
27695895Syz147064 			return (DLADM_STATUS_BADVAL);
27705895Syz147064 		if (dlap->dap_npush == 0)
27715895Syz147064 			return (DLADM_STATUS_BADVAL);
27725895Syz147064 
27735895Syz147064 		dlap->dap_anchor = dlap->dap_npush;
27745895Syz147064 		return (DLADM_STATUS_OK);
27755895Syz147064 	}
27768957SMichael.Lim@Sun.COM 	if (dlap->dap_npush >= MAXAPUSH)
27775895Syz147064 		return (DLADM_STATUS_BADVALCNT);
27785895Syz147064 
27795895Syz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
27805895Syz147064 	    FMNAMESZ + 1);
27815895Syz147064 
27825895Syz147064 	return (DLADM_STATUS_OK);
27835895Syz147064 }
27845895Syz147064 
27855895Syz147064 /*
27865895Syz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
27875895Syz147064  * autopush modules. The former is used in dladm set-linkprop, and the
27885895Syz147064  * latter is used in the autopush(1M) file.
27895895Syz147064  */
27905895Syz147064 /* ARGSUSED */
27915895Syz147064 static dladm_status_t
2792*11878SVenu.Iyer@Sun.COM check_autopush(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2793*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
2794*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
27955895Syz147064 {
27965895Syz147064 	char			*module;
27975895Syz147064 	struct dlautopush	*dlap;
27985895Syz147064 	dladm_status_t		status;
27995895Syz147064 	char			val[DLADM_PROP_VAL_MAX];
28005895Syz147064 	char			delimiters[4];
28015895Syz147064 
28025895Syz147064 	if (val_cnt != 1)
28035895Syz147064 		return (DLADM_STATUS_BADVALCNT);
28045895Syz147064 
28057342SAruna.Ramakrishna@Sun.COM 	if (prop_val != NULL) {
28067342SAruna.Ramakrishna@Sun.COM 		dlap = malloc(sizeof (struct dlautopush));
28077342SAruna.Ramakrishna@Sun.COM 		if (dlap == NULL)
28087342SAruna.Ramakrishna@Sun.COM 			return (DLADM_STATUS_NOMEM);
28093448Sdh155122 
28107342SAruna.Ramakrishna@Sun.COM 		(void) memset(dlap, 0, sizeof (struct dlautopush));
28117342SAruna.Ramakrishna@Sun.COM 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
28127342SAruna.Ramakrishna@Sun.COM 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
28137342SAruna.Ramakrishna@Sun.COM 		module = strtok(val, delimiters);
28147342SAruna.Ramakrishna@Sun.COM 		while (module != NULL) {
28157342SAruna.Ramakrishna@Sun.COM 			status = i_dladm_add_ap_module(module, dlap);
28167342SAruna.Ramakrishna@Sun.COM 			if (status != DLADM_STATUS_OK)
28177342SAruna.Ramakrishna@Sun.COM 				return (status);
28187342SAruna.Ramakrishna@Sun.COM 			module = strtok(NULL, delimiters);
28197342SAruna.Ramakrishna@Sun.COM 		}
28207342SAruna.Ramakrishna@Sun.COM 
28217342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = (uintptr_t)dlap;
28227342SAruna.Ramakrishna@Sun.COM 	} else {
28237342SAruna.Ramakrishna@Sun.COM 		vdp->vd_val = 0;
28245895Syz147064 	}
28253448Sdh155122 	return (DLADM_STATUS_OK);
28263448Sdh155122 }
28273448Sdh155122 
28287663SSowmini.Varadhan@Sun.COM #define	WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
28297663SSowmini.Varadhan@Sun.COM 
28305903Ssowmini /* ARGSUSED */
28313448Sdh155122 static dladm_status_t
2832*11878SVenu.Iyer@Sun.COM get_rate_common(dladm_handle_t handle, prop_desc_t *pdp,
28338453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt, uint_t id,
28348453SAnurag.Maskey@Sun.COM     uint_t *perm_flags)
28353448Sdh155122 {
28365895Syz147064 	wl_rates_t	*wrp;
28375895Syz147064 	uint_t		i;
28385895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
28395895Syz147064 
28407663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
28417663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
28427663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
28435895Syz147064 
28448453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp, id, WLDP_BUFSIZE,
28458453SAnurag.Maskey@Sun.COM 	    B_FALSE);
28465895Syz147064 	if (status != DLADM_STATUS_OK)
28475895Syz147064 		goto done;
28485895Syz147064 
28495895Syz147064 	if (wrp->wl_rates_num > *val_cnt) {
28505895Syz147064 		status = DLADM_STATUS_TOOSMALL;
28515895Syz147064 		goto done;
28525895Syz147064 	}
28535895Syz147064 
28545895Syz147064 	if (wrp->wl_rates_rates[0] == 0) {
28555895Syz147064 		prop_val[0][0] = '\0';
28565895Syz147064 		*val_cnt = 1;
28575895Syz147064 		goto done;
28585895Syz147064 	}
28595895Syz147064 
28605895Syz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
28615895Syz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
28625895Syz147064 		    wrp->wl_rates_rates[i] % 2,
28635895Syz147064 		    (float)wrp->wl_rates_rates[i] / 2);
28645895Syz147064 	}
28655895Syz147064 	*val_cnt = wrp->wl_rates_num;
28668275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
28673448Sdh155122 
28685895Syz147064 done:
28697663SSowmini.Varadhan@Sun.COM 	free(wrp);
28705895Syz147064 	return (status);
28715895Syz147064 }
28725895Syz147064 
28735895Syz147064 static dladm_status_t
2874*11878SVenu.Iyer@Sun.COM get_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
28758275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
28768275SEric Cheng     uint_t flags, uint_t *perm_flags)
28775895Syz147064 {
28788118SVasumathi.Sundaram@Sun.COM 	if (media != DL_WIFI) {
2879*11878SVenu.Iyer@Sun.COM 		return (get_speed(handle, pdp, linkid, prop_val,
2880*11878SVenu.Iyer@Sun.COM 		    val_cnt, media, flags, perm_flags));
28818118SVasumathi.Sundaram@Sun.COM 	}
28825960Ssowmini 
2883*11878SVenu.Iyer@Sun.COM 	return (get_rate_common(handle, pdp, linkid, prop_val, val_cnt,
28848275SEric Cheng 	    MAC_PROP_WL_DESIRED_RATES, perm_flags));
28855895Syz147064 }
28865895Syz147064 
28876512Ssowmini /* ARGSUSED */
28885895Syz147064 static dladm_status_t
2889*11878SVenu.Iyer@Sun.COM get_rate_mod(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
28908275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
28918275SEric Cheng     uint_t flags, uint_t *perm_flags)
28925895Syz147064 {
28935960Ssowmini 	switch (media) {
28945960Ssowmini 	case DL_ETHER:
28956512Ssowmini 		/*
28966512Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
28976512Ssowmini 		 * links can have a speed of 5.5 Gbps.
28986512Ssowmini 		 */
28996512Ssowmini 		return (DLADM_STATUS_NOTSUP);
29005960Ssowmini 
29015960Ssowmini 	case DL_WIFI:
2902*11878SVenu.Iyer@Sun.COM 		return (get_rate_common(handle, pdp, linkid, prop_val,
29038453SAnurag.Maskey@Sun.COM 		    val_cnt, MAC_PROP_WL_SUPPORTED_RATES, perm_flags));
29045960Ssowmini 	default:
29055960Ssowmini 		return (DLADM_STATUS_BADARG);
29065960Ssowmini 	}
29075895Syz147064 }
29085895Syz147064 
29095895Syz147064 static dladm_status_t
2910*11878SVenu.Iyer@Sun.COM set_wlan_rate(dladm_handle_t handle, datalink_id_t linkid,
29118453SAnurag.Maskey@Sun.COM     dladm_wlan_rates_t *rates)
29125895Syz147064 {
29135895Syz147064 	int		i;
29145895Syz147064 	uint_t		len;
29155895Syz147064 	wl_rates_t	*wrp;
29165895Syz147064 	dladm_status_t	status = DLADM_STATUS_OK;
29175895Syz147064 
29187663SSowmini.Varadhan@Sun.COM 	wrp = malloc(WLDP_BUFSIZE);
29197663SSowmini.Varadhan@Sun.COM 	if (wrp == NULL)
29205895Syz147064 		return (DLADM_STATUS_NOMEM);
29215895Syz147064 
29227663SSowmini.Varadhan@Sun.COM 	bzero(wrp, WLDP_BUFSIZE);
29235895Syz147064 	for (i = 0; i < rates->wr_cnt; i++)
29245895Syz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
29255895Syz147064 	wrp->wl_rates_num = rates->wr_cnt;
29265895Syz147064 
29275895Syz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
29285895Syz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
29298453SAnurag.Maskey@Sun.COM 	status = i_dladm_wlan_param(handle, linkid, wrp,
29308453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_DESIRED_RATES, len, B_TRUE);
29315895Syz147064 
29327663SSowmini.Varadhan@Sun.COM 	free(wrp);
29335895Syz147064 	return (status);
29345895Syz147064 }
29353448Sdh155122 
29365903Ssowmini /* ARGSUSED */
29375895Syz147064 static dladm_status_t
2938*11878SVenu.Iyer@Sun.COM set_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
29395960Ssowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
29405895Syz147064 {
29415895Syz147064 	dladm_wlan_rates_t	rates;
29425895Syz147064 	dladm_status_t		status;
29435895Syz147064 
29445960Ssowmini 	/*
29455960Ssowmini 	 * can currently set rate on WIFI links only.
29465960Ssowmini 	 */
29475960Ssowmini 	if (media != DL_WIFI)
29485960Ssowmini 		return (DLADM_STATUS_PROPRDONLY);
29495960Ssowmini 
29505895Syz147064 	if (val_cnt != 1)
29515895Syz147064 		return (DLADM_STATUS_BADVALCNT);
29525895Syz147064 
29535895Syz147064 	rates.wr_cnt = 1;
29545895Syz147064 	rates.wr_rates[0] = vdp[0].vd_val;
29555895Syz147064 
2956*11878SVenu.Iyer@Sun.COM 	status = set_wlan_rate(handle, linkid, &rates);
2957*11878SVenu.Iyer@Sun.COM 
29585895Syz147064 	return (status);
29595895Syz147064 }
29603448Sdh155122 
29615895Syz147064 /* ARGSUSED */
29625895Syz147064 static dladm_status_t
2963*11878SVenu.Iyer@Sun.COM check_rate(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
2964*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
2965*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
29665895Syz147064 {
29675895Syz147064 	int		i;
29685895Syz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
29695895Syz147064 	char		*buf, **modval;
29705895Syz147064 	dladm_status_t	status;
29718118SVasumathi.Sundaram@Sun.COM 	uint_t 		perm_flags;
29725895Syz147064 
29735895Syz147064 	if (val_cnt != 1)
29745895Syz147064 		return (DLADM_STATUS_BADVALCNT);
29755895Syz147064 
29765895Syz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
29775895Syz147064 	    MAX_SUPPORT_RATES);
29785895Syz147064 	if (buf == NULL) {
29795895Syz147064 		status = DLADM_STATUS_NOMEM;
29805895Syz147064 		goto done;
29815895Syz147064 	}
29823448Sdh155122 
29835895Syz147064 	modval = (char **)(void *)buf;
29845895Syz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
29855895Syz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
29865895Syz147064 		    i * DLADM_STRSIZE;
29875895Syz147064 	}
29885895Syz147064 
2989*11878SVenu.Iyer@Sun.COM 	status = get_rate_mod(handle, NULL, linkid, modval, &modval_cnt,
29908453SAnurag.Maskey@Sun.COM 	    media, 0, &perm_flags);
29915895Syz147064 	if (status != DLADM_STATUS_OK)
29925895Syz147064 		goto done;
29935895Syz147064 
29945895Syz147064 	for (i = 0; i < modval_cnt; i++) {
29955895Syz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
29965903Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
29975903Ssowmini 			    (atof(*prop_val) * 2);
29985895Syz147064 			status = DLADM_STATUS_OK;
29993448Sdh155122 			break;
30003448Sdh155122 		}
30015895Syz147064 	}
30025895Syz147064 	if (i == modval_cnt)
30035895Syz147064 		status = DLADM_STATUS_BADVAL;
30045895Syz147064 done:
30055895Syz147064 	free(buf);
30065895Syz147064 	return (status);
30075895Syz147064 }
30085895Syz147064 
30095895Syz147064 static dladm_status_t
3010*11878SVenu.Iyer@Sun.COM get_phyconf(dladm_handle_t handle, datalink_id_t linkid, void *buf,
30118453SAnurag.Maskey@Sun.COM     int buflen)
30125895Syz147064 {
30138453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
30147663SSowmini.Varadhan@Sun.COM 	    buflen, B_FALSE));
30155895Syz147064 }
30165895Syz147064 
30175903Ssowmini /* ARGSUSED */
30185895Syz147064 static dladm_status_t
3019*11878SVenu.Iyer@Sun.COM get_channel(dladm_handle_t handle, prop_desc_t *pdp,
30208453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30218453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30225895Syz147064 {
30235895Syz147064 	uint32_t	channel;
30247663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
3025*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
30267663SSowmini.Varadhan@Sun.COM 	wl_phy_conf_t	wl_phy_conf;
30275895Syz147064 
3028*11878SVenu.Iyer@Sun.COM 	if ((status = get_phyconf(handle, linkid, buf, sizeof (buf)))
30297663SSowmini.Varadhan@Sun.COM 	    != DLADM_STATUS_OK)
3030*11878SVenu.Iyer@Sun.COM 		return (status);
30315895Syz147064 
30327663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf));
3033*11878SVenu.Iyer@Sun.COM 	if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel))
3034*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
30355895Syz147064 
30365895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
30375895Syz147064 	*val_cnt = 1;
30388275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
3039*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
30405895Syz147064 }
30415895Syz147064 
30425903Ssowmini /* ARGSUSED */
30435895Syz147064 static dladm_status_t
3044*11878SVenu.Iyer@Sun.COM get_powermode(dladm_handle_t handle, prop_desc_t *pdp,
30458453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
30468453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
30475895Syz147064 {
30487663SSowmini.Varadhan@Sun.COM 	wl_ps_mode_t	mode;
30495895Syz147064 	const char	*s;
30507663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
3051*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
3052*11878SVenu.Iyer@Sun.COM 
3053*11878SVenu.Iyer@Sun.COM 	if ((status = i_dladm_wlan_param(handle, linkid, buf,
3054*11878SVenu.Iyer@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3055*11878SVenu.Iyer@Sun.COM 		return (status);
30565895Syz147064 
30577663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&mode, buf, sizeof (mode));
30587663SSowmini.Varadhan@Sun.COM 	switch (mode.wl_ps_mode) {
30595895Syz147064 	case WL_PM_AM:
30605895Syz147064 		s = "off";
30615895Syz147064 		break;
30625895Syz147064 	case WL_PM_MPS:
30635895Syz147064 		s = "max";
30645895Syz147064 		break;
30655895Syz147064 	case WL_PM_FAST:
30665895Syz147064 		s = "fast";
30673448Sdh155122 		break;
30683448Sdh155122 	default:
3069*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
30705895Syz147064 	}
30715895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
30725895Syz147064 	*val_cnt = 1;
30738275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
3074*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
30755895Syz147064 }
30765895Syz147064 
3077*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
30785895Syz147064 static dladm_status_t
3079*11878SVenu.Iyer@Sun.COM set_powermode(dladm_handle_t handle, prop_desc_t *pdp,
3080*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
3081*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
30825895Syz147064 {
3083*11878SVenu.Iyer@Sun.COM 	dladm_wlan_powermode_t	powermode = vdp->vd_val;
3084*11878SVenu.Iyer@Sun.COM 	wl_ps_mode_t		ps_mode;
3085*11878SVenu.Iyer@Sun.COM 
3086*11878SVenu.Iyer@Sun.COM 	if (val_cnt != 1)
3087*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
30885895Syz147064 
30895895Syz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
30905895Syz147064 
3091*11878SVenu.Iyer@Sun.COM 	switch (powermode) {
30925895Syz147064 	case DLADM_WLAN_PM_OFF:
30935895Syz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
30943448Sdh155122 		break;
30955895Syz147064 	case DLADM_WLAN_PM_MAX:
30965895Syz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
30975895Syz147064 		break;
30985895Syz147064 	case DLADM_WLAN_PM_FAST:
30995895Syz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
31005895Syz147064 		break;
31015895Syz147064 	default:
31025895Syz147064 		return (DLADM_STATUS_NOTSUP);
31033448Sdh155122 	}
31048453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &ps_mode,
31058453SAnurag.Maskey@Sun.COM 	    MAC_PROP_WL_POWER_MODE, sizeof (ps_mode), B_TRUE));
31065895Syz147064 }
31075895Syz147064 
31085895Syz147064 /* ARGSUSED */
31095895Syz147064 static dladm_status_t
3110*11878SVenu.Iyer@Sun.COM get_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
31118275SEric Cheng     char **prop_val, uint_t *val_cnt, datalink_media_t media,
31128275SEric Cheng     uint_t flags, uint_t *perm_flags)
31135895Syz147064 {
31145895Syz147064 	wl_radio_t	radio;
31155895Syz147064 	const char	*s;
31167663SSowmini.Varadhan@Sun.COM 	char		buf[WLDP_BUFSIZE];
3117*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
3118*11878SVenu.Iyer@Sun.COM 
3119*11878SVenu.Iyer@Sun.COM 	if ((status = i_dladm_wlan_param(handle, linkid, buf,
3120*11878SVenu.Iyer@Sun.COM 	    MAC_PROP_WL_RADIO, sizeof (buf), B_FALSE)) != DLADM_STATUS_OK)
3121*11878SVenu.Iyer@Sun.COM 		return (status);
31223448Sdh155122 
31237663SSowmini.Varadhan@Sun.COM 	(void) memcpy(&radio, buf, sizeof (radio));
31245895Syz147064 	switch (radio) {
31255895Syz147064 	case B_TRUE:
31265895Syz147064 		s = "on";
31275895Syz147064 		break;
31285895Syz147064 	case B_FALSE:
31295895Syz147064 		s = "off";
31305895Syz147064 		break;
31315895Syz147064 	default:
3132*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOTFOUND);
31335895Syz147064 	}
31345895Syz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
31355895Syz147064 	*val_cnt = 1;
31368275SEric Cheng 	*perm_flags = MAC_PROP_PERM_RW;
3137*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
31383448Sdh155122 }
31393448Sdh155122 
3140*11878SVenu.Iyer@Sun.COM /* ARGSUSED */
31413448Sdh155122 static dladm_status_t
3142*11878SVenu.Iyer@Sun.COM set_radio(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3143*11878SVenu.Iyer@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
31443448Sdh155122 {
3145*11878SVenu.Iyer@Sun.COM 	dladm_wlan_radio_t	radio = vdp->vd_val;
3146*11878SVenu.Iyer@Sun.COM 	wl_radio_t		r;
3147*11878SVenu.Iyer@Sun.COM 
3148*11878SVenu.Iyer@Sun.COM 	if (val_cnt != 1)
3149*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
3150*11878SVenu.Iyer@Sun.COM 
3151*11878SVenu.Iyer@Sun.COM 	switch (radio) {
31525895Syz147064 	case DLADM_WLAN_RADIO_ON:
31535895Syz147064 		r = B_TRUE;
31545895Syz147064 		break;
31555895Syz147064 	case DLADM_WLAN_RADIO_OFF:
31565895Syz147064 		r = B_FALSE;
31575895Syz147064 		break;
31585895Syz147064 	default:
31595895Syz147064 		return (DLADM_STATUS_NOTSUP);
31605895Syz147064 	}
31618453SAnurag.Maskey@Sun.COM 	return (i_dladm_wlan_param(handle, linkid, &r, MAC_PROP_WL_RADIO,
31627663SSowmini.Varadhan@Sun.COM 	    sizeof (r), B_TRUE));
31635895Syz147064 }
31643448Sdh155122 
31655895Syz147064 /* ARGSUSED */
31665895Syz147064 static dladm_status_t
3167*11878SVenu.Iyer@Sun.COM check_hoplimit(dladm_handle_t handle, prop_desc_t *pdp,
3168*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
3169*11878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
317010616SSebastien.Roy@Sun.COM {
317110616SSebastien.Roy@Sun.COM 	int32_t	hlim;
317210616SSebastien.Roy@Sun.COM 	char	*ep;
317310616SSebastien.Roy@Sun.COM 
317410616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
317510616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
317610616SSebastien.Roy@Sun.COM 
317710616SSebastien.Roy@Sun.COM 	errno = 0;
317810616SSebastien.Roy@Sun.COM 	hlim = strtol(*prop_val, &ep, 10);
317910616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || hlim < 1 ||
318010616SSebastien.Roy@Sun.COM 	    hlim > (int32_t)UINT8_MAX)
318110616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
318210616SSebastien.Roy@Sun.COM 	vdp->vd_val = hlim;
318310616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
318410616SSebastien.Roy@Sun.COM }
318510616SSebastien.Roy@Sun.COM 
318610616SSebastien.Roy@Sun.COM /* ARGSUSED */
318710616SSebastien.Roy@Sun.COM static dladm_status_t
3188*11878SVenu.Iyer@Sun.COM check_encaplim(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3189*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t val_cnt, uint_t flags, val_desc_t *vdp,
3190*11878SVenu.Iyer@Sun.COM     datalink_media_t media)
319110616SSebastien.Roy@Sun.COM {
319210616SSebastien.Roy@Sun.COM 	int32_t	elim;
319310616SSebastien.Roy@Sun.COM 	char	*ep;
319410616SSebastien.Roy@Sun.COM 
319510616SSebastien.Roy@Sun.COM 	if (media != DL_IPV6)
319610616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADARG);
319710616SSebastien.Roy@Sun.COM 
319810616SSebastien.Roy@Sun.COM 	if (val_cnt != 1)
319910616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
320010616SSebastien.Roy@Sun.COM 
320110616SSebastien.Roy@Sun.COM 	errno = 0;
320210616SSebastien.Roy@Sun.COM 	elim = strtol(*prop_val, &ep, 10);
320310616SSebastien.Roy@Sun.COM 	if (errno != 0 || ep == *prop_val || elim < 0 ||
320410616SSebastien.Roy@Sun.COM 	    elim > (int32_t)UINT8_MAX)
320510616SSebastien.Roy@Sun.COM 		return (DLADM_STATUS_BADVAL);
320610616SSebastien.Roy@Sun.COM 	vdp->vd_val = elim;
320710616SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
320810616SSebastien.Roy@Sun.COM }
320910616SSebastien.Roy@Sun.COM 
32105895Syz147064 static dladm_status_t
32118453SAnurag.Maskey@Sun.COM i_dladm_set_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
32128453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt)
32133448Sdh155122 {
32145895Syz147064 	char		buf[MAXLINELEN];
32155895Syz147064 	int		i;
32165895Syz147064 	dladm_conf_t	conf;
32175895Syz147064 	dladm_status_t	status;
32183448Sdh155122 
32198453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
32205895Syz147064 	if (status != DLADM_STATUS_OK)
32215895Syz147064 		return (status);
32223448Sdh155122 
32235895Syz147064 	/*
32245895Syz147064 	 * reset case.
32255895Syz147064 	 */
32265895Syz147064 	if (val_cnt == 0) {
32278453SAnurag.Maskey@Sun.COM 		status = dladm_unset_conf_field(handle, conf, prop_name);
32285895Syz147064 		if (status == DLADM_STATUS_OK)
32298453SAnurag.Maskey@Sun.COM 			status = dladm_write_conf(handle, conf);
32305895Syz147064 		goto done;
32315895Syz147064 	}
32323448Sdh155122 
32335895Syz147064 	buf[0] = '\0';
32345895Syz147064 	for (i = 0; i < val_cnt; i++) {
32355895Syz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
32365895Syz147064 		if (i != val_cnt - 1)
32375895Syz147064 			(void) strlcat(buf, ",", MAXLINELEN);
32383448Sdh155122 	}
32393448Sdh155122 
32408453SAnurag.Maskey@Sun.COM 	status = dladm_set_conf_field(handle, conf, prop_name, DLADM_TYPE_STR,
32418453SAnurag.Maskey@Sun.COM 	    buf);
32425895Syz147064 	if (status == DLADM_STATUS_OK)
32438453SAnurag.Maskey@Sun.COM 		status = dladm_write_conf(handle, conf);
32445895Syz147064 
32455895Syz147064 done:
32468453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
32475895Syz147064 	return (status);
32483448Sdh155122 }
32495895Syz147064 
32505895Syz147064 static dladm_status_t
32518453SAnurag.Maskey@Sun.COM i_dladm_get_linkprop_db(dladm_handle_t handle, datalink_id_t linkid,
32528453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cntp)
32535895Syz147064 {
32545895Syz147064 	char		buf[MAXLINELEN], *str;
32555895Syz147064 	uint_t		cnt = 0;
32565895Syz147064 	dladm_conf_t	conf;
32575895Syz147064 	dladm_status_t	status;
32585895Syz147064 
32598453SAnurag.Maskey@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
32605895Syz147064 	if (status != DLADM_STATUS_OK)
32615895Syz147064 		return (status);
32625895Syz147064 
32638453SAnurag.Maskey@Sun.COM 	status = dladm_get_conf_field(handle, conf, prop_name, buf, MAXLINELEN);
32645895Syz147064 	if (status != DLADM_STATUS_OK)
32655895Syz147064 		goto done;
32665895Syz147064 
32675895Syz147064 	str = strtok(buf, ",");
32685895Syz147064 	while (str != NULL) {
32695895Syz147064 		if (cnt == *val_cntp) {
32705895Syz147064 			status = DLADM_STATUS_TOOSMALL;
32715895Syz147064 			goto done;
32725895Syz147064 		}
32735895Syz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
32745895Syz147064 		str = strtok(NULL, ",");
32755895Syz147064 	}
32765895Syz147064 
32775895Syz147064 	*val_cntp = cnt;
32785895Syz147064 
32795895Syz147064 done:
32808453SAnurag.Maskey@Sun.COM 	dladm_destroy_conf(handle, conf);
32815895Syz147064 	return (status);
32825895Syz147064 }
32835903Ssowmini 
32848460SArtem.Kachitchkin@Sun.COM /*
32858460SArtem.Kachitchkin@Sun.COM  * Walk persistent private link properties of a link.
32868460SArtem.Kachitchkin@Sun.COM  */
32878460SArtem.Kachitchkin@Sun.COM static dladm_status_t
32888460SArtem.Kachitchkin@Sun.COM i_dladm_walk_linkprop_priv_db(dladm_handle_t handle, datalink_id_t linkid,
32898460SArtem.Kachitchkin@Sun.COM     void *arg, int (*func)(dladm_handle_t, datalink_id_t, const char *, void *))
32908460SArtem.Kachitchkin@Sun.COM {
32918460SArtem.Kachitchkin@Sun.COM 	dladm_status_t		status;
32928460SArtem.Kachitchkin@Sun.COM 	dladm_conf_t		conf;
32938460SArtem.Kachitchkin@Sun.COM 	char			last_attr[MAXLINKATTRLEN];
32948460SArtem.Kachitchkin@Sun.COM 	char			attr[MAXLINKATTRLEN];
32958460SArtem.Kachitchkin@Sun.COM 	char			attrval[MAXLINKATTRVALLEN];
32968460SArtem.Kachitchkin@Sun.COM 	size_t			attrsz;
32978460SArtem.Kachitchkin@Sun.COM 
32988460SArtem.Kachitchkin@Sun.COM 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
32998460SArtem.Kachitchkin@Sun.COM 		return (DLADM_STATUS_BADARG);
33008460SArtem.Kachitchkin@Sun.COM 
33018460SArtem.Kachitchkin@Sun.COM 	status = dladm_read_conf(handle, linkid, &conf);
33028460SArtem.Kachitchkin@Sun.COM 	if (status != DLADM_STATUS_OK)
33038460SArtem.Kachitchkin@Sun.COM 		return (status);
33048460SArtem.Kachitchkin@Sun.COM 
33058460SArtem.Kachitchkin@Sun.COM 	last_attr[0] = '\0';
33068460SArtem.Kachitchkin@Sun.COM 	while ((status = dladm_getnext_conf_linkprop(handle, conf, last_attr,
33078460SArtem.Kachitchkin@Sun.COM 	    attr, attrval, MAXLINKATTRVALLEN, &attrsz)) == DLADM_STATUS_OK) {
33088460SArtem.Kachitchkin@Sun.COM 		if (attr[0] == '_') {
33098460SArtem.Kachitchkin@Sun.COM 			if (func(handle, linkid, attr, arg) ==
33108460SArtem.Kachitchkin@Sun.COM 			    DLADM_WALK_TERMINATE)
33118460SArtem.Kachitchkin@Sun.COM 				break;
33128460SArtem.Kachitchkin@Sun.COM 		}
33138460SArtem.Kachitchkin@Sun.COM 		(void) strlcpy(last_attr, attr, MAXLINKATTRLEN);
33148460SArtem.Kachitchkin@Sun.COM 	}
33158460SArtem.Kachitchkin@Sun.COM 
33168460SArtem.Kachitchkin@Sun.COM 	dladm_destroy_conf(handle, conf);
33178460SArtem.Kachitchkin@Sun.COM 	return (DLADM_STATUS_OK);
33188460SArtem.Kachitchkin@Sun.COM }
33198460SArtem.Kachitchkin@Sun.COM 
33207663SSowmini.Varadhan@Sun.COM static link_attr_t *
33215903Ssowmini dladm_name2prop(const char *prop_name)
33225903Ssowmini {
33237663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33245903Ssowmini 
33257663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
33265903Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
33275903Ssowmini 			break;
33285903Ssowmini 	}
33295903Ssowmini 	return (p);
33305903Ssowmini }
33315903Ssowmini 
33327663SSowmini.Varadhan@Sun.COM static link_attr_t *
33337663SSowmini.Varadhan@Sun.COM dladm_id2prop(mac_prop_id_t propid)
33347663SSowmini.Varadhan@Sun.COM {
33357663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33367663SSowmini.Varadhan@Sun.COM 
33377663SSowmini.Varadhan@Sun.COM 	for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) {
33387663SSowmini.Varadhan@Sun.COM 		if (p->pp_id == propid)
33397663SSowmini.Varadhan@Sun.COM 			break;
33407663SSowmini.Varadhan@Sun.COM 	}
33417663SSowmini.Varadhan@Sun.COM 	return (p);
33427663SSowmini.Varadhan@Sun.COM }
33435903Ssowmini 
33446789Sam223141 static dld_ioc_macprop_t *
33457663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid,
33467663SSowmini.Varadhan@Sun.COM     const char *prop_name, mac_prop_id_t propid, uint_t flags,
33477663SSowmini.Varadhan@Sun.COM     dladm_status_t *status)
33485903Ssowmini {
33495903Ssowmini 	int dsize;
33506789Sam223141 	dld_ioc_macprop_t *dip;
33515903Ssowmini 
33525903Ssowmini 	*status = DLADM_STATUS_OK;
33536789Sam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
33545903Ssowmini 	dip = malloc(dsize);
33555903Ssowmini 	if (dip == NULL) {
33565903Ssowmini 		*status = DLADM_STATUS_NOMEM;
33575903Ssowmini 		return (NULL);
33585903Ssowmini 	}
33595903Ssowmini 	bzero(dip, dsize);
33605903Ssowmini 	dip->pr_valsize = valsize;
33616512Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
33625960Ssowmini 	dip->pr_linkid = linkid;
33637663SSowmini.Varadhan@Sun.COM 	dip->pr_num = propid;
33646512Ssowmini 	dip->pr_flags = flags;
33655903Ssowmini 	return (dip);
33665903Ssowmini }
33675903Ssowmini 
33687663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
33697663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid,
33707663SSowmini.Varadhan@Sun.COM     const char *prop_name, uint_t flags, dladm_status_t *status)
33717663SSowmini.Varadhan@Sun.COM {
33727663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
33737663SSowmini.Varadhan@Sun.COM 
33747663SSowmini.Varadhan@Sun.COM 	p = dladm_name2prop(prop_name);
33757663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
33767663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id,
33777663SSowmini.Varadhan@Sun.COM 	    flags, status));
33787663SSowmini.Varadhan@Sun.COM }
33797663SSowmini.Varadhan@Sun.COM 
33807663SSowmini.Varadhan@Sun.COM static dld_ioc_macprop_t *
33817663SSowmini.Varadhan@Sun.COM i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid,
33827663SSowmini.Varadhan@Sun.COM     mac_prop_id_t propid, 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_id2prop(propid);
33877663SSowmini.Varadhan@Sun.COM 	valsize = MAX(p->pp_valsize, valsize);
33887663SSowmini.Varadhan@Sun.COM 	return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid,
33897663SSowmini.Varadhan@Sun.COM 	    flags, status));
33907663SSowmini.Varadhan@Sun.COM }
33917663SSowmini.Varadhan@Sun.COM 
33925903Ssowmini /* ARGSUSED */
33935903Ssowmini static dladm_status_t
3394*11878SVenu.Iyer@Sun.COM set_public_prop(dladm_handle_t handle, prop_desc_t *pdp,
33958453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags,
33968453SAnurag.Maskey@Sun.COM     datalink_media_t media)
33975903Ssowmini {
33986789Sam223141 	dld_ioc_macprop_t	*dip;
33995903Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
34005903Ssowmini 	uint8_t		u8;
34015903Ssowmini 	uint16_t	u16;
34025903Ssowmini 	uint32_t	u32;
34035903Ssowmini 	void		*val;
34045903Ssowmini 
34058275SEric Cheng 	dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, 0, &status);
34065903Ssowmini 	if (dip == NULL)
34075903Ssowmini 		return (status);
34085903Ssowmini 
34098275SEric Cheng 	if (pdp->pd_flags & PD_CHECK_ALLOC)
34105903Ssowmini 		val = (void *)vdp->vd_val;
34115903Ssowmini 	else {
34125903Ssowmini 		/*
34135903Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
34145903Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
34155903Ssowmini 		 */
34165903Ssowmini 		switch (dip->pr_valsize) {
34175903Ssowmini 		case 1:
34185903Ssowmini 			u8 = vdp->vd_val;
34195903Ssowmini 			val = &u8;
34205903Ssowmini 			break;
34215903Ssowmini 		case 2:
34225903Ssowmini 			u16 = vdp->vd_val;
34235903Ssowmini 			val = &u16;
34245903Ssowmini 			break;
34255903Ssowmini 		case 4:
34265903Ssowmini 			u32 = vdp->vd_val;
34275903Ssowmini 			val = &u32;
34285903Ssowmini 			break;
34295903Ssowmini 		default:
34305903Ssowmini 			val = &vdp->vd_val;
34315903Ssowmini 			break;
34325903Ssowmini 		}
34335903Ssowmini 	}
34345903Ssowmini 
34357342SAruna.Ramakrishna@Sun.COM 	if (val != NULL)
34367342SAruna.Ramakrishna@Sun.COM 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
34377342SAruna.Ramakrishna@Sun.COM 	else
34387342SAruna.Ramakrishna@Sun.COM 		dip->pr_valsize = 0;
34397342SAruna.Ramakrishna@Sun.COM 
34408453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
34417663SSowmini.Varadhan@Sun.COM 
34427663SSowmini.Varadhan@Sun.COM done:
34437663SSowmini.Varadhan@Sun.COM 	free(dip);
34447663SSowmini.Varadhan@Sun.COM 	return (status);
34457663SSowmini.Varadhan@Sun.COM }
34467663SSowmini.Varadhan@Sun.COM 
34477663SSowmini.Varadhan@Sun.COM dladm_status_t
34488453SAnurag.Maskey@Sun.COM i_dladm_macprop(dladm_handle_t handle, void *dip, boolean_t set)
34497663SSowmini.Varadhan@Sun.COM {
34507663SSowmini.Varadhan@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
34517663SSowmini.Varadhan@Sun.COM 
34528453SAnurag.Maskey@Sun.COM 	if (ioctl(dladm_dld_fd(handle),
34538453SAnurag.Maskey@Sun.COM 	    (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip))
34545903Ssowmini 		status = dladm_errno2status(errno);
34558453SAnurag.Maskey@Sun.COM 
34565903Ssowmini 	return (status);
34575903Ssowmini }
34585903Ssowmini 
3459*11878SVenu.Iyer@Sun.COM static dladm_status_t
34608453SAnurag.Maskey@Sun.COM i_dladm_get_public_prop(dladm_handle_t handle, datalink_id_t linkid,
3461*11878SVenu.Iyer@Sun.COM     char *prop_name, uint_t flags, uint_t *perm_flags, void *arg, size_t size)
34625903Ssowmini {
3463*11878SVenu.Iyer@Sun.COM 	dld_ioc_macprop_t	*dip;
3464*11878SVenu.Iyer@Sun.COM 	dladm_status_t		status;
3465*11878SVenu.Iyer@Sun.COM 
3466*11878SVenu.Iyer@Sun.COM 	dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, &status);
34676512Ssowmini 	if (dip == NULL)
3468*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
3469*11878SVenu.Iyer@Sun.COM 
3470*11878SVenu.Iyer@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
3471*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK) {
34726512Ssowmini 		free(dip);
3473*11878SVenu.Iyer@Sun.COM 		return (status);
34746512Ssowmini 	}
3475*11878SVenu.Iyer@Sun.COM 
34768275SEric Cheng 	if (perm_flags != NULL)
34778275SEric Cheng 		*perm_flags = dip->pr_perm_flags;
34788275SEric Cheng 
3479*11878SVenu.Iyer@Sun.COM 	if (arg != NULL)
3480*11878SVenu.Iyer@Sun.COM 		(void) memcpy(arg, dip->pr_val, size);
3481*11878SVenu.Iyer@Sun.COM 	free(dip);
3482*11878SVenu.Iyer@Sun.COM 	return (DLADM_STATUS_OK);
34835903Ssowmini }
34845903Ssowmini 
34855903Ssowmini /* ARGSUSED */
34865903Ssowmini static dladm_status_t
3487*11878SVenu.Iyer@Sun.COM check_uint32(dladm_handle_t handle, prop_desc_t *pdp,
3488*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
3489*11878SVenu.Iyer@Sun.COM     val_desc_t *v, datalink_media_t media)
34905903Ssowmini {
34915903Ssowmini 	if (val_cnt != 1)
34925903Ssowmini 		return (DLADM_STATUS_BADVAL);
349310491SRishi.Srivatsavai@Sun.COM 	v->vd_val = strtoul(prop_val[0], NULL, 0);
34945903Ssowmini 	return (DLADM_STATUS_OK);
34955903Ssowmini }
34965903Ssowmini 
34975903Ssowmini /* ARGSUSED */
34985903Ssowmini static dladm_status_t
3499*11878SVenu.Iyer@Sun.COM get_duplex(dladm_handle_t handle, prop_desc_t *pdp,
35008453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35018453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35025903Ssowmini {
35035903Ssowmini 	link_duplex_t   link_duplex;
35045903Ssowmini 	dladm_status_t  status;
35055903Ssowmini 
35068453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
35075903Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
35085903Ssowmini 		return (status);
35095903Ssowmini 
35105903Ssowmini 	switch (link_duplex) {
35115903Ssowmini 	case LINK_DUPLEX_FULL:
35125903Ssowmini 		(void) strcpy(*prop_val, "full");
35135903Ssowmini 		break;
35145903Ssowmini 	case LINK_DUPLEX_HALF:
35155903Ssowmini 		(void) strcpy(*prop_val, "half");
35165903Ssowmini 		break;
35175903Ssowmini 	default:
35185903Ssowmini 		(void) strcpy(*prop_val, "unknown");
35195903Ssowmini 		break;
35205903Ssowmini 	}
35215903Ssowmini 	*val_cnt = 1;
35225903Ssowmini 	return (DLADM_STATUS_OK);
35235903Ssowmini }
35245903Ssowmini 
35255903Ssowmini /* ARGSUSED */
35265903Ssowmini static dladm_status_t
3527*11878SVenu.Iyer@Sun.COM get_speed(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid,
3528*11878SVenu.Iyer@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
3529*11878SVenu.Iyer@Sun.COM     uint_t *perm_flags)
35305903Ssowmini {
35315903Ssowmini 	uint64_t	ifspeed = 0;
35325903Ssowmini 	dladm_status_t status;
35335903Ssowmini 
35348453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
35355903Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
35365903Ssowmini 		return (status);
35376512Ssowmini 
35385960Ssowmini 	if ((ifspeed % 1000000) != 0) {
35395960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
35405960Ssowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
35415960Ssowmini 	} else {
35425960Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
35435960Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
35445960Ssowmini 	}
35455903Ssowmini 	*val_cnt = 1;
35468275SEric Cheng 	*perm_flags = MAC_PROP_PERM_READ;
35475903Ssowmini 	return (DLADM_STATUS_OK);
35485903Ssowmini }
35495903Ssowmini 
35505903Ssowmini /* ARGSUSED */
35515903Ssowmini static dladm_status_t
3552*11878SVenu.Iyer@Sun.COM get_link_state(dladm_handle_t handle, prop_desc_t *pdp,
35538453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35548453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35555903Ssowmini {
35568275SEric Cheng 	link_state_t		link_state;
35578275SEric Cheng 	dladm_status_t		status;
35588306SSowmini.Varadhan@Sun.COM 
3559*11878SVenu.Iyer@Sun.COM 	status = dladm_get_state(handle, linkid, &link_state);
35606512Ssowmini 	if (status != DLADM_STATUS_OK)
35615903Ssowmini 		return (status);
35628275SEric Cheng 
35635903Ssowmini 	switch (link_state) {
35645903Ssowmini 	case LINK_STATE_UP:
35655903Ssowmini 		(void) strcpy(*prop_val, "up");
35665903Ssowmini 		break;
35675903Ssowmini 	case LINK_STATE_DOWN:
35685903Ssowmini 		(void) strcpy(*prop_val, "down");
35695903Ssowmini 		break;
35705903Ssowmini 	default:
35715903Ssowmini 		(void) strcpy(*prop_val, "unknown");
35725903Ssowmini 		break;
35735903Ssowmini 	}
35745903Ssowmini 	*val_cnt = 1;
35758306SSowmini.Varadhan@Sun.COM 	*perm_flags = MAC_PROP_PERM_READ;
35765903Ssowmini 	return (DLADM_STATUS_OK);
35775903Ssowmini }
35785903Ssowmini 
35795903Ssowmini /* ARGSUSED */
35805903Ssowmini static dladm_status_t
3581*11878SVenu.Iyer@Sun.COM get_binary(dladm_handle_t handle, prop_desc_t *pdp,
35828453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
35838453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
35845903Ssowmini {
3585*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
3586*11878SVenu.Iyer@Sun.COM 	uint_t		v = 0;
3587*11878SVenu.Iyer@Sun.COM 
3588*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3589*11878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
3590*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
35915903Ssowmini 		return (status);
35928275SEric Cheng 
3593*11878SVenu.Iyer@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%d", (uint_t)(v > 0));
35945903Ssowmini 	*val_cnt = 1;
35955903Ssowmini 	return (DLADM_STATUS_OK);
35965903Ssowmini }
35975903Ssowmini 
35985960Ssowmini /* ARGSUSED */
35995903Ssowmini static dladm_status_t
3600*11878SVenu.Iyer@Sun.COM get_uint32(dladm_handle_t handle, prop_desc_t *pdp,
36018453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
36028453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
36035903Ssowmini {
3604*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
3605*11878SVenu.Iyer@Sun.COM 	uint32_t	v = 0;
3606*11878SVenu.Iyer@Sun.COM 
3607*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3608*11878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
3609*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
36105903Ssowmini 		return (status);
36118275SEric Cheng 
36126512Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
36135903Ssowmini 	*val_cnt = 1;
36145903Ssowmini 	return (DLADM_STATUS_OK);
36155903Ssowmini }
36165903Ssowmini 
36179514SGirish.Moodalbail@Sun.COM /* ARGSUSED */
36189514SGirish.Moodalbail@Sun.COM static dladm_status_t
3619*11878SVenu.Iyer@Sun.COM get_range(dladm_handle_t handle, prop_desc_t *pdp,
36209514SGirish.Moodalbail@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
36219514SGirish.Moodalbail@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
36229514SGirish.Moodalbail@Sun.COM {
36239514SGirish.Moodalbail@Sun.COM 	dld_ioc_macprop_t *dip;
36249514SGirish.Moodalbail@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
36259514SGirish.Moodalbail@Sun.COM 	size_t	sz;
36269514SGirish.Moodalbail@Sun.COM 	mac_propval_range_t *rangep;
36279514SGirish.Moodalbail@Sun.COM 
36289514SGirish.Moodalbail@Sun.COM 	sz = sizeof (mac_propval_range_t);
36299514SGirish.Moodalbail@Sun.COM 
36309514SGirish.Moodalbail@Sun.COM 	/*
36319514SGirish.Moodalbail@Sun.COM 	 * As caller we don't know number of value ranges, the driver
36329514SGirish.Moodalbail@Sun.COM 	 * supports. To begin with we assume that number to be 1. If the
36339514SGirish.Moodalbail@Sun.COM 	 * buffer size is insufficient, driver returns back with the
36349514SGirish.Moodalbail@Sun.COM 	 * actual count of value ranges. See mac.h for more details.
36359514SGirish.Moodalbail@Sun.COM 	 */
36369514SGirish.Moodalbail@Sun.COM retry:
36379514SGirish.Moodalbail@Sun.COM 	if ((dip = i_dladm_buf_alloc_by_name(sz, linkid, pdp->pd_name, flags,
36389514SGirish.Moodalbail@Sun.COM 	    &status)) == NULL)
36399514SGirish.Moodalbail@Sun.COM 		return (status);
36409514SGirish.Moodalbail@Sun.COM 
36419514SGirish.Moodalbail@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
36429514SGirish.Moodalbail@Sun.COM 	if (status != DLADM_STATUS_OK) {
36439514SGirish.Moodalbail@Sun.COM 		if (status == DLADM_STATUS_TOOSMALL) {
36449514SGirish.Moodalbail@Sun.COM 			int err;
36459514SGirish.Moodalbail@Sun.COM 
36469514SGirish.Moodalbail@Sun.COM 			rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
36479514SGirish.Moodalbail@Sun.COM 			if ((err = i_dladm_range_size(rangep, &sz)) == 0) {
36489514SGirish.Moodalbail@Sun.COM 				free(dip);
36499514SGirish.Moodalbail@Sun.COM 				goto retry;
36509514SGirish.Moodalbail@Sun.COM 			} else {
36519514SGirish.Moodalbail@Sun.COM 				status = dladm_errno2status(err);
36529514SGirish.Moodalbail@Sun.COM 			}
36539514SGirish.Moodalbail@Sun.COM 		}
36549514SGirish.Moodalbail@Sun.COM 		free(dip);
36559514SGirish.Moodalbail@Sun.COM 		return (status);
36569514SGirish.Moodalbail@Sun.COM 	}
3657*11878SVenu.Iyer@Sun.COM 
36589514SGirish.Moodalbail@Sun.COM 	rangep = (mac_propval_range_t *)(void *)&dip->pr_val;
3659*11878SVenu.Iyer@Sun.COM 	if (rangep->mpr_count == 0) {
3660*11878SVenu.Iyer@Sun.COM 		*val_cnt = 1;
3661*11878SVenu.Iyer@Sun.COM 		(void) snprintf(prop_val[0], DLADM_PROP_VAL_MAX, "--");
3662*11878SVenu.Iyer@Sun.COM 		goto done;
3663*11878SVenu.Iyer@Sun.COM 	}
36649514SGirish.Moodalbail@Sun.COM 
36659514SGirish.Moodalbail@Sun.COM 	switch (rangep->mpr_type) {
36669514SGirish.Moodalbail@Sun.COM 	case MAC_PROPVAL_UINT32: {
36679514SGirish.Moodalbail@Sun.COM 		mac_propval_uint32_range_t *ur;
36689514SGirish.Moodalbail@Sun.COM 		uint_t	count = rangep->mpr_count, i;
36699514SGirish.Moodalbail@Sun.COM 
3670*11878SVenu.Iyer@Sun.COM 		ur = &rangep->mpr_range_uint32[0];
36719514SGirish.Moodalbail@Sun.COM 
36729514SGirish.Moodalbail@Sun.COM 		for (i = 0; i < count; i++, ur++) {
36739514SGirish.Moodalbail@Sun.COM 			if (ur->mpur_min == ur->mpur_max) {
36749514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
36759514SGirish.Moodalbail@Sun.COM 				    "%ld", ur->mpur_min);
36769514SGirish.Moodalbail@Sun.COM 			} else {
36779514SGirish.Moodalbail@Sun.COM 				(void) snprintf(prop_val[i], DLADM_PROP_VAL_MAX,
36789514SGirish.Moodalbail@Sun.COM 				    "%ld-%ld", ur->mpur_min, ur->mpur_max);
36799514SGirish.Moodalbail@Sun.COM 			}
36809514SGirish.Moodalbail@Sun.COM 		}
36819514SGirish.Moodalbail@Sun.COM 		*val_cnt = count;
36829514SGirish.Moodalbail@Sun.COM 		break;
36839514SGirish.Moodalbail@Sun.COM 	}
36849514SGirish.Moodalbail@Sun.COM 	default:
36859514SGirish.Moodalbail@Sun.COM 		status = DLADM_STATUS_BADARG;
36869514SGirish.Moodalbail@Sun.COM 		break;
36879514SGirish.Moodalbail@Sun.COM 	}
3688*11878SVenu.Iyer@Sun.COM done:
36899514SGirish.Moodalbail@Sun.COM 	free(dip);
36909514SGirish.Moodalbail@Sun.COM 	return (status);
36919514SGirish.Moodalbail@Sun.COM }
36929514SGirish.Moodalbail@Sun.COM 
36935960Ssowmini /* ARGSUSED */
36945903Ssowmini static dladm_status_t
3695*11878SVenu.Iyer@Sun.COM get_tagmode(dladm_handle_t handle, prop_desc_t *pdp,
36968874SSebastien.Roy@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
36978874SSebastien.Roy@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
36988874SSebastien.Roy@Sun.COM {
36998874SSebastien.Roy@Sun.COM 	link_tagmode_t		mode;
37008874SSebastien.Roy@Sun.COM 	dladm_status_t		status;
37018874SSebastien.Roy@Sun.COM 
3702*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3703*11878SVenu.Iyer@Sun.COM 	    perm_flags, &mode, sizeof (mode));
3704*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
37058874SSebastien.Roy@Sun.COM 		return (status);
37068874SSebastien.Roy@Sun.COM 
37078874SSebastien.Roy@Sun.COM 	switch (mode) {
37088874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_NORMAL:
37098874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "normal", DLADM_PROP_VAL_MAX);
37108874SSebastien.Roy@Sun.COM 		break;
37118874SSebastien.Roy@Sun.COM 	case LINK_TAGMODE_VLANONLY:
37128874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "vlanonly", DLADM_PROP_VAL_MAX);
37138874SSebastien.Roy@Sun.COM 		break;
37148874SSebastien.Roy@Sun.COM 	default:
37158874SSebastien.Roy@Sun.COM 		(void) strlcpy(*prop_val, "unknown", DLADM_PROP_VAL_MAX);
37168874SSebastien.Roy@Sun.COM 	}
37178874SSebastien.Roy@Sun.COM 	*val_cnt = 1;
37188874SSebastien.Roy@Sun.COM 	return (DLADM_STATUS_OK);
37198874SSebastien.Roy@Sun.COM }
37208874SSebastien.Roy@Sun.COM 
37218874SSebastien.Roy@Sun.COM /* ARGSUSED */
37228874SSebastien.Roy@Sun.COM static dladm_status_t
3723*11878SVenu.Iyer@Sun.COM get_flowctl(dladm_handle_t handle, prop_desc_t *pdp,
37248453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
37258453SAnurag.Maskey@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
37265903Ssowmini {
3727*11878SVenu.Iyer@Sun.COM 	link_flowctrl_t	v;
3728*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status;
3729*11878SVenu.Iyer@Sun.COM 
3730*11878SVenu.Iyer@Sun.COM 	status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags,
3731*11878SVenu.Iyer@Sun.COM 	    perm_flags, &v, sizeof (v));
3732*11878SVenu.Iyer@Sun.COM 	if (status != DLADM_STATUS_OK)
37335903Ssowmini 		return (status);
37348275SEric Cheng 
37355903Ssowmini 	switch (v) {
37365903Ssowmini 	case LINK_FLOWCTRL_NONE:
37375903Ssowmini 		(void) sprintf(*prop_val, "no");
37385903Ssowmini 		break;
37395903Ssowmini 	case LINK_FLOWCTRL_RX:
37405903Ssowmini 		(void) sprintf(*prop_val, "rx");
37415903Ssowmini 		break;
37425903Ssowmini 	case LINK_FLOWCTRL_TX:
37435903Ssowmini 		(void) sprintf(*prop_val, "tx");
37445903Ssowmini 		break;
37455903Ssowmini 	case LINK_FLOWCTRL_BI:
37465903Ssowmini 		(void) sprintf(*prop_val, "bi");
37475903Ssowmini 		break;
37485903Ssowmini 	}
37495903Ssowmini 	*val_cnt = 1;
37505903Ssowmini 	return (DLADM_STATUS_OK);
37515903Ssowmini }
37525903Ssowmini 
37535903Ssowmini 
37545903Ssowmini /* ARGSUSED */
37555903Ssowmini static dladm_status_t
37569692SRishi.Srivatsavai@Sun.COM i_dladm_set_private_prop(dladm_handle_t handle, datalink_id_t linkid,
37578453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags)
37588453SAnurag.Maskey@Sun.COM 
37595903Ssowmini {
37607663SSowmini.Varadhan@Sun.COM 	int		i, slen;
37617408SSebastien.Roy@Sun.COM 	int 		bufsize = 0;
37626789Sam223141 	dld_ioc_macprop_t *dip = NULL;
37635903Ssowmini 	uchar_t 	*dp;
37647663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
37656512Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
37665903Ssowmini 
37675903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
37685903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
37695903Ssowmini 		return (DLADM_STATUS_BADARG);
37705903Ssowmini 	p = dladm_name2prop(prop_name);
37716789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
37725903Ssowmini 		return (DLADM_STATUS_BADARG);
37735903Ssowmini 
37749692SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
37759692SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
37769692SRishi.Srivatsavai@Sun.COM 
37775903Ssowmini 	/*
37785903Ssowmini 	 * private properties: all parsing is done in the kernel.
37795903Ssowmini 	 * allocate a enough space for each property + its separator (',').
37805903Ssowmini 	 */
37815903Ssowmini 	for (i = 0; i < val_cnt; i++) {
37825903Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
37835903Ssowmini 	}
37846512Ssowmini 
37856512Ssowmini 	if (prop_val == NULL) {
37866512Ssowmini 		/*
37876512Ssowmini 		 * getting default value. so use more buffer space.
37886512Ssowmini 		 */
37897663SSowmini.Varadhan@Sun.COM 		bufsize += DLADM_PROP_BUF_CHUNK;
37906512Ssowmini 	}
37916512Ssowmini 
37927663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name,
3793*11878SVenu.Iyer@Sun.COM 	    (prop_val != NULL ? 0 : DLD_PROP_DEFAULT), &status);
37945903Ssowmini 	if (dip == NULL)
37955903Ssowmini 		return (status);
37965903Ssowmini 
37975903Ssowmini 	dp = (uchar_t *)dip->pr_val;
37985903Ssowmini 	slen = 0;
37997663SSowmini.Varadhan@Sun.COM 
38006512Ssowmini 	if (prop_val == NULL) {
38018453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_FALSE);
38028460SArtem.Kachitchkin@Sun.COM 		dip->pr_flags = 0;
38036512Ssowmini 	} else {
38046512Ssowmini 		for (i = 0; i < val_cnt; i++) {
38056512Ssowmini 			int plen = 0;
38065903Ssowmini 
38076512Ssowmini 			plen = strlen(prop_val[i]);
38086512Ssowmini 			bcopy(prop_val[i], dp, plen);
38096512Ssowmini 			slen += plen;
38106512Ssowmini 			/*
38116512Ssowmini 			 * add a "," separator and update dp.
38126512Ssowmini 			 */
38136512Ssowmini 			if (i != (val_cnt -1))
38146512Ssowmini 				dp[slen++] = ',';
38156512Ssowmini 			dp += (plen + 1);
38166512Ssowmini 		}
38178460SArtem.Kachitchkin@Sun.COM 	}
38188460SArtem.Kachitchkin@Sun.COM 	if (status == DLADM_STATUS_OK)
38198453SAnurag.Maskey@Sun.COM 		status = i_dladm_macprop(handle, dip, B_TRUE);
38206512Ssowmini 
38215903Ssowmini 	free(dip);
38226512Ssowmini 	return (status);
38235903Ssowmini }
38245903Ssowmini 
38255903Ssowmini static dladm_status_t
38268460SArtem.Kachitchkin@Sun.COM i_dladm_get_priv_prop(dladm_handle_t handle, datalink_id_t linkid,
38278453SAnurag.Maskey@Sun.COM     const char *prop_name, char **prop_val, uint_t *val_cnt,
38288453SAnurag.Maskey@Sun.COM     dladm_prop_type_t type, uint_t dld_flags)
38295903Ssowmini {
38307663SSowmini.Varadhan@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
38316789Sam223141 	dld_ioc_macprop_t *dip = NULL;
38327663SSowmini.Varadhan@Sun.COM 	link_attr_t *p;
38335903Ssowmini 
38345903Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
38355903Ssowmini 	    (prop_val != NULL && val_cnt == 0))
38365903Ssowmini 		return (DLADM_STATUS_BADARG);
38375903Ssowmini 
38385903Ssowmini 	p = dladm_name2prop(prop_name);
38396789Sam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
38405903Ssowmini 		return (DLADM_STATUS_BADARG);
38415903Ssowmini 
38425903Ssowmini 	/*
38435903Ssowmini 	 * private properties: all parsing is done in the kernel.
38445903Ssowmini 	 */
38457663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name,
38467663SSowmini.Varadhan@Sun.COM 	    dld_flags, &status);
38475903Ssowmini 	if (dip == NULL)
38485903Ssowmini 		return (status);
38495903Ssowmini 
38508453SAnurag.Maskey@Sun.COM 	if ((status = i_dladm_macprop(handle, dip, B_FALSE)) ==
38518453SAnurag.Maskey@Sun.COM 	    DLADM_STATUS_OK) {
38528118SVasumathi.Sundaram@Sun.COM 		if (type == DLADM_PROP_VAL_PERM) {
38538275SEric Cheng 			(void) dladm_perm2str(dip->pr_perm_flags, *prop_val);
38548460SArtem.Kachitchkin@Sun.COM 		} else if (type == DLADM_PROP_VAL_MODIFIABLE) {
38558460SArtem.Kachitchkin@Sun.COM 			*prop_val[0] = '\0';
38568118SVasumathi.Sundaram@Sun.COM 		} else {
38578118SVasumathi.Sundaram@Sun.COM 			(void) strncpy(*prop_val, dip->pr_val,
38588118SVasumathi.Sundaram@Sun.COM 			    DLADM_PROP_VAL_MAX);
38598118SVasumathi.Sundaram@Sun.COM 		}
38605903Ssowmini 		*val_cnt = 1;
38618460SArtem.Kachitchkin@Sun.COM 	} else if ((status == DLADM_STATUS_NOTSUP) &&
38628460SArtem.Kachitchkin@Sun.COM 	    (type == DLADM_PROP_VAL_CURRENT)) {
38638460SArtem.Kachitchkin@Sun.COM 		status = DLADM_STATUS_NOTFOUND;
38645903Ssowmini 	}
38656512Ssowmini 	free(dip);
38665903Ssowmini 	return (status);
38675903Ssowmini }
38686512Ssowmini 
38696512Ssowmini 
38706512Ssowmini static dladm_status_t
38718453SAnurag.Maskey@Sun.COM i_dladm_getset_defval(dladm_handle_t handle, prop_desc_t *pdp,
38728453SAnurag.Maskey@Sun.COM     datalink_id_t linkid, datalink_media_t media, uint_t flags)
38736512Ssowmini {
38746512Ssowmini 	dladm_status_t status;
38756512Ssowmini 	char **prop_vals = NULL, *buf;
38766512Ssowmini 	size_t bufsize;
38776512Ssowmini 	uint_t cnt;
38786512Ssowmini 	int i;
38798118SVasumathi.Sundaram@Sun.COM 	uint_t perm_flags;
38806512Ssowmini 
38816512Ssowmini 	/*
38826512Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
38836512Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
38846512Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
38856512Ssowmini 	 */
38866512Ssowmini 	bufsize =
38876512Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
38886512Ssowmini 	buf = malloc(bufsize);
38896512Ssowmini 	prop_vals = (char **)(void *)buf;
38906512Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
38916512Ssowmini 		prop_vals[i] = buf +
38926512Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
38936512Ssowmini 		    i * DLADM_PROP_VAL_MAX;
38946512Ssowmini 	}
38956768Sar224390 
38966768Sar224390 	/*
38977342SAruna.Ramakrishna@Sun.COM 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
38987342SAruna.Ramakrishna@Sun.COM 	 * string, the "" itself is used to reset the property (exceptions
38997342SAruna.Ramakrishna@Sun.COM 	 * are zone and autopush, which populate vdp->vd_val). So
39007342SAruna.Ramakrishna@Sun.COM 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
39017342SAruna.Ramakrishna@Sun.COM 	 * down on the setprop using the global values in the table. For
39027342SAruna.Ramakrishna@Sun.COM 	 * other cases (vd_name is ""), doing reset-linkprop will cause
39037342SAruna.Ramakrishna@Sun.COM 	 * libdladm to do a getprop to find the default value and then do
39047342SAruna.Ramakrishna@Sun.COM 	 * a setprop to reset the value to default.
39056768Sar224390 	 */
39068453SAnurag.Maskey@Sun.COM 	status = pdp->pd_get(handle, pdp, linkid, prop_vals, &cnt, media,
3907*11878SVenu.Iyer@Sun.COM 	    DLD_PROP_DEFAULT, &perm_flags);
39086512Ssowmini 	if (status == DLADM_STATUS_OK) {
39098118SVasumathi.Sundaram@Sun.COM 		if (perm_flags == MAC_PROP_PERM_RW) {
39108453SAnurag.Maskey@Sun.COM 			status = i_dladm_set_single_prop(handle, linkid,
39118453SAnurag.Maskey@Sun.COM 			    pdp->pd_class, media, pdp, prop_vals, cnt, flags);
39128118SVasumathi.Sundaram@Sun.COM 		}
39138118SVasumathi.Sundaram@Sun.COM 		else
39148118SVasumathi.Sundaram@Sun.COM 			status = DLADM_STATUS_NOTSUP;
39156512Ssowmini 	}
39166512Ssowmini 	free(buf);
39176512Ssowmini 	return (status);
39186512Ssowmini }
39197663SSowmini.Varadhan@Sun.COM 
392010491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
392110491SRishi.Srivatsavai@Sun.COM static dladm_status_t
3922*11878SVenu.Iyer@Sun.COM get_stp(dladm_handle_t handle, struct prop_desc *pd, datalink_id_t linkid,
392310491SRishi.Srivatsavai@Sun.COM     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags,
392410491SRishi.Srivatsavai@Sun.COM     uint_t *perm_flags)
392510491SRishi.Srivatsavai@Sun.COM {
392610491SRishi.Srivatsavai@Sun.COM 	const bridge_public_prop_t *bpp;
392710491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
392810491SRishi.Srivatsavai@Sun.COM 	int val, i;
392910491SRishi.Srivatsavai@Sun.COM 
393010491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
393110491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
393210491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
393310491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
393410491SRishi.Srivatsavai@Sun.COM 	for (bpp = bridge_prop; bpp->bpp_name != NULL; bpp++)
393510491SRishi.Srivatsavai@Sun.COM 		if (strcmp(bpp->bpp_name, pd->pd_name) == 0)
393610491SRishi.Srivatsavai@Sun.COM 			break;
393710491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_port_cfg(handle, linkid, bpp->bpp_code, &val);
393810491SRishi.Srivatsavai@Sun.COM 	/* If the daemon isn't running, then return the persistent value */
393910491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
394010491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
394110491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
394210491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
394310491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
394410491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
394510491SRishi.Srivatsavai@Sun.COM 	}
394610491SRishi.Srivatsavai@Sun.COM 	if (retv != DLADM_STATUS_OK) {
394710491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
394810491SRishi.Srivatsavai@Sun.COM 		return (retv);
394910491SRishi.Srivatsavai@Sun.COM 	}
395010491SRishi.Srivatsavai@Sun.COM 	if (val == pd->pd_defval.vd_val && pd->pd_defval.vd_name[0] != '\0') {
395110491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
395210491SRishi.Srivatsavai@Sun.COM 		    DLADM_PROP_VAL_MAX);
395310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
395410491SRishi.Srivatsavai@Sun.COM 	}
395510491SRishi.Srivatsavai@Sun.COM 	for (i = 0; i < pd->pd_noptval; i++) {
395610491SRishi.Srivatsavai@Sun.COM 		if (val == pd->pd_optval[i].vd_val) {
395710491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_optval[i].vd_name,
395810491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
395910491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_OK);
396010491SRishi.Srivatsavai@Sun.COM 		}
396110491SRishi.Srivatsavai@Sun.COM 	}
396210491SRishi.Srivatsavai@Sun.COM 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", (unsigned)val);
396310491SRishi.Srivatsavai@Sun.COM 	return (DLADM_STATUS_OK);
396410491SRishi.Srivatsavai@Sun.COM }
396510491SRishi.Srivatsavai@Sun.COM 
396610491SRishi.Srivatsavai@Sun.COM /* ARGSUSED1 */
396710491SRishi.Srivatsavai@Sun.COM static dladm_status_t
396810491SRishi.Srivatsavai@Sun.COM set_stp_prop(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
396910491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
397010491SRishi.Srivatsavai@Sun.COM {
397110491SRishi.Srivatsavai@Sun.COM 	/*
397210491SRishi.Srivatsavai@Sun.COM 	 * Special case for mcheck: the daemon resets the value to zero, and we
397310491SRishi.Srivatsavai@Sun.COM 	 * don't want the daemon to refresh itself; it leads to deadlock.
397410491SRishi.Srivatsavai@Sun.COM 	 */
397510491SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_NOREFRESH)
397610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
397710491SRishi.Srivatsavai@Sun.COM 
397810491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
397910491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
398010491SRishi.Srivatsavai@Sun.COM }
398110491SRishi.Srivatsavai@Sun.COM 
398210491SRishi.Srivatsavai@Sun.COM /*
398310491SRishi.Srivatsavai@Sun.COM  * This is used only for stp_priority, stp_cost, and stp_mcheck.
398410491SRishi.Srivatsavai@Sun.COM  */
398510491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
398610491SRishi.Srivatsavai@Sun.COM static dladm_status_t
398710491SRishi.Srivatsavai@Sun.COM check_stp_prop(dladm_handle_t handle, struct prop_desc *pd,
3988*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
3989*11878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
399010491SRishi.Srivatsavai@Sun.COM {
399110491SRishi.Srivatsavai@Sun.COM 	char *cp;
399210491SRishi.Srivatsavai@Sun.COM 	boolean_t iscost;
399310491SRishi.Srivatsavai@Sun.COM 
399410491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
399510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
399610491SRishi.Srivatsavai@Sun.COM 
399710491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
399810491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 0;
399910491SRishi.Srivatsavai@Sun.COM 	} else {
400010491SRishi.Srivatsavai@Sun.COM 		/* Only stp_priority and stp_cost use this function */
400110491SRishi.Srivatsavai@Sun.COM 		iscost = strcmp(pd->pd_name, "stp_cost") == 0;
400210491SRishi.Srivatsavai@Sun.COM 
400310491SRishi.Srivatsavai@Sun.COM 		if (iscost && strcmp(prop_val[0], "auto") == 0) {
400410491SRishi.Srivatsavai@Sun.COM 			/* Illegal value 0 is allowed to mean "automatic" */
400510491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = 0;
400610491SRishi.Srivatsavai@Sun.COM 		} else {
400710491SRishi.Srivatsavai@Sun.COM 			errno = 0;
400810491SRishi.Srivatsavai@Sun.COM 			vdp->vd_val = strtoul(prop_val[0], &cp, 0);
400910491SRishi.Srivatsavai@Sun.COM 			if (errno != 0 || *cp != '\0')
401010491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_BADVAL);
401110491SRishi.Srivatsavai@Sun.COM 		}
401210491SRishi.Srivatsavai@Sun.COM 	}
401310491SRishi.Srivatsavai@Sun.COM 
401410491SRishi.Srivatsavai@Sun.COM 	if (iscost) {
401510491SRishi.Srivatsavai@Sun.COM 		return (vdp->vd_val > 65535 ? DLADM_STATUS_BADVAL :
401610491SRishi.Srivatsavai@Sun.COM 		    DLADM_STATUS_OK);
401710491SRishi.Srivatsavai@Sun.COM 	} else {
401810491SRishi.Srivatsavai@Sun.COM 		if (vdp->vd_val > 255)
401910491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
402010491SRishi.Srivatsavai@Sun.COM 		/*
402110491SRishi.Srivatsavai@Sun.COM 		 * If the user is setting stp_mcheck non-zero, then (per the
402210491SRishi.Srivatsavai@Sun.COM 		 * IEEE management standards and UNH testing) we need to check
402310491SRishi.Srivatsavai@Sun.COM 		 * whether this link is part of a bridge that is running RSTP.
402410491SRishi.Srivatsavai@Sun.COM 		 * If it's not, then setting the flag is an error.  Note that
402510491SRishi.Srivatsavai@Sun.COM 		 * errors are intentionally discarded here; it's the value
402610491SRishi.Srivatsavai@Sun.COM 		 * that's the problem -- it's not a bad value, merely one that
402710491SRishi.Srivatsavai@Sun.COM 		 * can't be used now.
402810491SRishi.Srivatsavai@Sun.COM 		 */
402910491SRishi.Srivatsavai@Sun.COM 		if (strcmp(pd->pd_name, "stp_mcheck") == 0 &&
403010491SRishi.Srivatsavai@Sun.COM 		    vdp->vd_val != 0) {
403110491SRishi.Srivatsavai@Sun.COM 			char bridge[MAXLINKNAMELEN];
403210491SRishi.Srivatsavai@Sun.COM 			UID_STP_CFG_T cfg;
403310491SRishi.Srivatsavai@Sun.COM 			dladm_bridge_prot_t brprot;
403410491SRishi.Srivatsavai@Sun.COM 
403510491SRishi.Srivatsavai@Sun.COM 			if (dladm_bridge_getlink(handle, linkid, bridge,
403610491SRishi.Srivatsavai@Sun.COM 			    sizeof (bridge)) != DLADM_STATUS_OK ||
403710491SRishi.Srivatsavai@Sun.COM 			    dladm_bridge_get_properties(bridge, &cfg,
403810491SRishi.Srivatsavai@Sun.COM 			    &brprot) != DLADM_STATUS_OK)
403910491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
404010491SRishi.Srivatsavai@Sun.COM 			if (cfg.force_version <= 1)
404110491SRishi.Srivatsavai@Sun.COM 				return (DLADM_STATUS_FAILED);
404210491SRishi.Srivatsavai@Sun.COM 		}
404310491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
404410491SRishi.Srivatsavai@Sun.COM 	}
404510491SRishi.Srivatsavai@Sun.COM }
404610491SRishi.Srivatsavai@Sun.COM 
404710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
404810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
404910491SRishi.Srivatsavai@Sun.COM get_bridge_forward(dladm_handle_t handle, struct prop_desc *pd,
405010491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
405110491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
405210491SRishi.Srivatsavai@Sun.COM {
405310491SRishi.Srivatsavai@Sun.COM 	dladm_status_t retv;
405410491SRishi.Srivatsavai@Sun.COM 	uint_t val;
405510491SRishi.Srivatsavai@Sun.COM 
405610491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
405710491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
405810491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
405910491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
406010491SRishi.Srivatsavai@Sun.COM 	retv = dladm_bridge_get_forwarding(handle, linkid, &val);
406110491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_NOTFOUND) {
406210491SRishi.Srivatsavai@Sun.COM 		if (i_dladm_get_linkprop_db(handle, linkid, pd->pd_name,
406310491SRishi.Srivatsavai@Sun.COM 		    prop_val, val_cnt) != DLADM_STATUS_OK)
406410491SRishi.Srivatsavai@Sun.COM 			(void) strlcpy(*prop_val, pd->pd_defval.vd_name,
406510491SRishi.Srivatsavai@Sun.COM 			    DLADM_PROP_VAL_MAX);
406610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
406710491SRishi.Srivatsavai@Sun.COM 	}
406810491SRishi.Srivatsavai@Sun.COM 	if (retv == DLADM_STATUS_OK)
406910491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", val);
407010491SRishi.Srivatsavai@Sun.COM 	else
407110491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
407210491SRishi.Srivatsavai@Sun.COM 	return (retv);
407310491SRishi.Srivatsavai@Sun.COM }
407410491SRishi.Srivatsavai@Sun.COM 
407510491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
407610491SRishi.Srivatsavai@Sun.COM static dladm_status_t
407710491SRishi.Srivatsavai@Sun.COM set_bridge_forward(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
407810491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
407910491SRishi.Srivatsavai@Sun.COM {
408010491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
408110491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
408210491SRishi.Srivatsavai@Sun.COM }
408310491SRishi.Srivatsavai@Sun.COM 
408410491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
408510491SRishi.Srivatsavai@Sun.COM static dladm_status_t
408610491SRishi.Srivatsavai@Sun.COM get_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
408710491SRishi.Srivatsavai@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
408810491SRishi.Srivatsavai@Sun.COM     datalink_media_t media, uint_t flags, uint_t *perm_flags)
408910491SRishi.Srivatsavai@Sun.COM {
409010491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
409110491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
409210491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
409310491SRishi.Srivatsavai@Sun.COM 
409410491SRishi.Srivatsavai@Sun.COM 	if (flags != 0)
409510491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
409610491SRishi.Srivatsavai@Sun.COM 	*perm_flags = MAC_PROP_PERM_RW;
409710491SRishi.Srivatsavai@Sun.COM 	*val_cnt = 1;
409810491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
409910491SRishi.Srivatsavai@Sun.COM 	    0, &status);
410010491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
410110491SRishi.Srivatsavai@Sun.COM 		return (status);
410210491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_FALSE);
410310491SRishi.Srivatsavai@Sun.COM 	if (status == DLADM_STATUS_OK) {
410410491SRishi.Srivatsavai@Sun.COM 		(void) memcpy(&pvid, dip->pr_val, sizeof (pvid));
410510491SRishi.Srivatsavai@Sun.COM 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%u", pvid);
410610491SRishi.Srivatsavai@Sun.COM 	} else {
410710491SRishi.Srivatsavai@Sun.COM 		(void) strlcpy(*prop_val, "?", DLADM_PROP_VAL_MAX);
410810491SRishi.Srivatsavai@Sun.COM 	}
410910491SRishi.Srivatsavai@Sun.COM 	free(dip);
411010491SRishi.Srivatsavai@Sun.COM 	return (status);
411110491SRishi.Srivatsavai@Sun.COM }
411210491SRishi.Srivatsavai@Sun.COM 
411310491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
411410491SRishi.Srivatsavai@Sun.COM static dladm_status_t
411510491SRishi.Srivatsavai@Sun.COM set_bridge_pvid(dladm_handle_t handle, prop_desc_t *pd, datalink_id_t linkid,
411610491SRishi.Srivatsavai@Sun.COM     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
411710491SRishi.Srivatsavai@Sun.COM {
411810491SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
411910491SRishi.Srivatsavai@Sun.COM 	dld_ioc_macprop_t *dip;
412010491SRishi.Srivatsavai@Sun.COM 	uint16_t pvid;
412110491SRishi.Srivatsavai@Sun.COM 
412210491SRishi.Srivatsavai@Sun.COM 	dip = i_dladm_buf_alloc_by_id(sizeof (uint16_t), linkid, MAC_PROP_PVID,
412310491SRishi.Srivatsavai@Sun.COM 	    0, &status);
412410491SRishi.Srivatsavai@Sun.COM 	if (dip == NULL)
412510491SRishi.Srivatsavai@Sun.COM 		return (status);
412610491SRishi.Srivatsavai@Sun.COM 	pvid = vdp->vd_val;
412710491SRishi.Srivatsavai@Sun.COM 	(void) memcpy(dip->pr_val, &pvid, sizeof (pvid));
412810491SRishi.Srivatsavai@Sun.COM 	status = i_dladm_macprop(handle, dip, B_TRUE);
412910491SRishi.Srivatsavai@Sun.COM 	free(dip);
413010491SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
413110491SRishi.Srivatsavai@Sun.COM 		return (status);
413210491SRishi.Srivatsavai@Sun.COM 
413310491SRishi.Srivatsavai@Sun.COM 	/* Tell the running daemon, if any */
413410491SRishi.Srivatsavai@Sun.COM 	return (dladm_bridge_refresh(handle, linkid));
413510491SRishi.Srivatsavai@Sun.COM }
413610491SRishi.Srivatsavai@Sun.COM 
413710491SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
413810491SRishi.Srivatsavai@Sun.COM static dladm_status_t
413910491SRishi.Srivatsavai@Sun.COM check_bridge_pvid(dladm_handle_t handle, struct prop_desc *pd,
4140*11878SVenu.Iyer@Sun.COM     datalink_id_t linkid, char **prop_val, uint_t val_cnt, uint_t flags,
4141*11878SVenu.Iyer@Sun.COM     val_desc_t *vdp, datalink_media_t media)
414210491SRishi.Srivatsavai@Sun.COM {
414310491SRishi.Srivatsavai@Sun.COM 	char *cp;
414410491SRishi.Srivatsavai@Sun.COM 
414510491SRishi.Srivatsavai@Sun.COM 	if (val_cnt != 1)
414610491SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADVALCNT);
414710491SRishi.Srivatsavai@Sun.COM 
414810491SRishi.Srivatsavai@Sun.COM 	if (prop_val == NULL) {
414910491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = 1;
415010491SRishi.Srivatsavai@Sun.COM 	} else {
415110491SRishi.Srivatsavai@Sun.COM 		errno = 0;
415210491SRishi.Srivatsavai@Sun.COM 		vdp->vd_val = strtoul(prop_val[0], &cp, 0);
415310491SRishi.Srivatsavai@Sun.COM 		if (errno != 0 || *cp != '\0')
415410491SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADVAL);
415510491SRishi.Srivatsavai@Sun.COM 	}
415610491SRishi.Srivatsavai@Sun.COM 
415710491SRishi.Srivatsavai@Sun.COM 	return (vdp->vd_val > VLAN_ID_MAX ? DLADM_STATUS_BADVAL :
415810491SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK);
415910491SRishi.Srivatsavai@Sun.COM }
416010491SRishi.Srivatsavai@Sun.COM 
41617663SSowmini.Varadhan@Sun.COM dladm_status_t
41628453SAnurag.Maskey@Sun.COM i_dladm_wlan_param(dladm_handle_t handle, datalink_id_t linkid, void *buf,
41638453SAnurag.Maskey@Sun.COM     mac_prop_id_t cmd, size_t len, boolean_t set)
41647663SSowmini.Varadhan@Sun.COM {
41657663SSowmini.Varadhan@Sun.COM 	uint32_t		flags;
41667663SSowmini.Varadhan@Sun.COM 	dladm_status_t		status;
41677663SSowmini.Varadhan@Sun.COM 	uint32_t		media;
41687663SSowmini.Varadhan@Sun.COM 	dld_ioc_macprop_t	*dip;
41697663SSowmini.Varadhan@Sun.COM 	void			*dp;
41707663SSowmini.Varadhan@Sun.COM 
41718453SAnurag.Maskey@Sun.COM 	if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
41728453SAnurag.Maskey@Sun.COM 	    &media, NULL, 0)) != DLADM_STATUS_OK) {
41737663SSowmini.Varadhan@Sun.COM 		return (status);
41747663SSowmini.Varadhan@Sun.COM 	}
41757663SSowmini.Varadhan@Sun.COM 
41767663SSowmini.Varadhan@Sun.COM 	if (media != DL_WIFI)
41777663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_BADARG);
41787663SSowmini.Varadhan@Sun.COM 
41797663SSowmini.Varadhan@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
41807663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_TEMPONLY);
41817663SSowmini.Varadhan@Sun.COM 
41827663SSowmini.Varadhan@Sun.COM 	if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET))
41837663SSowmini.Varadhan@Sun.COM 		len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1;
41847663SSowmini.Varadhan@Sun.COM 
41857663SSowmini.Varadhan@Sun.COM 	dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status);
41867663SSowmini.Varadhan@Sun.COM 	if (dip == NULL)
41877663SSowmini.Varadhan@Sun.COM 		return (DLADM_STATUS_NOMEM);
41887663SSowmini.Varadhan@Sun.COM 
41897663SSowmini.Varadhan@Sun.COM 	dp = (uchar_t *)dip->pr_val;
41907663SSowmini.Varadhan@Sun.COM 	if (set)
41917663SSowmini.Varadhan@Sun.COM 		(void) memcpy(dp, buf, len);
41927663SSowmini.Varadhan@Sun.COM 
41938453SAnurag.Maskey@Sun.COM 	status = i_dladm_macprop(handle, dip, set);
419410191SSowmini.Varadhan@Sun.COM 	if (status == DLADM_STATUS_OK) {
41957663SSowmini.Varadhan@Sun.COM 		if (!set)
41967663SSowmini.Varadhan@Sun.COM 			(void) memcpy(buf, dp, len);
41977663SSowmini.Varadhan@Sun.COM 	}
41987663SSowmini.Varadhan@Sun.COM 
41997663SSowmini.Varadhan@Sun.COM 	free(dip);
42007663SSowmini.Varadhan@Sun.COM 	return (status);
42017663SSowmini.Varadhan@Sun.COM }
42027663SSowmini.Varadhan@Sun.COM 
42038275SEric Cheng dladm_status_t
42048275SEric Cheng dladm_parse_link_props(char *str, dladm_arg_list_t **listp, boolean_t novalues)
42058275SEric Cheng {
42068460SArtem.Kachitchkin@Sun.COM 	return (dladm_parse_args(str, listp, novalues));
42078275SEric Cheng }
42088275SEric Cheng 
42098275SEric Cheng /*
42108275SEric Cheng  * Retrieve the one link property from the database
42118275SEric Cheng  */
42128275SEric Cheng /*ARGSUSED*/
42138275SEric Cheng static int
42148453SAnurag.Maskey@Sun.COM i_dladm_get_one_prop(dladm_handle_t handle, datalink_id_t linkid,
42158453SAnurag.Maskey@Sun.COM     const char *prop_name, void *arg)
42168275SEric Cheng {
42178275SEric Cheng 	dladm_arg_list_t	*proplist = arg;
42188275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
42198275SEric Cheng 
42208275SEric Cheng 	aip = &proplist->al_info[proplist->al_count];
42218275SEric Cheng 	/*
42228275SEric Cheng 	 * it is fine to point to prop_name since prop_name points to the
42238275SEric Cheng 	 * prop_table[n].pd_name.
42248275SEric Cheng 	 */
42258275SEric Cheng 	aip->ai_name = prop_name;
42268275SEric Cheng 
42278453SAnurag.Maskey@Sun.COM 	(void) dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_PERSISTENT,
42288453SAnurag.Maskey@Sun.COM 	    prop_name, aip->ai_val, &aip->ai_count);
42298275SEric Cheng 
42308275SEric Cheng 	if (aip->ai_count != 0)
42318275SEric Cheng 		proplist->al_count++;
42328275SEric Cheng 
42338275SEric Cheng 	return (DLADM_WALK_CONTINUE);
42348275SEric Cheng }
42358275SEric Cheng 
42368275SEric Cheng 
42378275SEric Cheng /*
42388275SEric Cheng  * Retrieve all link properties for a link from the database and
42398275SEric Cheng  * return a property list.
42408275SEric Cheng  */
42418275SEric Cheng dladm_status_t
42428453SAnurag.Maskey@Sun.COM dladm_link_get_proplist(dladm_handle_t handle, datalink_id_t linkid,
42438453SAnurag.Maskey@Sun.COM     dladm_arg_list_t **listp)
42448275SEric Cheng {
42458275SEric Cheng 	dladm_arg_list_t	*list;
42468275SEric Cheng 	dladm_status_t		status = DLADM_STATUS_OK;
42478275SEric Cheng 
42488275SEric Cheng 	list = calloc(1, sizeof (dladm_arg_list_t));
42498275SEric Cheng 	if (list == NULL)
42508275SEric Cheng 		return (dladm_errno2status(errno));
42518275SEric Cheng 
42528453SAnurag.Maskey@Sun.COM 	status = dladm_walk_linkprop(handle, linkid, list,
42538453SAnurag.Maskey@Sun.COM 	    i_dladm_get_one_prop);
42548275SEric Cheng 
42558275SEric Cheng 	*listp = list;
42568275SEric Cheng 	return (status);
42578275SEric Cheng }
42588275SEric Cheng 
42598275SEric Cheng /*
42608275SEric Cheng  * Retrieve the named property from a proplist, check the value and
42618275SEric Cheng  * convert to a kernel structure.
42628275SEric Cheng  */
42638275SEric Cheng static dladm_status_t
42648453SAnurag.Maskey@Sun.COM i_dladm_link_proplist_extract_one(dladm_handle_t handle,
4265*11878SVenu.Iyer@Sun.COM     dladm_arg_list_t *proplist, const char *name, uint_t flags, void *arg)
42668275SEric Cheng {
42678275SEric Cheng 	dladm_status_t		status;
42688275SEric Cheng 	dladm_arg_info_t	*aip = NULL;
42698275SEric Cheng 	int			i, j;
42708275SEric Cheng 
42718275SEric Cheng 	/* Find named property in proplist */
42728275SEric Cheng 	for (i = 0; i < proplist->al_count; i++) {
42738275SEric Cheng 		aip = &proplist->al_info[i];
42748275SEric Cheng 		if (strcasecmp(aip->ai_name, name) == 0)
42758275SEric Cheng 			break;
42768275SEric Cheng 	}
42778275SEric Cheng 
42788275SEric Cheng 	/* Property not in list */
42798275SEric Cheng 	if (i == proplist->al_count)
42808275SEric Cheng 		return (DLADM_STATUS_OK);
42818275SEric Cheng 
42828275SEric Cheng 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
42838275SEric Cheng 		prop_desc_t	*pdp = &prop_table[i];
42848275SEric Cheng 		val_desc_t	*vdp;
42858275SEric Cheng 
42868275SEric Cheng 		vdp = malloc(sizeof (val_desc_t) * aip->ai_count);
42878275SEric Cheng 		if (vdp == NULL)
42888275SEric Cheng 			return (DLADM_STATUS_NOMEM);
42898275SEric Cheng 
42908275SEric Cheng 		if (strcasecmp(aip->ai_name, pdp->pd_name) != 0)
42918275SEric Cheng 			continue;
42928275SEric Cheng 
42938275SEric Cheng 		if (aip->ai_val == NULL)
42948275SEric Cheng 			return (DLADM_STATUS_BADARG);
42958275SEric Cheng 
42968275SEric Cheng 		/* Check property value */
42978275SEric Cheng 		if (pdp->pd_check != NULL) {
42988453SAnurag.Maskey@Sun.COM 			status = pdp->pd_check(handle, pdp, 0, aip->ai_val,
4299*11878SVenu.Iyer@Sun.COM 			    aip->ai_count, flags, vdp, 0);
43008275SEric Cheng 		} else {
43018275SEric Cheng 			status = DLADM_STATUS_BADARG;
43028275SEric Cheng 		}
43038275SEric Cheng 
43048275SEric Cheng 		if (status != DLADM_STATUS_OK)
43058275SEric Cheng 			return (status);
43068275SEric Cheng 
43078275SEric Cheng 		for (j = 0; j < DLADM_MAX_RSRC_PROP; j++) {
43088275SEric Cheng 			resource_prop_t	*rpp = &rsrc_prop_table[j];
43098275SEric Cheng 
43108275SEric Cheng 			if (strcasecmp(aip->ai_name, rpp->rp_name) != 0)
43118275SEric Cheng 				continue;
43128275SEric Cheng 
43138275SEric Cheng 			/* Extract kernel structure */
43148275SEric Cheng 			if (rpp->rp_extract != NULL) {
431510734SEric Cheng 				status = rpp->rp_extract(vdp,
431610734SEric Cheng 				    aip->ai_count, arg);
43178275SEric Cheng 			} else {
43188275SEric Cheng 				status = DLADM_STATUS_BADARG;
43198275SEric Cheng 			}
43208275SEric Cheng 			break;
43218275SEric Cheng 		}
43228275SEric Cheng 
43238275SEric Cheng 		if (status != DLADM_STATUS_OK)
43248275SEric Cheng 			return (status);
43258275SEric Cheng 
43268275SEric Cheng 		break;
43278275SEric Cheng 	}
43288275SEric Cheng 	return (status);
43298275SEric Cheng }
43308275SEric Cheng 
43318275SEric Cheng /*
43328275SEric Cheng  * Extract properties from a proplist and convert to mac_resource_props_t.
43338275SEric Cheng  */
43348275SEric Cheng dladm_status_t
43358453SAnurag.Maskey@Sun.COM dladm_link_proplist_extract(dladm_handle_t handle, dladm_arg_list_t *proplist,
4336*11878SVenu.Iyer@Sun.COM     mac_resource_props_t *mrp, uint_t flags)
43378275SEric Cheng {
433810734SEric Cheng 	dladm_status_t	status;
433910734SEric Cheng 	int		i;
434010734SEric Cheng 
434110734SEric Cheng 	for (i = 0; i < DLADM_MAX_RSRC_PROP; i++) {
434210734SEric Cheng 		status = i_dladm_link_proplist_extract_one(handle,
4343*11878SVenu.Iyer@Sun.COM 		    proplist, rsrc_prop_table[i].rp_name, flags, mrp);
434410734SEric Cheng 		if (status != DLADM_STATUS_OK)
434510734SEric Cheng 			return (status);
434610734SEric Cheng 	}
43478275SEric Cheng 	return (status);
43488275SEric Cheng }
43498275SEric Cheng 
43508275SEric Cheng static const char *
43518275SEric Cheng dladm_perm2str(uint_t perm, char *buf)
43528275SEric Cheng {
43538275SEric Cheng 	(void) snprintf(buf, DLADM_STRSIZE, "%c%c",
43548275SEric Cheng 	    ((perm & MAC_PROP_PERM_READ) != 0) ? 'r' : '-',
43558275SEric Cheng 	    ((perm & MAC_PROP_PERM_WRITE) != 0) ? 'w' : '-');
43568275SEric Cheng 	return (buf);
43578275SEric Cheng }
43588306SSowmini.Varadhan@Sun.COM 
43598306SSowmini.Varadhan@Sun.COM dladm_status_t
4360*11878SVenu.Iyer@Sun.COM dladm_get_state(dladm_handle_t handle, datalink_id_t linkid,
43618453SAnurag.Maskey@Sun.COM     link_state_t *state)
43628306SSowmini.Varadhan@Sun.COM {
43638306SSowmini.Varadhan@Sun.COM 	uint_t			perms;
43648306SSowmini.Varadhan@Sun.COM 
4365*11878SVenu.Iyer@Sun.COM 	return (i_dladm_get_public_prop(handle, linkid, "state", 0,
4366*11878SVenu.Iyer@Sun.COM 	    &perms, state, sizeof (*state)));
43678306SSowmini.Varadhan@Sun.COM }
43688460SArtem.Kachitchkin@Sun.COM 
43698460SArtem.Kachitchkin@Sun.COM boolean_t
43708460SArtem.Kachitchkin@Sun.COM dladm_attr_is_linkprop(const char *name)
43718460SArtem.Kachitchkin@Sun.COM {
43728460SArtem.Kachitchkin@Sun.COM 	/* non-property attribute names */
43738460SArtem.Kachitchkin@Sun.COM 	const char *nonprop[] = {
43748460SArtem.Kachitchkin@Sun.COM 		/* dlmgmtd core attributes */
43758460SArtem.Kachitchkin@Sun.COM 		"name",
43768460SArtem.Kachitchkin@Sun.COM 		"class",
43778460SArtem.Kachitchkin@Sun.COM 		"media",
43788460SArtem.Kachitchkin@Sun.COM 		FPHYMAJ,
43798460SArtem.Kachitchkin@Sun.COM 		FPHYINST,
43808460SArtem.Kachitchkin@Sun.COM 		FDEVNAME,
43818460SArtem.Kachitchkin@Sun.COM 
43828460SArtem.Kachitchkin@Sun.COM 		/* other attributes for vlan, aggr, etc */
43838460SArtem.Kachitchkin@Sun.COM 		DLADM_ATTR_NAMES
43848460SArtem.Kachitchkin@Sun.COM 	};
43858460SArtem.Kachitchkin@Sun.COM 	boolean_t	is_nonprop = B_FALSE;
43868460SArtem.Kachitchkin@Sun.COM 	int		i;
43878460SArtem.Kachitchkin@Sun.COM 
43888460SArtem.Kachitchkin@Sun.COM 	for (i = 0; i < sizeof (nonprop) / sizeof (nonprop[0]); i++) {
43898460SArtem.Kachitchkin@Sun.COM 		if (strcmp(name, nonprop[i]) == 0) {
43908460SArtem.Kachitchkin@Sun.COM 			is_nonprop = B_TRUE;
43918460SArtem.Kachitchkin@Sun.COM 			break;
43928460SArtem.Kachitchkin@Sun.COM 		}
43938460SArtem.Kachitchkin@Sun.COM 	}
43948460SArtem.Kachitchkin@Sun.COM 
43958460SArtem.Kachitchkin@Sun.COM 	return (!is_nonprop);
43968460SArtem.Kachitchkin@Sun.COM }
4397*11878SVenu.Iyer@Sun.COM 
4398*11878SVenu.Iyer@Sun.COM dladm_status_t
4399*11878SVenu.Iyer@Sun.COM dladm_linkprop_is_set(dladm_handle_t handle, datalink_id_t linkid,
4400*11878SVenu.Iyer@Sun.COM     dladm_prop_type_t type, const char *prop_name, boolean_t *is_set)
4401*11878SVenu.Iyer@Sun.COM {
4402*11878SVenu.Iyer@Sun.COM 	char		*buf, **propvals;
4403*11878SVenu.Iyer@Sun.COM 	uint_t		valcnt = DLADM_MAX_PROP_VALCNT;
4404*11878SVenu.Iyer@Sun.COM 	int		i;
4405*11878SVenu.Iyer@Sun.COM 	dladm_status_t	status = DLADM_STATUS_OK;
4406*11878SVenu.Iyer@Sun.COM 
4407*11878SVenu.Iyer@Sun.COM 	*is_set = B_FALSE;
4408*11878SVenu.Iyer@Sun.COM 
4409*11878SVenu.Iyer@Sun.COM 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
4410*11878SVenu.Iyer@Sun.COM 	    DLADM_MAX_PROP_VALCNT)) == NULL)
4411*11878SVenu.Iyer@Sun.COM 		return (DLADM_STATUS_NOMEM);
4412*11878SVenu.Iyer@Sun.COM 
4413*11878SVenu.Iyer@Sun.COM 	propvals = (char **)(void *)buf;
4414*11878SVenu.Iyer@Sun.COM 	for (i = 0; i < valcnt; i++) {
4415*11878SVenu.Iyer@Sun.COM 		propvals[i] = buf +
4416*11878SVenu.Iyer@Sun.COM 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
4417*11878SVenu.Iyer@Sun.COM 		    i * DLADM_PROP_VAL_MAX;
4418*11878SVenu.Iyer@Sun.COM 	}
4419*11878SVenu.Iyer@Sun.COM 
4420*11878SVenu.Iyer@Sun.COM 	if (dladm_get_linkprop(handle, linkid, type, prop_name, propvals,
4421*11878SVenu.Iyer@Sun.COM 	    &valcnt) != DLADM_STATUS_OK) {
4422*11878SVenu.Iyer@Sun.COM 		goto done;
4423*11878SVenu.Iyer@Sun.COM 	}
4424*11878SVenu.Iyer@Sun.COM 
4425*11878SVenu.Iyer@Sun.COM 	if ((strcmp(prop_name, "pool") == 0) && (strlen(*propvals) != 0)) {
4426*11878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
4427*11878SVenu.Iyer@Sun.COM 	} else if ((strcmp(prop_name, "cpus") == 0) && (valcnt != 0)) {
4428*11878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
4429*11878SVenu.Iyer@Sun.COM 	} else if ((strcmp(prop_name, "_softmac") == 0) && (valcnt != 0) &&
4430*11878SVenu.Iyer@Sun.COM 	    (strcmp(propvals[0], "true") == 0)) {
4431*11878SVenu.Iyer@Sun.COM 		*is_set = B_TRUE;
4432*11878SVenu.Iyer@Sun.COM 	}
4433*11878SVenu.Iyer@Sun.COM 
4434*11878SVenu.Iyer@Sun.COM done:
4435*11878SVenu.Iyer@Sun.COM 	if (buf != NULL)
4436*11878SVenu.Iyer@Sun.COM 		free(buf);
4437*11878SVenu.Iyer@Sun.COM 	return (status);
4438*11878SVenu.Iyer@Sun.COM }
4439