xref: /titanic_44/usr/src/lib/libdladm/common/linkprop.c (revision 3bc21d0a9c7b31b1132c254e389a4114c23bcf00)
10ba2cbe9Sxc151355 /*
20ba2cbe9Sxc151355  * CDDL HEADER START
30ba2cbe9Sxc151355  *
40ba2cbe9Sxc151355  * The contents of this file are subject to the terms of the
50ba2cbe9Sxc151355  * Common Development and Distribution License (the "License").
60ba2cbe9Sxc151355  * You may not use this file except in compliance with the License.
70ba2cbe9Sxc151355  *
80ba2cbe9Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90ba2cbe9Sxc151355  * or http://www.opensolaris.org/os/licensing.
100ba2cbe9Sxc151355  * See the License for the specific language governing permissions
110ba2cbe9Sxc151355  * and limitations under the License.
120ba2cbe9Sxc151355  *
130ba2cbe9Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
140ba2cbe9Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150ba2cbe9Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
160ba2cbe9Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
170ba2cbe9Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
180ba2cbe9Sxc151355  *
190ba2cbe9Sxc151355  * CDDL HEADER END
200ba2cbe9Sxc151355  */
210ba2cbe9Sxc151355 /*
22d62bc4baSyz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230ba2cbe9Sxc151355  * Use is subject to license terms.
240ba2cbe9Sxc151355  */
250ba2cbe9Sxc151355 
260ba2cbe9Sxc151355 #include <stdlib.h>
270ba2cbe9Sxc151355 #include <strings.h>
280ba2cbe9Sxc151355 #include <errno.h>
290ba2cbe9Sxc151355 #include <ctype.h>
30d62bc4baSyz147064 #include <stddef.h>
31f4b3ec61Sdh155122 #include <sys/types.h>
320ba2cbe9Sxc151355 #include <sys/stat.h>
33f4b3ec61Sdh155122 #include <sys/dld.h>
34f4b3ec61Sdh155122 #include <sys/zone.h>
35f4b3ec61Sdh155122 #include <fcntl.h>
36f4b3ec61Sdh155122 #include <unistd.h>
37f4b3ec61Sdh155122 #include <libdevinfo.h>
38f4b3ec61Sdh155122 #include <zone.h>
39f595a68aSyz147064 #include <libdllink.h>
400ba2cbe9Sxc151355 #include <libdladm_impl.h>
41d62bc4baSyz147064 #include <libdlwlan_impl.h>
42f595a68aSyz147064 #include <libdlwlan.h>
43d62bc4baSyz147064 #include <libdlvlan.h>
44f4b3ec61Sdh155122 #include <dlfcn.h>
45f4b3ec61Sdh155122 #include <link.h>
46d62bc4baSyz147064 #include <inet/wifi_ioctl.h>
47e7801d59Ssowmini #include <libdladm.h>
48e7801d59Ssowmini #include <sys/param.h>
49e7801d59Ssowmini #include <inttypes.h>
50e7801d59Ssowmini #include <sys/ethernet.h>
51f4b3ec61Sdh155122 
52d62bc4baSyz147064 /*
53d62bc4baSyz147064  * The linkprop get() callback.
54e7801d59Ssowmini  * - pd: 	pointer to the struct prop_desc
55d62bc4baSyz147064  * - propstrp:	a property string array to keep the returned property.
56d62bc4baSyz147064  *		Caller allocated.
57d62bc4baSyz147064  * - cntp:	number of returned properties.
58d62bc4baSyz147064  *		Caller also uses it to indicate how many it expects.
59d62bc4baSyz147064  */
60e7801d59Ssowmini struct prop_desc;
61e7801d59Ssowmini 
62e7801d59Ssowmini typedef dladm_status_t	pd_getf_t(struct prop_desc *pd,
636b9e797cSsowmini 			datalink_id_t, char **propstp, uint_t *cntp,
644045d941Ssowmini 			datalink_media_t, uint_t);
65f4b3ec61Sdh155122 
66d62bc4baSyz147064 /*
67d62bc4baSyz147064  * The linkprop set() callback.
68d62bc4baSyz147064  * - propval:	a val_desc_t array which keeps the property values to be set.
69d62bc4baSyz147064  * - cnt:	number of properties to be set.
70e7801d59Ssowmini  * - flags: 	additional flags passed down the system call.
71e7801d59Ssowmini  *
72e7801d59Ssowmini  * pd_set takes val_desc_t given by pd_check(), translates it into
73e7801d59Ssowmini  * a format suitable for kernel consumption. This may require allocation
74e7801d59Ssowmini  * of ioctl buffers etc. pd_set() may call another common routine (used
75e7801d59Ssowmini  * by all other pd_sets) which invokes the ioctl.
76d62bc4baSyz147064  */
77e7801d59Ssowmini typedef dladm_status_t	pd_setf_t(struct prop_desc *, datalink_id_t,
786b9e797cSsowmini 			val_desc_t *propval, uint_t cnt, uint_t flags,
796b9e797cSsowmini 			datalink_media_t);
80f4b3ec61Sdh155122 
81f4b3ec61Sdh155122 
82d62bc4baSyz147064 /*
83d62bc4baSyz147064  * The linkprop check() callback.
84d62bc4baSyz147064  * - propstrp:	property string array which keeps the property to be checked.
85d62bc4baSyz147064  * - cnt:	number of properties.
86d62bc4baSyz147064  * - propval:	return value; the property values of the given property strings.
87e7801d59Ssowmini  *
88e7801d59Ssowmini  * pd_check checks that the input values are valid. It does so by
89e7801d59Ssowmini  * iteraring through the pd_modval list for the property. If
90e7801d59Ssowmini  * the modifiable values cannot be expressed as a list, a pd_check
91e7801d59Ssowmini  * specific to this property can be used. If the input values are
92e7801d59Ssowmini  * verified to be valid, pd_check allocates a val_desc_t and fills it
93e7801d59Ssowmini  * with either a val_desc_t found on the pd_modval list or something
94e7801d59Ssowmini  * generated on the fly.
95d62bc4baSyz147064  */
96e7801d59Ssowmini typedef dladm_status_t	pd_checkf_t(struct prop_desc *pd,
97e7801d59Ssowmini 			    datalink_id_t, char **propstrp,
986b9e797cSsowmini 			    uint_t cnt, val_desc_t *propval,
996b9e797cSsowmini 			    datalink_media_t);
100f4b3ec61Sdh155122 
101*3bc21d0aSAruna Ramakrishna - Sun Microsystems typedef struct dladm_public_prop_s {
1023fd94f8cSam223141 	mac_prop_id_t	pp_id;
103e7801d59Ssowmini 	size_t		pp_valsize;
104e7801d59Ssowmini 	char		*pp_name;
105e7801d59Ssowmini 	char		*pp_desc;
106*3bc21d0aSAruna Ramakrishna - Sun Microsystems } dladm_public_prop_t;
107e7801d59Ssowmini 
108*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dld_ioc_macprop_t *i_dladm_buf_alloc(size_t, datalink_id_t, const char *,
1094045d941Ssowmini 					uint_t, dladm_status_t *);
110*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_set_prop(datalink_id_t, const char *, char **,
111e7801d59Ssowmini 					uint_t, uint_t);
112*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t i_dladm_get_prop(datalink_id_t, const char *, char **,
1134045d941Ssowmini 					uint_t *, dladm_prop_type_t, uint_t);
114*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_public_prop_t *dladm_name2prop(const char *);
115*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dld_ioc_macprop_t *i_dladm_get_public_prop(datalink_id_t, char *, uint_t,
116*3bc21d0aSAruna Ramakrishna - Sun Microsystems 					dladm_status_t *);
117d62bc4baSyz147064 static pd_getf_t	do_get_zone, do_get_autopush, do_get_rate_mod,
118d62bc4baSyz147064 			do_get_rate_prop, do_get_channel_prop,
119e7801d59Ssowmini 			do_get_powermode_prop, do_get_radio_prop,
120*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_duplex_get, i_dladm_status_get,
121*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_binary_get, i_dladm_uint32_get,
122*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_flowctl_get;
123*3bc21d0aSAruna Ramakrishna - Sun Microsystems static pd_setf_t	do_set_zone, do_set_rate_prop,
124e7801d59Ssowmini 			do_set_powermode_prop, do_set_radio_prop,
125*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_set_public_prop;
126e7801d59Ssowmini static pd_checkf_t	do_check_zone, do_check_autopush, do_check_rate,
127*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			i_dladm_defmtu_check;
128f4b3ec61Sdh155122 
129*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_status_t	i_dladm_speed_get(struct prop_desc *, datalink_id_t,
1304045d941Ssowmini 			char **, uint_t *, uint_t);
1316b9e797cSsowmini 
132f4b3ec61Sdh155122 typedef struct prop_desc {
133d62bc4baSyz147064 	/*
134d62bc4baSyz147064 	 * link property name
135d62bc4baSyz147064 	 */
136f4b3ec61Sdh155122 	char			*pd_name;
137d62bc4baSyz147064 
138d62bc4baSyz147064 	/*
139d62bc4baSyz147064 	 * default property value, can be set to { "", NULL }
140d62bc4baSyz147064 	 */
141f4b3ec61Sdh155122 	val_desc_t		pd_defval;
142d62bc4baSyz147064 
143d62bc4baSyz147064 	/*
144d62bc4baSyz147064 	 * list of optional property values, can be NULL.
145d62bc4baSyz147064 	 *
146d62bc4baSyz147064 	 * This is set to non-NULL if there is a list of possible property
147d62bc4baSyz147064 	 * values.  pd_optval would point to the array of possible values.
148d62bc4baSyz147064 	 */
149d62bc4baSyz147064 	val_desc_t		*pd_optval;
150d62bc4baSyz147064 
151d62bc4baSyz147064 	/*
152d62bc4baSyz147064 	 * count of the above optional property values. 0 if pd_optval is NULL.
153d62bc4baSyz147064 	 */
154d62bc4baSyz147064 	uint_t			pd_noptval;
155d62bc4baSyz147064 
156d62bc4baSyz147064 	/*
157d62bc4baSyz147064 	 * callback to set link property;
158d62bc4baSyz147064 	 * set to NULL if this property is read-only
159d62bc4baSyz147064 	 */
160f4b3ec61Sdh155122 	pd_setf_t		*pd_set;
161d62bc4baSyz147064 
162d62bc4baSyz147064 	/*
163d62bc4baSyz147064 	 * callback to get modifiable link property
164d62bc4baSyz147064 	 */
165f4b3ec61Sdh155122 	pd_getf_t		*pd_getmod;
166d62bc4baSyz147064 
167d62bc4baSyz147064 	/*
168d62bc4baSyz147064 	 * callback to get current link property
169d62bc4baSyz147064 	 */
170f4b3ec61Sdh155122 	pd_getf_t		*pd_get;
171d62bc4baSyz147064 
172d62bc4baSyz147064 	/*
173d62bc4baSyz147064 	 * callback to validate link property value, set to NULL if pd_optval
174d62bc4baSyz147064 	 * is not NULL. In that case, validate the value by comparing it with
175d62bc4baSyz147064 	 * the pd_optval. Return a val_desc_t array pointer if the value is
176d62bc4baSyz147064 	 * valid.
177d62bc4baSyz147064 	 */
178f4b3ec61Sdh155122 	pd_checkf_t		*pd_check;
179d62bc4baSyz147064 
180d62bc4baSyz147064 	uint_t			pd_flags;
181e7801d59Ssowmini #define	PD_TEMPONLY	0x1	/* property is temporary only */
182e7801d59Ssowmini #define	PD_CHECK_ALLOC	0x2	/* alloc vd_val as part of pd_check */
183d62bc4baSyz147064 	/*
184d62bc4baSyz147064 	 * indicate link classes this property applies to.
185d62bc4baSyz147064 	 */
186d62bc4baSyz147064 	datalink_class_t	pd_class;
187d62bc4baSyz147064 
188d62bc4baSyz147064 	/*
189d62bc4baSyz147064 	 * indicate link media type this property applies to.
190d62bc4baSyz147064 	 */
191d62bc4baSyz147064 	datalink_media_t	pd_dmedia;
192f4b3ec61Sdh155122 } prop_desc_t;
193f4b3ec61Sdh155122 
1943fd94f8cSam223141 #define	MAC_PROP_BUFSIZE(v)	sizeof (dld_ioc_macprop_t) + (v) - 1
195e7801d59Ssowmini 
196e7801d59Ssowmini 
197*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_public_prop_t dladm_prop[] = {
1983fd94f8cSam223141 	{ MAC_PROP_DUPLEX,	sizeof (link_duplex_t),
1996b9e797cSsowmini 	    "duplex",		"link duplex mode" },
200e7801d59Ssowmini 
2013fd94f8cSam223141 	{MAC_PROP_SPEED,	sizeof (uint64_t),
2026b9e797cSsowmini 	    "speed",		"link speed (bps)" },
203e7801d59Ssowmini 
2043fd94f8cSam223141 	{ MAC_PROP_STATUS,	sizeof (link_state_t),
2056b9e797cSsowmini 	    "state",		"link up/down" },
206e7801d59Ssowmini 
2073fd94f8cSam223141 	{ MAC_PROP_AUTONEG,	sizeof (uint8_t),
208e7801d59Ssowmini 	    "adv_autoneg_cap",	"Advertised auto-negotiation" },
209e7801d59Ssowmini 
2103fd94f8cSam223141 	{ MAC_PROP_MTU,		sizeof (uint32_t),
2116b9e797cSsowmini 	    "mtu",		"current link mtu" },
212e7801d59Ssowmini 
2133fd94f8cSam223141 	{ MAC_PROP_FLOWCTRL,	sizeof (link_flowctrl_t),
214e7801d59Ssowmini 	    "flowctrl",		"flowcontrol" },
215e7801d59Ssowmini 
216*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	{ MAC_PROP_ZONE,	sizeof (dld_ioc_zid_t),
217*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    "zone",		"non-global zones" },
218*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
219*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	{ MAC_PROP_AUTOPUSH,	sizeof (struct dlautopush),
220*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    "autopush",		"autopush modules" },
221*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
2223fd94f8cSam223141 	{ MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),
223e7801d59Ssowmini 	    "adv_1000fdx_cap",	"Adv 1000 Mbps fdx" },
224e7801d59Ssowmini 
2253fd94f8cSam223141 	{ MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t),
226e7801d59Ssowmini 	    "en_1000fdx_cap",	"Enable 1000 Mbps fdx" },
227e7801d59Ssowmini 
2283fd94f8cSam223141 	{ MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),
229e7801d59Ssowmini 	    "adv_1000hdx_cap", "Adv 1000 Mbps hdx" },
230e7801d59Ssowmini 
2313fd94f8cSam223141 	{ MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t),
232e7801d59Ssowmini 	    "en_1000hdx_cap",	"Enable 1000 Mbps hdx" },
233e7801d59Ssowmini 
2343fd94f8cSam223141 	{ MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t),
235e7801d59Ssowmini 	    "adv_100fdx_cap",	"Adv 100 Mbps fdx" },
236e7801d59Ssowmini 
2373fd94f8cSam223141 	{ MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t),
238e7801d59Ssowmini 	    "en_100fdx_cap",	"Enable 100 Mbps fdx" },
239e7801d59Ssowmini 
2403fd94f8cSam223141 	{ MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t),
241e7801d59Ssowmini 	    "adv_100hdx_cap",	"Adv 100 Mbps hdx" },
242e7801d59Ssowmini 
2433fd94f8cSam223141 	{ MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t),
244e7801d59Ssowmini 	    "en_100hdx_cap",	"Enable 100 Mbps hdx" },
245e7801d59Ssowmini 
2463fd94f8cSam223141 	{ MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t),
247e7801d59Ssowmini 	    "adv_10fdx_cap",	"Adv 10 Mbps fdx" },
248e7801d59Ssowmini 
2493fd94f8cSam223141 	{ MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t),
250e7801d59Ssowmini 	    "en_10fdx_cap",	"Enable 10 Mbps fdx" },
251e7801d59Ssowmini 
2523fd94f8cSam223141 	{ MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t),
253e7801d59Ssowmini 	    "adv_10hdx_cap",	"Adv 10 Mbps hdx" },
254e7801d59Ssowmini 
2553fd94f8cSam223141 	{ MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t),
256e7801d59Ssowmini 	    "en_10hdx_cap",	"Enable 10 Mbps hdx" },
257e7801d59Ssowmini 
2583fd94f8cSam223141 	{ MAC_PROP_PRIVATE, 0,
259e7801d59Ssowmini 	    "driver-private",	"" }
260e7801d59Ssowmini };
261e7801d59Ssowmini 
262e7801d59Ssowmini static  val_desc_t	link_duplex_vals[] = {
263e7801d59Ssowmini 	{ "half", 	LINK_DUPLEX_HALF	},
264e7801d59Ssowmini 	{ "full", 	LINK_DUPLEX_HALF	}
265e7801d59Ssowmini };
266e7801d59Ssowmini static  val_desc_t	link_status_vals[] = {
267e7801d59Ssowmini 	{ "up",		LINK_STATE_UP		},
268e7801d59Ssowmini 	{ "down",	LINK_STATE_DOWN		}
269e7801d59Ssowmini };
270e7801d59Ssowmini static  val_desc_t	link_01_vals[] = {
271e7801d59Ssowmini 	{ "1",		1			},
272e7801d59Ssowmini 	{ "0",		0			}
273e7801d59Ssowmini };
274e7801d59Ssowmini static  val_desc_t	link_flow_vals[] = {
275e7801d59Ssowmini 	{ "no",		LINK_FLOWCTRL_NONE	},
276e7801d59Ssowmini 	{ "tx",		LINK_FLOWCTRL_TX	},
277e7801d59Ssowmini 	{ "rx",		LINK_FLOWCTRL_RX	},
278e7801d59Ssowmini 	{ "bi",		LINK_FLOWCTRL_BI	}
279e7801d59Ssowmini };
280e7801d59Ssowmini 
281e7801d59Ssowmini #define	VALCNT(vals)    (sizeof ((vals)) / sizeof (val_desc_t))
282e7801d59Ssowmini 
283d62bc4baSyz147064 static val_desc_t	dladm_wlan_radio_vals[] = {
284d62bc4baSyz147064 	{ "on",		DLADM_WLAN_RADIO_ON	},
285d62bc4baSyz147064 	{ "off",	DLADM_WLAN_RADIO_OFF	}
286d62bc4baSyz147064 };
287d62bc4baSyz147064 
288d62bc4baSyz147064 static val_desc_t	dladm_wlan_powermode_vals[] = {
289d62bc4baSyz147064 	{ "off",	DLADM_WLAN_PM_OFF	},
290d62bc4baSyz147064 	{ "fast",	DLADM_WLAN_PM_FAST	},
291d62bc4baSyz147064 	{ "max",	DLADM_WLAN_PM_MAX	}
292d62bc4baSyz147064 };
293d62bc4baSyz147064 
294f4b3ec61Sdh155122 static prop_desc_t	prop_table[] = {
295d62bc4baSyz147064 
296e7801d59Ssowmini 	{ "channel",	{ NULL, 0 },
297e7801d59Ssowmini 	    NULL, 0, NULL, NULL,
298d62bc4baSyz147064 	    do_get_channel_prop, NULL, 0,
299d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
300d62bc4baSyz147064 
301d62bc4baSyz147064 	{ "powermode",	{ "off", DLADM_WLAN_PM_OFF },
302d62bc4baSyz147064 	    dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
303d62bc4baSyz147064 	    do_set_powermode_prop, NULL,
304d62bc4baSyz147064 	    do_get_powermode_prop, NULL, 0,
305d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
306d62bc4baSyz147064 
307d62bc4baSyz147064 	{ "radio",	{ "on", DLADM_WLAN_RADIO_ON },
308d62bc4baSyz147064 	    dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
309d62bc4baSyz147064 	    do_set_radio_prop, NULL,
310d62bc4baSyz147064 	    do_get_radio_prop, NULL, 0,
311d62bc4baSyz147064 	    DATALINK_CLASS_PHYS, DL_WIFI },
312d62bc4baSyz147064 
313d62bc4baSyz147064 	{ "speed",	{ "", 0 }, NULL, 0,
314d62bc4baSyz147064 	    do_set_rate_prop, do_get_rate_mod,
315d62bc4baSyz147064 	    do_get_rate_prop, do_check_rate, 0,
3166b9e797cSsowmini 	    DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE },
317d62bc4baSyz147064 
3184045d941Ssowmini 	{ "autopush",	{ "", 0 }, NULL, 0,
319*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL,
320*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
321d62bc4baSyz147064 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
322d62bc4baSyz147064 
3234045d941Ssowmini 	{ "zone",	{ "", 0 }, NULL, 0,
324f4b3ec61Sdh155122 	    do_set_zone, NULL,
325*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    do_get_zone, do_check_zone, PD_TEMPONLY|PD_CHECK_ALLOC,
326e7801d59Ssowmini 	    DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
327e7801d59Ssowmini 
3284045d941Ssowmini 	{ "duplex", { "", 0 },
329e7801d59Ssowmini 	    link_duplex_vals, VALCNT(link_duplex_vals),
330*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_duplex_get, NULL,
331e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
332e7801d59Ssowmini 
3336b9e797cSsowmini 	{ "state", { "up", LINK_STATE_UP },
334e7801d59Ssowmini 	    link_status_vals, VALCNT(link_status_vals),
335*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_status_get, NULL,
3364045d941Ssowmini 	    0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
337e7801d59Ssowmini 
338e7801d59Ssowmini 	{ "adv_autoneg_cap", { "1", 1 },
339e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
340*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
341e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
342e7801d59Ssowmini 
3434045d941Ssowmini 	{ "mtu", { "", 0 }, NULL, 0,
344*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_uint32_get,
345*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_defmtu_check, 0, DATALINK_CLASS_ALL,
346*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    DATALINK_ANY_MEDIATYPE },
347e7801d59Ssowmini 
3484045d941Ssowmini 	{ "flowctrl", { "", 0 },
349e7801d59Ssowmini 	    link_flow_vals, VALCNT(link_flow_vals),
350*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_flowctl_get, NULL,
351e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
352e7801d59Ssowmini 
3534045d941Ssowmini 	{ "adv_1000fdx_cap", { "", 0 },
3544045d941Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
355*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
356e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
357e7801d59Ssowmini 
3584045d941Ssowmini 	{ "en_1000fdx_cap", { "", 0 },
359e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
360*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
361e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
362e7801d59Ssowmini 
3634045d941Ssowmini 	{ "adv_1000hdx_cap", { "", 0 },
364e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
365*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
366e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
367e7801d59Ssowmini 
3684045d941Ssowmini 	{ "en_1000hdx_cap", { "", 0 },
369e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
370*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
371e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
372e7801d59Ssowmini 
3734045d941Ssowmini 	{ "adv_100fdx_cap", { "", 0 },
374e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
375*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
376e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
377e7801d59Ssowmini 
3784045d941Ssowmini 	{ "en_100fdx_cap", { "", 0 },
379e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
380*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
381e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
382e7801d59Ssowmini 
3834045d941Ssowmini 	{ "adv_100hdx_cap", { "", 0 },
384e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
385*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
386e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
387e7801d59Ssowmini 
3884045d941Ssowmini 	{ "en_100hdx_cap", { "", 0 },
389e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
390*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
391e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
392e7801d59Ssowmini 
3934045d941Ssowmini 	{ "adv_10fdx_cap", { "", 0 },
394e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
395*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
396e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
397e7801d59Ssowmini 
3984045d941Ssowmini 	{ "en_10fdx_cap", { "", 0 },
399e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
400*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
401e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
402e7801d59Ssowmini 
4034045d941Ssowmini 	{ "adv_10hdx_cap", { "", 0 },
404e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
405*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    NULL, NULL, i_dladm_binary_get, NULL,
406e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER },
407e7801d59Ssowmini 
4084045d941Ssowmini 	{ "en_10hdx_cap", { "", 0 },
409e7801d59Ssowmini 	    link_01_vals, VALCNT(link_01_vals),
410*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	    i_dladm_set_public_prop, NULL, i_dladm_binary_get, NULL,
411e7801d59Ssowmini 	    0, DATALINK_CLASS_PHYS, DL_ETHER }
412e7801d59Ssowmini 
413f4b3ec61Sdh155122 };
414f4b3ec61Sdh155122 
415d62bc4baSyz147064 #define	DLADM_MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
4160ba2cbe9Sxc151355 
417d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop_db(datalink_id_t, const char *,
418d62bc4baSyz147064 			    char **, uint_t);
419d62bc4baSyz147064 static dladm_status_t	i_dladm_get_linkprop_db(datalink_id_t, const char *,
420d62bc4baSyz147064 			    char **, uint_t *);
421d62bc4baSyz147064 static dladm_status_t	i_dladm_set_single_prop(datalink_id_t, datalink_class_t,
422d62bc4baSyz147064 			    uint32_t, prop_desc_t *, char **, uint_t, uint_t);
423d62bc4baSyz147064 static dladm_status_t	i_dladm_set_linkprop(datalink_id_t, const char *,
424d62bc4baSyz147064 			    char **, uint_t, uint_t);
4254045d941Ssowmini static dladm_status_t	i_dladm_getset_defval(prop_desc_t *, datalink_id_t,
4264045d941Ssowmini 			    datalink_media_t, uint_t);
427d62bc4baSyz147064 /*
428d62bc4baSyz147064  * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
429d62bc4baSyz147064  * rates to be retrieved. However, we cannot increase it at this
430d62bc4baSyz147064  * time because it will break binary compatibility with unbundled
431d62bc4baSyz147064  * WiFi drivers and utilities. So for now we define an additional
432d62bc4baSyz147064  * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
433d62bc4baSyz147064  */
434d62bc4baSyz147064 #define	MAX_SUPPORT_RATES	64
435d62bc4baSyz147064 
436d62bc4baSyz147064 #define	AP_ANCHOR	"[anchor]"
437d62bc4baSyz147064 #define	AP_DELIMITER	'.'
438d62bc4baSyz147064 
439d62bc4baSyz147064 static dladm_status_t
440d62bc4baSyz147064 do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
441d62bc4baSyz147064     val_desc_t *vdp)
4420ba2cbe9Sxc151355 {
443d62bc4baSyz147064 	int		i, j;
4440ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
4450ba2cbe9Sxc151355 
446d62bc4baSyz147064 	for (j = 0; j < val_cnt; j++) {
447d62bc4baSyz147064 		for (i = 0; i < pdp->pd_noptval; i++) {
448d62bc4baSyz147064 			if (strcasecmp(*prop_val,
449d62bc4baSyz147064 			    pdp->pd_optval[i].vd_name) == 0) {
4500ba2cbe9Sxc151355 				break;
4510ba2cbe9Sxc151355 			}
4520ba2cbe9Sxc151355 		}
453d62bc4baSyz147064 		if (i == pdp->pd_noptval) {
454d62bc4baSyz147064 			status = DLADM_STATUS_BADVAL;
455d62bc4baSyz147064 			goto done;
456d62bc4baSyz147064 		}
457d62bc4baSyz147064 		(void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
4580ba2cbe9Sxc151355 	}
4590ba2cbe9Sxc151355 
460d62bc4baSyz147064 done:
461d62bc4baSyz147064 	return (status);
4620ba2cbe9Sxc151355 }
4630ba2cbe9Sxc151355 
4640ba2cbe9Sxc151355 static dladm_status_t
465d62bc4baSyz147064 i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
466d62bc4baSyz147064     uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
467d62bc4baSyz147064     uint_t flags)
4680ba2cbe9Sxc151355 {
4690ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
470d62bc4baSyz147064 	val_desc_t	*vdp = NULL;
471d62bc4baSyz147064 	boolean_t	needfree = B_FALSE;
472d62bc4baSyz147064 	uint_t		cnt, i;
4730ba2cbe9Sxc151355 
474d62bc4baSyz147064 	if (!(pdp->pd_class & class))
475d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
4760ba2cbe9Sxc151355 
477d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
478d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
479d62bc4baSyz147064 
480d62bc4baSyz147064 	if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
481d62bc4baSyz147064 		return (DLADM_STATUS_TEMPONLY);
482d62bc4baSyz147064 
483d62bc4baSyz147064 	if (!(flags & DLADM_OPT_ACTIVE))
484d62bc4baSyz147064 		return (DLADM_STATUS_OK);
485d62bc4baSyz147064 
486d62bc4baSyz147064 	if (pdp->pd_set == NULL)
487d62bc4baSyz147064 		return (DLADM_STATUS_PROPRDONLY);
488d62bc4baSyz147064 
489e7801d59Ssowmini 	if (pdp->pd_flags & PD_CHECK_ALLOC)
490e7801d59Ssowmini 		needfree = B_TRUE;
491e7801d59Ssowmini 	else
492e7801d59Ssowmini 		needfree = B_FALSE;
493d62bc4baSyz147064 	if (prop_val != NULL) {
494d62bc4baSyz147064 		vdp = malloc(sizeof (val_desc_t) * val_cnt);
495d62bc4baSyz147064 		if (vdp == NULL)
496d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
497d62bc4baSyz147064 
498e7801d59Ssowmini 
499d62bc4baSyz147064 		if (pdp->pd_check != NULL) {
500e7801d59Ssowmini 			status = pdp->pd_check(pdp, linkid, prop_val, val_cnt,
5016b9e797cSsowmini 			    vdp, media);
502d62bc4baSyz147064 		} else if (pdp->pd_optval != NULL) {
503d62bc4baSyz147064 			status = do_check_prop(pdp, prop_val, val_cnt, vdp);
504d62bc4baSyz147064 		} else {
505d62bc4baSyz147064 			status = DLADM_STATUS_BADARG;
5060ba2cbe9Sxc151355 		}
5070ba2cbe9Sxc151355 
508d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
509d62bc4baSyz147064 			goto done;
510d62bc4baSyz147064 
511d62bc4baSyz147064 		cnt = val_cnt;
512d62bc4baSyz147064 	} else {
513d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL)
514d62bc4baSyz147064 			return (DLADM_STATUS_NOTSUP);
515d62bc4baSyz147064 
516*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		cnt = 1;
517*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if ((pdp->pd_flags & PD_CHECK_ALLOC) != 0 ||
5184045d941Ssowmini 		    strlen(pdp->pd_defval.vd_name) > 0) {
519d62bc4baSyz147064 			if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
520d62bc4baSyz147064 				return (DLADM_STATUS_NOMEM);
521*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
522*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			if (pdp->pd_check != NULL) {
523*3bc21d0aSAruna Ramakrishna - Sun Microsystems 				status = pdp->pd_check(pdp, linkid, prop_val,
524*3bc21d0aSAruna Ramakrishna - Sun Microsystems 				    cnt, vdp, media);
525*3bc21d0aSAruna Ramakrishna - Sun Microsystems 				if (status != DLADM_STATUS_OK)
526*3bc21d0aSAruna Ramakrishna - Sun Microsystems 					goto done;
527*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			} else {
5284045d941Ssowmini 				(void) memcpy(vdp, &pdp->pd_defval,
5294045d941Ssowmini 				    sizeof (val_desc_t));
530*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
5314045d941Ssowmini 		} else {
5324045d941Ssowmini 			status = i_dladm_getset_defval(pdp, linkid,
5334045d941Ssowmini 			    media, flags);
5344045d941Ssowmini 			return (status);
5354045d941Ssowmini 		}
536d62bc4baSyz147064 	}
5376b9e797cSsowmini 	status = pdp->pd_set(pdp, linkid, vdp, cnt, flags, media);
538d62bc4baSyz147064 	if (needfree) {
539d62bc4baSyz147064 		for (i = 0; i < cnt; i++)
540e7801d59Ssowmini 			free((void *)((val_desc_t *)vdp + i)->vd_val);
541d62bc4baSyz147064 	}
542d62bc4baSyz147064 done:
543d62bc4baSyz147064 	free(vdp);
544d62bc4baSyz147064 	return (status);
545d62bc4baSyz147064 }
546d62bc4baSyz147064 
547d62bc4baSyz147064 static dladm_status_t
548d62bc4baSyz147064 i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name,
549d62bc4baSyz147064     char **prop_val, uint_t val_cnt, uint_t flags)
550d62bc4baSyz147064 {
551d62bc4baSyz147064 	int			i;
552d62bc4baSyz147064 	boolean_t		found = B_FALSE;
553d62bc4baSyz147064 	datalink_class_t	class;
554d62bc4baSyz147064 	uint32_t		media;
555d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
556d62bc4baSyz147064 
557d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
558d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
5590ba2cbe9Sxc151355 		return (status);
5600ba2cbe9Sxc151355 
561d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
562d62bc4baSyz147064 		prop_desc_t	*pdp = &prop_table[i];
563d62bc4baSyz147064 		dladm_status_t	s;
5640ba2cbe9Sxc151355 
565d62bc4baSyz147064 		if (prop_name != NULL &&
566d62bc4baSyz147064 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
567d62bc4baSyz147064 			continue;
568d62bc4baSyz147064 
569d62bc4baSyz147064 		found = B_TRUE;
570d62bc4baSyz147064 		s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val,
571d62bc4baSyz147064 		    val_cnt, flags);
572d62bc4baSyz147064 
573d62bc4baSyz147064 		if (prop_name != NULL) {
574d62bc4baSyz147064 			status = s;
575d62bc4baSyz147064 			break;
576d62bc4baSyz147064 		} else {
577d62bc4baSyz147064 			if (s != DLADM_STATUS_OK &&
578d62bc4baSyz147064 			    s != DLADM_STATUS_NOTSUP)
579d62bc4baSyz147064 				status = s;
580d62bc4baSyz147064 		}
581d62bc4baSyz147064 	}
582e7801d59Ssowmini 	if (!found) {
583e7801d59Ssowmini 		if (prop_name[0] == '_') {
584e7801d59Ssowmini 			/* other private properties */
585*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = i_dladm_set_prop(linkid, prop_name, prop_val,
586e7801d59Ssowmini 			    val_cnt, flags);
587e7801d59Ssowmini 		} else  {
5880ba2cbe9Sxc151355 			status = DLADM_STATUS_NOTFOUND;
589e7801d59Ssowmini 		}
590e7801d59Ssowmini 	}
5910ba2cbe9Sxc151355 
5920ba2cbe9Sxc151355 	return (status);
5930ba2cbe9Sxc151355 }
5940ba2cbe9Sxc151355 
595d62bc4baSyz147064 /*
596d62bc4baSyz147064  * Set/reset link property for specific link
597d62bc4baSyz147064  */
598d62bc4baSyz147064 dladm_status_t
599d62bc4baSyz147064 dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val,
600d62bc4baSyz147064     uint_t val_cnt, uint_t flags)
6010ba2cbe9Sxc151355 {
602d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
6030ba2cbe9Sxc151355 
604d62bc4baSyz147064 	if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
605d62bc4baSyz147064 	    (prop_val == NULL && val_cnt > 0) ||
606d62bc4baSyz147064 	    (prop_val != NULL && val_cnt == 0) ||
607d62bc4baSyz147064 	    (prop_name == NULL && prop_val != NULL)) {
608d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
6090ba2cbe9Sxc151355 	}
6100ba2cbe9Sxc151355 
611d62bc4baSyz147064 	status = i_dladm_set_linkprop(linkid, prop_name, prop_val,
612d62bc4baSyz147064 	    val_cnt, flags);
613d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
614d62bc4baSyz147064 		return (status);
615d62bc4baSyz147064 
616d62bc4baSyz147064 	if (flags & DLADM_OPT_PERSIST) {
617d62bc4baSyz147064 		status = i_dladm_set_linkprop_db(linkid, prop_name,
618d62bc4baSyz147064 		    prop_val, val_cnt);
619d62bc4baSyz147064 	}
620d62bc4baSyz147064 	return (status);
621d62bc4baSyz147064 }
622d62bc4baSyz147064 
623d62bc4baSyz147064 /*
624d62bc4baSyz147064  * Walk link properties of the given specific link.
625d62bc4baSyz147064  */
626d62bc4baSyz147064 dladm_status_t
627d62bc4baSyz147064 dladm_walk_linkprop(datalink_id_t linkid, void *arg,
628d62bc4baSyz147064     int (*func)(datalink_id_t, const char *, void *))
6290ba2cbe9Sxc151355 {
630d62bc4baSyz147064 	dladm_status_t		status;
631d62bc4baSyz147064 	datalink_class_t	class;
632d62bc4baSyz147064 	uint_t			media;
633d62bc4baSyz147064 	int			i;
6340ba2cbe9Sxc151355 
635d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || func == NULL)
636d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
6370ba2cbe9Sxc151355 
638d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
639d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
640d62bc4baSyz147064 		return (status);
641d62bc4baSyz147064 
642d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++) {
643d62bc4baSyz147064 		if (!(prop_table[i].pd_class & class))
644d62bc4baSyz147064 			continue;
645d62bc4baSyz147064 
646d62bc4baSyz147064 		if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
647d62bc4baSyz147064 			continue;
648d62bc4baSyz147064 
649d62bc4baSyz147064 		if (func(linkid, prop_table[i].pd_name, arg) ==
650d62bc4baSyz147064 		    DLADM_WALK_TERMINATE) {
651d62bc4baSyz147064 			break;
652d62bc4baSyz147064 		}
653d62bc4baSyz147064 	}
654d62bc4baSyz147064 
655d62bc4baSyz147064 	return (DLADM_STATUS_OK);
656d62bc4baSyz147064 }
657d62bc4baSyz147064 
658d62bc4baSyz147064 /*
659d62bc4baSyz147064  * Get linkprop of the given specific link.
660d62bc4baSyz147064  */
661d62bc4baSyz147064 dladm_status_t
662d62bc4baSyz147064 dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
663d62bc4baSyz147064     const char *prop_name, char **prop_val, uint_t *val_cntp)
664d62bc4baSyz147064 {
665d62bc4baSyz147064 	dladm_status_t		status = DLADM_STATUS_OK;
666d62bc4baSyz147064 	datalink_class_t	class;
667d62bc4baSyz147064 	uint_t			media;
668d62bc4baSyz147064 	prop_desc_t		*pdp;
6694045d941Ssowmini 	uint_t			cnt, dld_flags = 0;
670d62bc4baSyz147064 	int			i;
671d62bc4baSyz147064 
6724045d941Ssowmini 	if (type == DLADM_PROP_VAL_DEFAULT)
6733fd94f8cSam223141 		dld_flags = MAC_PROP_DEFAULT;
6744045d941Ssowmini 
675d62bc4baSyz147064 	if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
676d62bc4baSyz147064 	    prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
677d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
678d62bc4baSyz147064 
679d62bc4baSyz147064 	for (i = 0; i < DLADM_MAX_PROPS; i++)
680d62bc4baSyz147064 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
681d62bc4baSyz147064 			break;
682d62bc4baSyz147064 
683e7801d59Ssowmini 	if (i == DLADM_MAX_PROPS) {
684e7801d59Ssowmini 		if (prop_name[0] == '_') {
685e7801d59Ssowmini 			/*
686e7801d59Ssowmini 			 * private property.
687e7801d59Ssowmini 			 */
688*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			return (i_dladm_get_prop(linkid, prop_name,
6894045d941Ssowmini 			    prop_val, val_cntp, type, dld_flags));
690e7801d59Ssowmini 		} else {
691d62bc4baSyz147064 			return (DLADM_STATUS_NOTFOUND);
692e7801d59Ssowmini 		}
693e7801d59Ssowmini 	}
694d62bc4baSyz147064 
695d62bc4baSyz147064 	pdp = &prop_table[i];
696d62bc4baSyz147064 
697d62bc4baSyz147064 	status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
698d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
699d62bc4baSyz147064 		return (status);
700d62bc4baSyz147064 
701d62bc4baSyz147064 	if (!(pdp->pd_class & class))
702d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
703d62bc4baSyz147064 
704d62bc4baSyz147064 	if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
705d62bc4baSyz147064 		return (DLADM_STATUS_BADARG);
706d62bc4baSyz147064 
707d62bc4baSyz147064 	switch (type) {
708d62bc4baSyz147064 	case DLADM_PROP_VAL_CURRENT:
7094045d941Ssowmini 		status = pdp->pd_get(pdp, linkid, prop_val, val_cntp, media,
7104045d941Ssowmini 		    dld_flags);
711d62bc4baSyz147064 		break;
712d62bc4baSyz147064 
713d62bc4baSyz147064 	case DLADM_PROP_VAL_DEFAULT:
71413a55820Sar224390 		/*
71513a55820Sar224390 		 * If defaults are not defined for the property,
71613a55820Sar224390 		 * pd_defval.vd_name should be null. If the driver
71713a55820Sar224390 		 * has to be contacted for the value, vd_name should
71813a55820Sar224390 		 * be the empty string (""). Otherwise, dladm will
71913a55820Sar224390 		 * just print whatever is in the table.
72013a55820Sar224390 		 */
721d62bc4baSyz147064 		if (pdp->pd_defval.vd_name == NULL) {
722d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
723d62bc4baSyz147064 			break;
724d62bc4baSyz147064 		}
7254045d941Ssowmini 
7264045d941Ssowmini 		if (strlen(pdp->pd_defval.vd_name) == 0) {
7274045d941Ssowmini 			status = pdp->pd_get(pdp, linkid, prop_val, val_cntp,
7284045d941Ssowmini 			    media, dld_flags);
7294045d941Ssowmini 		} else {
730d62bc4baSyz147064 			(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
7314045d941Ssowmini 		}
732d62bc4baSyz147064 		*val_cntp = 1;
733d62bc4baSyz147064 		break;
734d62bc4baSyz147064 
735d62bc4baSyz147064 	case DLADM_PROP_VAL_MODIFIABLE:
736d62bc4baSyz147064 		if (pdp->pd_getmod != NULL) {
737e7801d59Ssowmini 			status = pdp->pd_getmod(pdp, linkid, prop_val,
7384045d941Ssowmini 			    val_cntp, media, dld_flags);
739d62bc4baSyz147064 			break;
740d62bc4baSyz147064 		}
741d62bc4baSyz147064 		cnt = pdp->pd_noptval;
742d62bc4baSyz147064 		if (cnt == 0) {
743d62bc4baSyz147064 			status = DLADM_STATUS_NOTSUP;
744d62bc4baSyz147064 		} else if (cnt > *val_cntp) {
745d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
746d62bc4baSyz147064 		} else {
747d62bc4baSyz147064 			for (i = 0; i < cnt; i++) {
748d62bc4baSyz147064 				(void) strcpy(prop_val[i],
749d62bc4baSyz147064 				    pdp->pd_optval[i].vd_name);
750d62bc4baSyz147064 			}
751d62bc4baSyz147064 			*val_cntp = cnt;
752d62bc4baSyz147064 		}
753d62bc4baSyz147064 		break;
754d62bc4baSyz147064 	case DLADM_PROP_VAL_PERSISTENT:
755d62bc4baSyz147064 		if (pdp->pd_flags & PD_TEMPONLY)
756d62bc4baSyz147064 			return (DLADM_STATUS_TEMPONLY);
757d62bc4baSyz147064 		status = i_dladm_get_linkprop_db(linkid, prop_name,
758d62bc4baSyz147064 		    prop_val, val_cntp);
759d62bc4baSyz147064 		break;
760d62bc4baSyz147064 	default:
761d62bc4baSyz147064 		status = DLADM_STATUS_BADARG;
762d62bc4baSyz147064 		break;
763d62bc4baSyz147064 	}
764d62bc4baSyz147064 
765d62bc4baSyz147064 	return (status);
766d62bc4baSyz147064 }
767d62bc4baSyz147064 
768d62bc4baSyz147064 /*ARGSUSED*/
769d62bc4baSyz147064 static int
770d62bc4baSyz147064 i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg)
771d62bc4baSyz147064 {
772d62bc4baSyz147064 	char	*buf, **propvals;
773d62bc4baSyz147064 	uint_t	i, valcnt = DLADM_MAX_PROP_VALCNT;
774d62bc4baSyz147064 
775d62bc4baSyz147064 	if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
776d62bc4baSyz147064 	    DLADM_MAX_PROP_VALCNT)) == NULL) {
777d62bc4baSyz147064 		return (DLADM_WALK_CONTINUE);
778d62bc4baSyz147064 	}
779d62bc4baSyz147064 
780d62bc4baSyz147064 	propvals = (char **)(void *)buf;
781d62bc4baSyz147064 	for (i = 0; i < valcnt; i++) {
782d62bc4baSyz147064 		propvals[i] = buf +
783d62bc4baSyz147064 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
784d62bc4baSyz147064 		    i * DLADM_PROP_VAL_MAX;
785d62bc4baSyz147064 	}
786d62bc4baSyz147064 
787d62bc4baSyz147064 	if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name,
788d62bc4baSyz147064 	    propvals, &valcnt) != DLADM_STATUS_OK) {
789d62bc4baSyz147064 		goto done;
790d62bc4baSyz147064 	}
791d62bc4baSyz147064 
792d62bc4baSyz147064 	(void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt,
793d62bc4baSyz147064 	    DLADM_OPT_ACTIVE);
794d62bc4baSyz147064 
795d62bc4baSyz147064 done:
796d62bc4baSyz147064 	if (buf != NULL)
797d62bc4baSyz147064 		free(buf);
798d62bc4baSyz147064 
799d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
800d62bc4baSyz147064 }
801d62bc4baSyz147064 
802d62bc4baSyz147064 /*ARGSUSED*/
803d62bc4baSyz147064 static int
804d62bc4baSyz147064 i_dladm_init_linkprop(datalink_id_t linkid, void *arg)
805d62bc4baSyz147064 {
80630890389Sartem 	(void) dladm_init_linkprop(linkid, B_TRUE);
807d62bc4baSyz147064 	return (DLADM_WALK_CONTINUE);
8080ba2cbe9Sxc151355 }
8090ba2cbe9Sxc151355 
8100ba2cbe9Sxc151355 dladm_status_t
81130890389Sartem dladm_init_linkprop(datalink_id_t linkid, boolean_t any_media)
8120ba2cbe9Sxc151355 {
81330890389Sartem 	datalink_media_t	dmedia;
81430890389Sartem 	uint32_t		media;
81530890389Sartem 
81630890389Sartem 	dmedia = any_media ? DATALINK_ANY_MEDIATYPE : DL_WIFI;
81730890389Sartem 
818d62bc4baSyz147064 	if (linkid == DATALINK_ALL_LINKID) {
819d62bc4baSyz147064 		(void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL,
82030890389Sartem 		    DATALINK_CLASS_ALL, dmedia, DLADM_OPT_PERSIST);
82130890389Sartem 	} else if (any_media || ((dladm_datalink_id2info(linkid, NULL, NULL,
82230890389Sartem 	    &media, NULL, 0) == DLADM_STATUS_OK) &&
82330890389Sartem 	    DATALINK_MEDIA_ACCEPTED(dmedia, media))) {
824d62bc4baSyz147064 		(void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop);
825d62bc4baSyz147064 	}
826d62bc4baSyz147064 	return (DLADM_STATUS_OK);
8270ba2cbe9Sxc151355 }
828f4b3ec61Sdh155122 
829e7801d59Ssowmini /* ARGSUSED */
830f4b3ec61Sdh155122 static dladm_status_t
831e7801d59Ssowmini do_get_zone(struct prop_desc *pd, datalink_id_t linkid,
8324045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
833f4b3ec61Sdh155122 {
834d62bc4baSyz147064 	char		zone_name[ZONENAME_MAX];
835d62bc4baSyz147064 	zoneid_t	zid;
836d62bc4baSyz147064 	dladm_status_t	status;
837*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
838*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
839f4b3ec61Sdh155122 
8404045d941Ssowmini 	if (flags != 0)
8414045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
8424045d941Ssowmini 
843*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
844d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
845d62bc4baSyz147064 		return (status);
846d62bc4baSyz147064 
847*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	cp = dip->pr_val;
848*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&zid, cp, sizeof (zid));
849*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
850*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
851d62bc4baSyz147064 	*val_cnt = 1;
852d62bc4baSyz147064 	if (zid != GLOBAL_ZONEID) {
853d62bc4baSyz147064 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
854f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
855f4b3ec61Sdh155122 
856d62bc4baSyz147064 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
85747a01978Sbw 	} else {
858d62bc4baSyz147064 		*prop_val[0] = '\0';
85947a01978Sbw 	}
860f4b3ec61Sdh155122 
861f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
862f4b3ec61Sdh155122 }
863f4b3ec61Sdh155122 
864f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
865f4b3ec61Sdh155122 
866f4b3ec61Sdh155122 static int
867f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
868f4b3ec61Sdh155122 {
869f4b3ec61Sdh155122 	char			root[MAXPATHLEN];
870f4b3ec61Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
871f4b3ec61Sdh155122 	void			*dlhandle;
872f4b3ec61Sdh155122 	void			*sym;
873f4b3ec61Sdh155122 	int			ret;
874f4b3ec61Sdh155122 
875f4b3ec61Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
876f4b3ec61Sdh155122 		return (-1);
877f4b3ec61Sdh155122 
878f4b3ec61Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
879f4b3ec61Sdh155122 		(void) dlclose(dlhandle);
880f4b3ec61Sdh155122 		return (-1);
881f4b3ec61Sdh155122 	}
882f4b3ec61Sdh155122 
883f4b3ec61Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
884f4b3ec61Sdh155122 
885f4b3ec61Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
886f4b3ec61Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
887f4b3ec61Sdh155122 	(void) dlclose(dlhandle);
888f4b3ec61Sdh155122 	return (ret);
889f4b3ec61Sdh155122 }
890f4b3ec61Sdh155122 
891f4b3ec61Sdh155122 static dladm_status_t
892d62bc4baSyz147064 i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add)
893f4b3ec61Sdh155122 {
894f4b3ec61Sdh155122 	char		path[MAXPATHLEN];
895d62bc4baSyz147064 	char		name[MAXLINKNAMELEN];
896f4b3ec61Sdh155122 	di_prof_t	prof = NULL;
897f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
898f4b3ec61Sdh155122 	dladm_status_t	status;
899d62bc4baSyz147064 	int		ret;
900f4b3ec61Sdh155122 
901f4b3ec61Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
902f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
903f4b3ec61Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
904f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
905f4b3ec61Sdh155122 	if (di_prof_init(path, &prof) != 0)
906f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
907f4b3ec61Sdh155122 
908d62bc4baSyz147064 	status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN);
909f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
910d62bc4baSyz147064 		goto cleanup;
911f4b3ec61Sdh155122 
912d62bc4baSyz147064 	if (add)
913d62bc4baSyz147064 		ret = di_prof_add_dev(prof, name);
914d62bc4baSyz147064 	else
915d62bc4baSyz147064 		ret = di_prof_add_exclude(prof, name);
916f4b3ec61Sdh155122 
917d62bc4baSyz147064 	if (ret != 0) {
918d62bc4baSyz147064 		status = dladm_errno2status(errno);
919d62bc4baSyz147064 		goto cleanup;
920f4b3ec61Sdh155122 	}
921f4b3ec61Sdh155122 
922d62bc4baSyz147064 	if (di_prof_commit(prof) != 0)
923d62bc4baSyz147064 		status = dladm_errno2status(errno);
924d62bc4baSyz147064 cleanup:
925d62bc4baSyz147064 	if (prof)
926d62bc4baSyz147064 		di_prof_fini(prof);
927d62bc4baSyz147064 
928d62bc4baSyz147064 	return (status);
929f4b3ec61Sdh155122 }
930f4b3ec61Sdh155122 
931e7801d59Ssowmini /* ARGSUSED */
932f4b3ec61Sdh155122 static dladm_status_t
9336b9e797cSsowmini do_set_zone(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp,
9346b9e797cSsowmini     uint_t val_cnt, uint_t flags, datalink_media_t media)
935f4b3ec61Sdh155122 {
936*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status = DLADM_STATUS_OK;
937f4b3ec61Sdh155122 	zoneid_t	zid_old, zid_new;
938d62bc4baSyz147064 	char		link[MAXLINKNAMELEN];
939*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
940*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
941*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t		*dzp;
942f4b3ec61Sdh155122 
943f4b3ec61Sdh155122 	if (val_cnt != 1)
944f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
945f4b3ec61Sdh155122 
946*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = (dld_ioc_zid_t *)vdp->vd_val;
947*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
948*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	/*
949*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * If diz_is_ppa_hack is set, then an implicit vlan must be created.
950*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * There is no old value to compare against, and vdp->vd_val is
951*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * already populated with the zoneid and linkname in the function
952*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * do_check_zone().
953*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 */
954*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
955*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dzp->diz_is_ppa_hack) {
956*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		zid_old = GLOBAL_ZONEID;
957*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
958*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		dip = i_dladm_get_public_prop(linkid, pd->pd_name,
959*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, &status);
960f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
961f4b3ec61Sdh155122 			return (status);
962f4b3ec61Sdh155122 
963*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		cp = dip->pr_val;
964*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		(void) memcpy(&zid_old, cp, sizeof (zid_old));
965*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		free(dip);
966d62bc4baSyz147064 	}
967f4b3ec61Sdh155122 
968*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	zid_new = dzp->diz_zid;
969*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(link, dzp->diz_link, MAXLINKNAMELEN);
970*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
971*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	/* Do nothing if setting to current value */
972*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new == zid_old)
973*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (status);
974*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
975d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
976d62bc4baSyz147064 		/*
977d62bc4baSyz147064 		 * If the new zoneid is the global zone, we could destroy
978d62bc4baSyz147064 		 * the link (in the case of an implicitly-created VLAN) as a
979*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * result of setting the zoneid. In that case, we defer the
980*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * operation to the end of this function to avoid recreating
981*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * the VLAN and getting a different linkid during the rollback
982*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * if other operation fails.
983d62bc4baSyz147064 		 *
984*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * Otherwise, this operation will hold a reference to the
985d62bc4baSyz147064 		 * link and prevent a link renaming, so we need to do it
986d62bc4baSyz147064 		 * before other operations.
987d62bc4baSyz147064 		 */
988*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
989*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
990d62bc4baSyz147064 		if (status != DLADM_STATUS_OK)
991d62bc4baSyz147064 			return (status);
992d62bc4baSyz147064 	}
993d62bc4baSyz147064 
994d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID) {
995d62bc4baSyz147064 		if (zone_remove_datalink(zid_old, link) != 0 &&
996f4b3ec61Sdh155122 		    errno != ENXIO) {
997f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
998f4b3ec61Sdh155122 			goto rollback1;
999f4b3ec61Sdh155122 		}
1000f4b3ec61Sdh155122 
1001d62bc4baSyz147064 		/*
1002d62bc4baSyz147064 		 * It is okay to fail to update the /dev entry (some
1003d62bc4baSyz147064 		 * vanity-named links do not have a /dev entry).
1004d62bc4baSyz147064 		 */
1005d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_FALSE);
1006d62bc4baSyz147064 	}
1007d62bc4baSyz147064 
1008d62bc4baSyz147064 	if (zid_new != GLOBAL_ZONEID) {
1009d62bc4baSyz147064 		if (zone_add_datalink(zid_new, link) != 0) {
1010d62bc4baSyz147064 			status = dladm_errno2status(errno);
1011d62bc4baSyz147064 			goto rollback2;
1012d62bc4baSyz147064 		}
1013d62bc4baSyz147064 
1014*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (dzp->diz_is_ppa_hack) {
1015*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			if ((status = dladm_name2info(link, &linkid, NULL, NULL,
1016*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			    NULL)) != DLADM_STATUS_OK) {
1017*3bc21d0aSAruna Ramakrishna - Sun Microsystems 				return (status);
1018*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
1019*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
1020*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1021d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_new, linkid, B_TRUE);
1022d62bc4baSyz147064 	} else {
1023*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
1024*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1025f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
1026f4b3ec61Sdh155122 			goto rollback2;
1027f4b3ec61Sdh155122 	}
1028f4b3ec61Sdh155122 
1029f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1030f4b3ec61Sdh155122 
1031f4b3ec61Sdh155122 rollback2:
1032f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID)
1033d62bc4baSyz147064 		(void) i_dladm_update_deventry(zid_old, linkid, B_TRUE);
1034d62bc4baSyz147064 	if (zid_old != GLOBAL_ZONEID)
1035d62bc4baSyz147064 		(void) zone_add_datalink(zid_old, link);
1036f4b3ec61Sdh155122 rollback1:
1037*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zid_new != GLOBAL_ZONEID) {
1038*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		dzp->diz_zid = zid_old;
1039*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		(void) i_dladm_set_public_prop(pd, linkid, vdp, val_cnt,
1040*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    flags, media);
1041*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1042*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1043f4b3ec61Sdh155122 	return (status);
1044f4b3ec61Sdh155122 }
1045f4b3ec61Sdh155122 
1046f4b3ec61Sdh155122 /* ARGSUSED */
1047f4b3ec61Sdh155122 static dladm_status_t
1048e7801d59Ssowmini do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
10496b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1050f4b3ec61Sdh155122 {
1051*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*zone_name;
1052*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		linkname[MAXLINKNAMELEN];
1053*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	zoneid_t	zoneid;
1054*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	char		*cp;
1055*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status = DLADM_STATUS_OK;
1056*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	boolean_t	is_ppa_hack = B_FALSE;
1057*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_zid_t	*dzp;
1058f4b3ec61Sdh155122 
1059f4b3ec61Sdh155122 	if (val_cnt != 1)
1060f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
1061f4b3ec61Sdh155122 
1062*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp = malloc(sizeof (dld_ioc_zid_t));
1063*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dzp == NULL)
1064*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (DLADM_STATUS_NOMEM);
1065f4b3ec61Sdh155122 
1066*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (prop_val) {
1067*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		/*
1068*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * The prop_val contains zone_name{:linkname}. The linkname is
1069*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 * present only when the link is a ppa-hacked vlan.
1070*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		 */
1071*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		cp = strchr(*prop_val, ':');
1072*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (cp) {
1073*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			(void) strlcpy(linkname, cp + 1, MAXLINKNAMELEN);
1074*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			*cp = '\0';
1075*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			is_ppa_hack = B_TRUE;
1076*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		} else {
1077*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = dladm_datalink_id2info(linkid, NULL, NULL,
1078*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			    NULL, linkname, MAXLINKNAMELEN);
1079*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			if (status != DLADM_STATUS_OK) {
1080*3bc21d0aSAruna Ramakrishna - Sun Microsystems 				goto done;
1081*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			}
1082*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
1083*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		zone_name = *prop_val;
1084*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
1085*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		zone_name = GLOBAL_ZONENAME;
1086*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL,
1087*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    linkname, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
1088*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1089*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		}
1090*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1091*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1092*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (strlen(linkname) > MAXLINKNAMELEN) {
1093*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
1094*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
1095*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1096*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1097*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if ((zoneid = getzoneidbyname(zone_name)) == -1) {
1098*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		status = DLADM_STATUS_BADVAL;
1099*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		goto done;
1100*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1101*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1102*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (zoneid != GLOBAL_ZONEID) {
1103f4b3ec61Sdh155122 		ushort_t	flags;
1104f4b3ec61Sdh155122 
1105*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
1106f4b3ec61Sdh155122 		    sizeof (flags)) < 0) {
1107*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = dladm_errno2status(errno);
1108*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1109f4b3ec61Sdh155122 		}
1110f4b3ec61Sdh155122 
1111f4b3ec61Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
1112*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			status = DLADM_STATUS_BADVAL;
1113*3bc21d0aSAruna Ramakrishna - Sun Microsystems 			goto done;
1114f4b3ec61Sdh155122 		}
1115f4b3ec61Sdh155122 	}
1116f4b3ec61Sdh155122 
1117*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memset(dzp, 0, sizeof (dld_ioc_zid_t));
1118*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1119*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp->diz_zid = zoneid;
1120*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) strlcpy(dzp->diz_link, linkname, MAXLINKNAMELEN);
1121*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dzp->diz_is_ppa_hack = is_ppa_hack;
1122*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
1123*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	vdp->vd_val = (uintptr_t)dzp;
1124f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1125*3bc21d0aSAruna Ramakrishna - Sun Microsystems done:
1126*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dzp);
1127*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	return (status);
1128f4b3ec61Sdh155122 }
1129f4b3ec61Sdh155122 
1130e7801d59Ssowmini /* ARGSUSED */
1131f4b3ec61Sdh155122 static dladm_status_t
1132e7801d59Ssowmini do_get_autopush(struct prop_desc *pd, datalink_id_t linkid,
11334045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1134d62bc4baSyz147064 {
1135*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	struct		dlautopush dlap;
1136*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	int		i, len;
1137*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_status_t	status;
1138*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dld_ioc_macprop_t	*dip;
1139d62bc4baSyz147064 
11403fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
11414045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
11424045d941Ssowmini 
1143d62bc4baSyz147064 	*val_cnt = 1;
1144*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
1145*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (dip == NULL) {
1146d62bc4baSyz147064 		(*prop_val)[0] = '\0';
1147d62bc4baSyz147064 		goto done;
1148d62bc4baSyz147064 	}
1149*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	(void) memcpy(&dlap, dip->pr_val, sizeof (dlap));
1150d62bc4baSyz147064 
1151*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	for (i = 0, len = 0; i < dlap.dap_npush; i++) {
1152d62bc4baSyz147064 		if (i != 0) {
1153d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1154d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
1155d62bc4baSyz147064 			len += 1;
1156d62bc4baSyz147064 		}
1157d62bc4baSyz147064 		(void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
1158*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    "%s", dlap.dap_aplist[i]);
1159*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		len += strlen(dlap.dap_aplist[i]);
1160*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		if (dlap.dap_anchor - 1 == i) {
1161d62bc4baSyz147064 			(void) snprintf(*prop_val + len,
1162d62bc4baSyz147064 			    DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
1163d62bc4baSyz147064 			    AP_ANCHOR);
1164d62bc4baSyz147064 			len += (strlen(AP_ANCHOR) + 1);
1165d62bc4baSyz147064 		}
1166d62bc4baSyz147064 	}
1167d62bc4baSyz147064 
1168*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	free(dip);
1169d62bc4baSyz147064 done:
1170d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1171d62bc4baSyz147064 }
1172d62bc4baSyz147064 
1173d62bc4baSyz147064 /*
1174d62bc4baSyz147064  * Add the specified module to the dlautopush structure; returns a
1175d62bc4baSyz147064  * DLADM_STATUS_* code.
1176d62bc4baSyz147064  */
1177d62bc4baSyz147064 dladm_status_t
1178d62bc4baSyz147064 i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
1179d62bc4baSyz147064 {
1180d62bc4baSyz147064 	if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
1181d62bc4baSyz147064 		return (DLADM_STATUS_BADVAL);
1182d62bc4baSyz147064 
1183d62bc4baSyz147064 	if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
1184d62bc4baSyz147064 		/*
1185d62bc4baSyz147064 		 * We don't allow multiple anchors, and the anchor must
1186d62bc4baSyz147064 		 * be after at least one module.
1187d62bc4baSyz147064 		 */
1188d62bc4baSyz147064 		if (dlap->dap_anchor != 0)
1189d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1190d62bc4baSyz147064 		if (dlap->dap_npush == 0)
1191d62bc4baSyz147064 			return (DLADM_STATUS_BADVAL);
1192d62bc4baSyz147064 
1193d62bc4baSyz147064 		dlap->dap_anchor = dlap->dap_npush;
1194d62bc4baSyz147064 		return (DLADM_STATUS_OK);
1195d62bc4baSyz147064 	}
1196d62bc4baSyz147064 	if (dlap->dap_npush > MAXAPUSH)
1197d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1198d62bc4baSyz147064 
1199d62bc4baSyz147064 	(void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
1200d62bc4baSyz147064 	    FMNAMESZ + 1);
1201d62bc4baSyz147064 
1202d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1203d62bc4baSyz147064 }
1204d62bc4baSyz147064 
1205d62bc4baSyz147064 /*
1206d62bc4baSyz147064  * Currently, both '.' and ' '(space) can be used as the delimiters between
1207d62bc4baSyz147064  * autopush modules. The former is used in dladm set-linkprop, and the
1208d62bc4baSyz147064  * latter is used in the autopush(1M) file.
1209d62bc4baSyz147064  */
1210d62bc4baSyz147064 /* ARGSUSED */
1211d62bc4baSyz147064 static dladm_status_t
1212e7801d59Ssowmini do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
12136b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1214d62bc4baSyz147064 {
1215d62bc4baSyz147064 	char			*module;
1216d62bc4baSyz147064 	struct dlautopush	*dlap;
1217d62bc4baSyz147064 	dladm_status_t		status;
1218d62bc4baSyz147064 	char			val[DLADM_PROP_VAL_MAX];
1219d62bc4baSyz147064 	char			delimiters[4];
1220d62bc4baSyz147064 
1221d62bc4baSyz147064 	if (val_cnt != 1)
1222d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1223d62bc4baSyz147064 
1224*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (prop_val != NULL) {
1225d62bc4baSyz147064 		dlap = malloc(sizeof (struct dlautopush));
1226d62bc4baSyz147064 		if (dlap == NULL)
1227d62bc4baSyz147064 			return (DLADM_STATUS_NOMEM);
1228d62bc4baSyz147064 
1229d62bc4baSyz147064 		(void) memset(dlap, 0, sizeof (struct dlautopush));
1230d62bc4baSyz147064 		(void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
1231d62bc4baSyz147064 		bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
1232d62bc4baSyz147064 		module = strtok(val, delimiters);
1233d62bc4baSyz147064 		while (module != NULL) {
1234d62bc4baSyz147064 			status = i_dladm_add_ap_module(module, dlap);
1235d62bc4baSyz147064 			if (status != DLADM_STATUS_OK)
1236d62bc4baSyz147064 				return (status);
1237d62bc4baSyz147064 			module = strtok(NULL, delimiters);
1238d62bc4baSyz147064 		}
1239d62bc4baSyz147064 
1240d62bc4baSyz147064 		vdp->vd_val = (uintptr_t)dlap;
1241*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	} else {
1242*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		vdp->vd_val = 0;
1243*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	}
1244d62bc4baSyz147064 	return (DLADM_STATUS_OK);
1245d62bc4baSyz147064 }
1246d62bc4baSyz147064 
1247e7801d59Ssowmini /* ARGSUSED */
1248d62bc4baSyz147064 static dladm_status_t
1249e7801d59Ssowmini do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid,
1250e7801d59Ssowmini     char **prop_val, uint_t *val_cnt, uint_t id)
1251d62bc4baSyz147064 {
1252d62bc4baSyz147064 	wl_rates_t	*wrp;
1253d62bc4baSyz147064 	uint_t		i;
1254d62bc4baSyz147064 	wldp_t		*gbuf = NULL;
1255d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1256d62bc4baSyz147064 
1257d62bc4baSyz147064 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
1258d62bc4baSyz147064 		status = DLADM_STATUS_NOMEM;
1259d62bc4baSyz147064 		goto done;
1260d62bc4baSyz147064 	}
1261d62bc4baSyz147064 
1262d62bc4baSyz147064 	status = i_dladm_wlan_get_ioctl(linkid, gbuf, id);
1263d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1264d62bc4baSyz147064 		goto done;
1265d62bc4baSyz147064 
1266d62bc4baSyz147064 	wrp = (wl_rates_t *)gbuf->wldp_buf;
1267d62bc4baSyz147064 	if (wrp->wl_rates_num > *val_cnt) {
1268d62bc4baSyz147064 		status = DLADM_STATUS_TOOSMALL;
1269d62bc4baSyz147064 		goto done;
1270d62bc4baSyz147064 	}
1271d62bc4baSyz147064 
1272d62bc4baSyz147064 	if (wrp->wl_rates_rates[0] == 0) {
1273d62bc4baSyz147064 		prop_val[0][0] = '\0';
1274d62bc4baSyz147064 		*val_cnt = 1;
1275d62bc4baSyz147064 		goto done;
1276d62bc4baSyz147064 	}
1277d62bc4baSyz147064 
1278d62bc4baSyz147064 	for (i = 0; i < wrp->wl_rates_num; i++) {
1279d62bc4baSyz147064 		(void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
1280d62bc4baSyz147064 		    wrp->wl_rates_rates[i] % 2,
1281d62bc4baSyz147064 		    (float)wrp->wl_rates_rates[i] / 2);
1282d62bc4baSyz147064 	}
1283d62bc4baSyz147064 	*val_cnt = wrp->wl_rates_num;
1284d62bc4baSyz147064 
1285d62bc4baSyz147064 done:
1286d62bc4baSyz147064 	free(gbuf);
1287d62bc4baSyz147064 	return (status);
1288d62bc4baSyz147064 }
1289d62bc4baSyz147064 
1290d62bc4baSyz147064 static dladm_status_t
1291e7801d59Ssowmini do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid,
12924045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1293d62bc4baSyz147064 {
12946b9e797cSsowmini 	if (media != DL_WIFI)
1295*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		return (i_dladm_speed_get(pd, linkid, prop_val,
1296*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		    val_cnt, flags));
12976b9e797cSsowmini 
1298e7801d59Ssowmini 	return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
1299d62bc4baSyz147064 	    WL_DESIRED_RATES));
1300d62bc4baSyz147064 }
1301d62bc4baSyz147064 
13024045d941Ssowmini /* ARGSUSED */
1303d62bc4baSyz147064 static dladm_status_t
1304e7801d59Ssowmini do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid,
13054045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1306d62bc4baSyz147064 {
13076b9e797cSsowmini 	switch (media) {
13086b9e797cSsowmini 	case DL_ETHER:
13094045d941Ssowmini 		/*
13104045d941Ssowmini 		 * Speed for ethernet links is unbounded. E.g., 802.11b
13114045d941Ssowmini 		 * links can have a speed of 5.5 Gbps.
13124045d941Ssowmini 		 */
13134045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
13146b9e797cSsowmini 
13156b9e797cSsowmini 	case DL_WIFI:
1316e7801d59Ssowmini 		return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
1317d62bc4baSyz147064 		    WL_SUPPORTED_RATES));
13186b9e797cSsowmini 	default:
13196b9e797cSsowmini 		return (DLADM_STATUS_BADARG);
13206b9e797cSsowmini 	}
1321d62bc4baSyz147064 }
1322d62bc4baSyz147064 
1323d62bc4baSyz147064 static dladm_status_t
1324d62bc4baSyz147064 do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates)
1325f4b3ec61Sdh155122 {
1326f4b3ec61Sdh155122 	int		i;
1327d62bc4baSyz147064 	uint_t		len;
1328d62bc4baSyz147064 	wldp_t		*gbuf;
1329d62bc4baSyz147064 	wl_rates_t	*wrp;
1330d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1331d62bc4baSyz147064 
1332d62bc4baSyz147064 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
1333d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1334d62bc4baSyz147064 
1335d62bc4baSyz147064 	(void) memset(gbuf, 0, MAX_BUF_LEN);
1336d62bc4baSyz147064 
1337d62bc4baSyz147064 	wrp = (wl_rates_t *)gbuf->wldp_buf;
1338d62bc4baSyz147064 	for (i = 0; i < rates->wr_cnt; i++)
1339d62bc4baSyz147064 		wrp->wl_rates_rates[i] = rates->wr_rates[i];
1340d62bc4baSyz147064 	wrp->wl_rates_num = rates->wr_cnt;
1341d62bc4baSyz147064 
1342d62bc4baSyz147064 	len = offsetof(wl_rates_t, wl_rates_rates) +
1343d62bc4baSyz147064 	    (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET;
1344d62bc4baSyz147064 	status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len,
1345d62bc4baSyz147064 	    WLAN_SET_PARAM, len);
1346d62bc4baSyz147064 
1347d62bc4baSyz147064 	free(gbuf);
1348d62bc4baSyz147064 	return (status);
1349d62bc4baSyz147064 }
1350d62bc4baSyz147064 
1351e7801d59Ssowmini /* ARGSUSED */
1352d62bc4baSyz147064 static dladm_status_t
1353e7801d59Ssowmini do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid,
13546b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1355d62bc4baSyz147064 {
1356d62bc4baSyz147064 	dladm_wlan_rates_t	rates;
1357f4b3ec61Sdh155122 	dladm_status_t		status;
1358f4b3ec61Sdh155122 
13596b9e797cSsowmini 	/*
13606b9e797cSsowmini 	 * can currently set rate on WIFI links only.
13616b9e797cSsowmini 	 */
13626b9e797cSsowmini 	if (media != DL_WIFI)
13636b9e797cSsowmini 		return (DLADM_STATUS_PROPRDONLY);
13646b9e797cSsowmini 
1365d62bc4baSyz147064 	if (val_cnt != 1)
1366d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1367f4b3ec61Sdh155122 
1368d62bc4baSyz147064 	rates.wr_cnt = 1;
1369d62bc4baSyz147064 	rates.wr_rates[0] = vdp[0].vd_val;
1370f4b3ec61Sdh155122 
1371d62bc4baSyz147064 	status = do_set_rate(linkid, &rates);
1372f4b3ec61Sdh155122 
1373d62bc4baSyz147064 done:
1374d62bc4baSyz147064 	return (status);
1375d62bc4baSyz147064 }
1376d62bc4baSyz147064 
1377d62bc4baSyz147064 /* ARGSUSED */
1378d62bc4baSyz147064 static dladm_status_t
1379e7801d59Ssowmini do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
13806b9e797cSsowmini     uint_t val_cnt, val_desc_t *vdp, datalink_media_t media)
1381d62bc4baSyz147064 {
1382d62bc4baSyz147064 	int		i;
1383d62bc4baSyz147064 	uint_t		modval_cnt = MAX_SUPPORT_RATES;
1384d62bc4baSyz147064 	char		*buf, **modval;
1385d62bc4baSyz147064 	dladm_status_t	status;
1386d62bc4baSyz147064 
1387d62bc4baSyz147064 	if (val_cnt != 1)
1388d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1389d62bc4baSyz147064 
1390d62bc4baSyz147064 	buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
1391d62bc4baSyz147064 	    MAX_SUPPORT_RATES);
1392d62bc4baSyz147064 	if (buf == NULL) {
1393d62bc4baSyz147064 		status = DLADM_STATUS_NOMEM;
1394d62bc4baSyz147064 		goto done;
1395d62bc4baSyz147064 	}
1396d62bc4baSyz147064 
1397d62bc4baSyz147064 	modval = (char **)(void *)buf;
1398d62bc4baSyz147064 	for (i = 0; i < MAX_SUPPORT_RATES; i++) {
1399d62bc4baSyz147064 		modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
1400d62bc4baSyz147064 		    i * DLADM_STRSIZE;
1401d62bc4baSyz147064 	}
1402d62bc4baSyz147064 
14034045d941Ssowmini 	status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt, media, 0);
1404d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1405d62bc4baSyz147064 		goto done;
1406d62bc4baSyz147064 
1407d62bc4baSyz147064 	for (i = 0; i < modval_cnt; i++) {
1408d62bc4baSyz147064 		if (strcasecmp(*prop_val, modval[i]) == 0) {
1409e7801d59Ssowmini 			vdp->vd_val = (uintptr_t)(uint_t)
1410e7801d59Ssowmini 			    (atof(*prop_val) * 2);
1411f4b3ec61Sdh155122 			status = DLADM_STATUS_OK;
1412f4b3ec61Sdh155122 			break;
1413f4b3ec61Sdh155122 		}
1414d62bc4baSyz147064 	}
1415d62bc4baSyz147064 	if (i == modval_cnt)
1416d62bc4baSyz147064 		status = DLADM_STATUS_BADVAL;
1417d62bc4baSyz147064 done:
1418d62bc4baSyz147064 	free(buf);
1419d62bc4baSyz147064 	return (status);
1420d62bc4baSyz147064 }
1421f4b3ec61Sdh155122 
1422d62bc4baSyz147064 static dladm_status_t
1423d62bc4baSyz147064 do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf)
1424d62bc4baSyz147064 {
1425d62bc4baSyz147064 	return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG));
1426d62bc4baSyz147064 }
1427d62bc4baSyz147064 
1428e7801d59Ssowmini /* ARGSUSED */
1429d62bc4baSyz147064 static dladm_status_t
1430e7801d59Ssowmini do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid,
14314045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1432d62bc4baSyz147064 {
1433d62bc4baSyz147064 	uint32_t	channel;
1434d62bc4baSyz147064 	wldp_t		*gbuf;
1435d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1436d62bc4baSyz147064 
1437d62bc4baSyz147064 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
1438d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1439d62bc4baSyz147064 
1440d62bc4baSyz147064 	if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK)
1441d62bc4baSyz147064 		goto done;
1442d62bc4baSyz147064 
1443d62bc4baSyz147064 	if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf,
1444d62bc4baSyz147064 	    &channel)) {
1445d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1446d62bc4baSyz147064 		goto done;
1447d62bc4baSyz147064 	}
1448d62bc4baSyz147064 
1449d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
1450d62bc4baSyz147064 	*val_cnt = 1;
1451d62bc4baSyz147064 
1452d62bc4baSyz147064 done:
1453d62bc4baSyz147064 	free(gbuf);
1454d62bc4baSyz147064 	return (status);
1455d62bc4baSyz147064 }
1456d62bc4baSyz147064 
1457d62bc4baSyz147064 static dladm_status_t
1458d62bc4baSyz147064 do_get_powermode(datalink_id_t linkid, wldp_t *gbuf)
1459d62bc4baSyz147064 {
1460d62bc4baSyz147064 	return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE));
1461d62bc4baSyz147064 }
1462d62bc4baSyz147064 
1463e7801d59Ssowmini /* ARGSUSED */
1464d62bc4baSyz147064 static dladm_status_t
1465e7801d59Ssowmini do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid,
14664045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1467d62bc4baSyz147064 {
1468d62bc4baSyz147064 	wl_ps_mode_t	*mode;
1469d62bc4baSyz147064 	const char	*s;
1470d62bc4baSyz147064 	wldp_t		*gbuf;
1471d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1472d62bc4baSyz147064 
1473d62bc4baSyz147064 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
1474d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1475d62bc4baSyz147064 
1476d62bc4baSyz147064 	if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK)
1477d62bc4baSyz147064 		goto done;
1478d62bc4baSyz147064 
1479d62bc4baSyz147064 	mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
1480d62bc4baSyz147064 	switch (mode->wl_ps_mode) {
1481d62bc4baSyz147064 	case WL_PM_AM:
1482d62bc4baSyz147064 		s = "off";
1483f4b3ec61Sdh155122 		break;
1484d62bc4baSyz147064 	case WL_PM_MPS:
1485d62bc4baSyz147064 		s = "max";
1486d62bc4baSyz147064 		break;
1487d62bc4baSyz147064 	case WL_PM_FAST:
1488d62bc4baSyz147064 		s = "fast";
1489f4b3ec61Sdh155122 		break;
1490f4b3ec61Sdh155122 	default:
1491d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1492d62bc4baSyz147064 		goto done;
1493f4b3ec61Sdh155122 	}
1494d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
1495d62bc4baSyz147064 	*val_cnt = 1;
1496d62bc4baSyz147064 
1497d62bc4baSyz147064 done:
1498d62bc4baSyz147064 	free(gbuf);
1499d62bc4baSyz147064 	return (status);
1500d62bc4baSyz147064 }
1501d62bc4baSyz147064 
1502d62bc4baSyz147064 static dladm_status_t
1503d62bc4baSyz147064 do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm)
1504d62bc4baSyz147064 {
1505d62bc4baSyz147064 	wl_ps_mode_t    ps_mode;
1506d62bc4baSyz147064 
1507d62bc4baSyz147064 	(void) memset(&ps_mode, 0xff, sizeof (ps_mode));
1508d62bc4baSyz147064 
1509d62bc4baSyz147064 	switch (*pm) {
1510d62bc4baSyz147064 	case DLADM_WLAN_PM_OFF:
1511d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_AM;
1512d62bc4baSyz147064 		break;
1513d62bc4baSyz147064 	case DLADM_WLAN_PM_MAX:
1514d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_MPS;
1515d62bc4baSyz147064 		break;
1516d62bc4baSyz147064 	case DLADM_WLAN_PM_FAST:
1517d62bc4baSyz147064 		ps_mode.wl_ps_mode = WL_PM_FAST;
1518d62bc4baSyz147064 		break;
1519d62bc4baSyz147064 	default:
1520d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
1521d62bc4baSyz147064 	}
1522d62bc4baSyz147064 	return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode,
1523d62bc4baSyz147064 	    sizeof (ps_mode)));
1524d62bc4baSyz147064 }
1525d62bc4baSyz147064 
1526d62bc4baSyz147064 /* ARGSUSED */
1527d62bc4baSyz147064 static dladm_status_t
1528e7801d59Ssowmini do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid,
15296b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1530d62bc4baSyz147064 {
1531d62bc4baSyz147064 	dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
1532d62bc4baSyz147064 	dladm_status_t status;
1533d62bc4baSyz147064 
1534d62bc4baSyz147064 	if (val_cnt != 1)
1535d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1536d62bc4baSyz147064 
1537d62bc4baSyz147064 	status = do_set_powermode(linkid, &powermode);
1538f4b3ec61Sdh155122 
1539f4b3ec61Sdh155122 	return (status);
1540f4b3ec61Sdh155122 }
1541f4b3ec61Sdh155122 
1542f4b3ec61Sdh155122 static dladm_status_t
1543d62bc4baSyz147064 do_get_radio(datalink_id_t linkid, wldp_t *gbuf)
1544f4b3ec61Sdh155122 {
1545d62bc4baSyz147064 	return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO));
1546d62bc4baSyz147064 }
1547d62bc4baSyz147064 
1548e7801d59Ssowmini /* ARGSUSED */
1549d62bc4baSyz147064 static dladm_status_t
1550e7801d59Ssowmini do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid,
15514045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1552d62bc4baSyz147064 {
1553d62bc4baSyz147064 	wl_radio_t	radio;
1554d62bc4baSyz147064 	const char	*s;
1555d62bc4baSyz147064 	wldp_t		*gbuf;
1556d62bc4baSyz147064 	dladm_status_t	status = DLADM_STATUS_OK;
1557d62bc4baSyz147064 
1558d62bc4baSyz147064 	if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
1559d62bc4baSyz147064 		return (DLADM_STATUS_NOMEM);
1560d62bc4baSyz147064 
1561d62bc4baSyz147064 	if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK)
1562d62bc4baSyz147064 		goto done;
1563d62bc4baSyz147064 
1564d62bc4baSyz147064 	radio = *(wl_radio_t *)(gbuf->wldp_buf);
1565d62bc4baSyz147064 	switch (radio) {
1566d62bc4baSyz147064 	case B_TRUE:
1567d62bc4baSyz147064 		s = "on";
1568d62bc4baSyz147064 		break;
1569d62bc4baSyz147064 	case B_FALSE:
1570d62bc4baSyz147064 		s = "off";
1571d62bc4baSyz147064 		break;
1572d62bc4baSyz147064 	default:
1573d62bc4baSyz147064 		status = DLADM_STATUS_NOTFOUND;
1574d62bc4baSyz147064 		goto done;
1575d62bc4baSyz147064 	}
1576d62bc4baSyz147064 	(void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
1577d62bc4baSyz147064 	*val_cnt = 1;
1578d62bc4baSyz147064 
1579d62bc4baSyz147064 done:
1580d62bc4baSyz147064 	free(gbuf);
1581d62bc4baSyz147064 	return (status);
1582d62bc4baSyz147064 }
1583d62bc4baSyz147064 
1584d62bc4baSyz147064 static dladm_status_t
1585d62bc4baSyz147064 do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio)
1586d62bc4baSyz147064 {
1587d62bc4baSyz147064 	wl_radio_t r;
1588d62bc4baSyz147064 
1589d62bc4baSyz147064 	switch (*radio) {
1590d62bc4baSyz147064 	case DLADM_WLAN_RADIO_ON:
1591d62bc4baSyz147064 		r = B_TRUE;
1592d62bc4baSyz147064 		break;
1593d62bc4baSyz147064 	case DLADM_WLAN_RADIO_OFF:
1594d62bc4baSyz147064 		r = B_FALSE;
1595d62bc4baSyz147064 		break;
1596d62bc4baSyz147064 	default:
1597d62bc4baSyz147064 		return (DLADM_STATUS_NOTSUP);
1598d62bc4baSyz147064 	}
1599d62bc4baSyz147064 	return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r)));
1600d62bc4baSyz147064 }
1601d62bc4baSyz147064 
1602d62bc4baSyz147064 /* ARGSUSED */
1603d62bc4baSyz147064 static dladm_status_t
1604e7801d59Ssowmini do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid,
16056b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t fags, datalink_media_t media)
1606d62bc4baSyz147064 {
1607d62bc4baSyz147064 	dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
1608f4b3ec61Sdh155122 	dladm_status_t status;
1609f4b3ec61Sdh155122 
1610d62bc4baSyz147064 	if (val_cnt != 1)
1611d62bc4baSyz147064 		return (DLADM_STATUS_BADVALCNT);
1612f4b3ec61Sdh155122 
1613d62bc4baSyz147064 	status = do_set_radio(linkid, &radio);
1614f4b3ec61Sdh155122 
1615d62bc4baSyz147064 	return (status);
1616d62bc4baSyz147064 }
1617f4b3ec61Sdh155122 
1618d62bc4baSyz147064 static dladm_status_t
1619d62bc4baSyz147064 i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name,
1620d62bc4baSyz147064     char **prop_val, uint_t val_cnt)
1621d62bc4baSyz147064 {
1622d62bc4baSyz147064 	char		buf[MAXLINELEN];
1623d62bc4baSyz147064 	int		i;
1624d62bc4baSyz147064 	dladm_conf_t	conf;
1625d62bc4baSyz147064 	dladm_status_t	status;
1626d62bc4baSyz147064 
1627d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
1628f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
1629f4b3ec61Sdh155122 		return (status);
1630f4b3ec61Sdh155122 
1631d62bc4baSyz147064 	/*
1632d62bc4baSyz147064 	 * reset case.
1633d62bc4baSyz147064 	 */
1634d62bc4baSyz147064 	if (val_cnt == 0) {
1635d62bc4baSyz147064 		status = dladm_unset_conf_field(conf, prop_name);
1636d62bc4baSyz147064 		if (status == DLADM_STATUS_OK)
1637d62bc4baSyz147064 			status = dladm_write_conf(conf);
1638d62bc4baSyz147064 		goto done;
1639f4b3ec61Sdh155122 	}
1640f4b3ec61Sdh155122 
1641d62bc4baSyz147064 	buf[0] = '\0';
1642d62bc4baSyz147064 	for (i = 0; i < val_cnt; i++) {
1643d62bc4baSyz147064 		(void) strlcat(buf, prop_val[i], MAXLINELEN);
1644d62bc4baSyz147064 		if (i != val_cnt - 1)
1645d62bc4baSyz147064 			(void) strlcat(buf, ",", MAXLINELEN);
1646d62bc4baSyz147064 	}
1647f4b3ec61Sdh155122 
1648d62bc4baSyz147064 	status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf);
1649d62bc4baSyz147064 	if (status == DLADM_STATUS_OK)
1650d62bc4baSyz147064 		status = dladm_write_conf(conf);
1651d62bc4baSyz147064 
1652d62bc4baSyz147064 done:
1653d62bc4baSyz147064 	dladm_destroy_conf(conf);
1654f4b3ec61Sdh155122 	return (status);
1655f4b3ec61Sdh155122 }
1656f4b3ec61Sdh155122 
1657f4b3ec61Sdh155122 static dladm_status_t
1658d62bc4baSyz147064 i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name,
1659d62bc4baSyz147064     char **prop_val, uint_t *val_cntp)
1660f4b3ec61Sdh155122 {
1661d62bc4baSyz147064 	char		buf[MAXLINELEN], *str;
1662d62bc4baSyz147064 	uint_t		cnt = 0;
1663d62bc4baSyz147064 	dladm_conf_t	conf;
1664d62bc4baSyz147064 	dladm_status_t	status;
1665f4b3ec61Sdh155122 
1666d62bc4baSyz147064 	status = dladm_read_conf(linkid, &conf);
1667d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1668f4b3ec61Sdh155122 		return (status);
1669d62bc4baSyz147064 
1670d62bc4baSyz147064 	status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN);
1671d62bc4baSyz147064 	if (status != DLADM_STATUS_OK)
1672d62bc4baSyz147064 		goto done;
1673d62bc4baSyz147064 
1674d62bc4baSyz147064 	str = strtok(buf, ",");
1675d62bc4baSyz147064 	while (str != NULL) {
1676d62bc4baSyz147064 		if (cnt == *val_cntp) {
1677d62bc4baSyz147064 			status = DLADM_STATUS_TOOSMALL;
1678d62bc4baSyz147064 			goto done;
1679d62bc4baSyz147064 		}
1680d62bc4baSyz147064 		(void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
1681d62bc4baSyz147064 		str = strtok(NULL, ",");
1682f4b3ec61Sdh155122 	}
1683f4b3ec61Sdh155122 
1684d62bc4baSyz147064 	*val_cntp = cnt;
1685f4b3ec61Sdh155122 
1686d62bc4baSyz147064 done:
1687d62bc4baSyz147064 	dladm_destroy_conf(conf);
1688d62bc4baSyz147064 	return (status);
1689f4b3ec61Sdh155122 }
1690e7801d59Ssowmini 
1691*3bc21d0aSAruna Ramakrishna - Sun Microsystems static dladm_public_prop_t *
1692e7801d59Ssowmini dladm_name2prop(const char *prop_name)
1693e7801d59Ssowmini {
1694*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_public_prop_t *p;
1695e7801d59Ssowmini 
1696*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	for (p = dladm_prop; p->pp_id != MAC_PROP_PRIVATE; p++) {
1697e7801d59Ssowmini 		if (strcmp(p->pp_name, prop_name) == 0)
1698e7801d59Ssowmini 			break;
1699e7801d59Ssowmini 	}
1700e7801d59Ssowmini 	return (p);
1701e7801d59Ssowmini }
1702e7801d59Ssowmini 
1703e7801d59Ssowmini 
17043fd94f8cSam223141 static dld_ioc_macprop_t *
1705*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name,
17064045d941Ssowmini     uint_t flags, dladm_status_t *status)
1707e7801d59Ssowmini {
1708e7801d59Ssowmini 	int dsize;
17093fd94f8cSam223141 	dld_ioc_macprop_t *dip;
1710*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_public_prop_t *p;
1711e7801d59Ssowmini 
1712e7801d59Ssowmini 	*status = DLADM_STATUS_OK;
1713e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
17143fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
1715e7801d59Ssowmini 		valsize = p->pp_valsize;
1716e7801d59Ssowmini 
17173fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(valsize);
1718e7801d59Ssowmini 	dip = malloc(dsize);
1719e7801d59Ssowmini 	if (dip == NULL) {
1720e7801d59Ssowmini 		*status = DLADM_STATUS_NOMEM;
1721e7801d59Ssowmini 		return (NULL);
1722e7801d59Ssowmini 	}
1723e7801d59Ssowmini 	bzero(dip, dsize);
1724e7801d59Ssowmini 	dip->pr_valsize = valsize;
17254045d941Ssowmini 	(void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name));
17263fd94f8cSam223141 	dip->pr_version = MAC_PROP_VERSION;
17276b9e797cSsowmini 	dip->pr_linkid = linkid;
1728e7801d59Ssowmini 	dip->pr_num = p->pp_id;
17294045d941Ssowmini 	dip->pr_flags = flags;
1730e7801d59Ssowmini 	return (dip);
1731e7801d59Ssowmini }
1732e7801d59Ssowmini 
1733e7801d59Ssowmini /* ARGSUSED */
1734e7801d59Ssowmini static dladm_status_t
1735*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_set_public_prop(prop_desc_t *pd, datalink_id_t linkid,
17366b9e797cSsowmini     val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media)
1737e7801d59Ssowmini {
17383fd94f8cSam223141 	dld_ioc_macprop_t	*dip;
1739e7801d59Ssowmini 	int		fd, dsize;
1740e7801d59Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
1741e7801d59Ssowmini 	uint8_t		u8;
1742e7801d59Ssowmini 	uint16_t	u16;
1743e7801d59Ssowmini 	uint32_t	u32;
1744e7801d59Ssowmini 	void		*val;
1745e7801d59Ssowmini 
1746*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_buf_alloc(0, linkid, pd->pd_name, 0, &status);
1747e7801d59Ssowmini 	if (dip == NULL)
1748e7801d59Ssowmini 		return (status);
1749e7801d59Ssowmini 
1750e7801d59Ssowmini 	if (pd->pd_flags & PD_CHECK_ALLOC)
1751e7801d59Ssowmini 		val = (void *)vdp->vd_val;
1752e7801d59Ssowmini 	else {
1753e7801d59Ssowmini 		/*
1754e7801d59Ssowmini 		 * Currently all 1/2/4-byte size properties are byte/word/int.
1755e7801d59Ssowmini 		 * No need (yet) to distinguish these from arrays of same size.
1756e7801d59Ssowmini 		 */
1757e7801d59Ssowmini 		switch (dip->pr_valsize) {
1758e7801d59Ssowmini 		case 1:
1759e7801d59Ssowmini 			u8 = vdp->vd_val;
1760e7801d59Ssowmini 			val = &u8;
1761e7801d59Ssowmini 			break;
1762e7801d59Ssowmini 		case 2:
1763e7801d59Ssowmini 			u16 = vdp->vd_val;
1764e7801d59Ssowmini 			val = &u16;
1765e7801d59Ssowmini 			break;
1766e7801d59Ssowmini 		case 4:
1767e7801d59Ssowmini 			u32 = vdp->vd_val;
1768e7801d59Ssowmini 			val = &u32;
1769e7801d59Ssowmini 			break;
1770e7801d59Ssowmini 		default:
1771e7801d59Ssowmini 			val = &vdp->vd_val;
1772e7801d59Ssowmini 			break;
1773e7801d59Ssowmini 		}
1774e7801d59Ssowmini 	}
1775e7801d59Ssowmini 
1776*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	if (val != NULL)
1777e7801d59Ssowmini 		(void) memcpy(dip->pr_val, val, dip->pr_valsize);
1778*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	else
1779*3bc21d0aSAruna Ramakrishna - Sun Microsystems 		dip->pr_valsize = 0;
1780*3bc21d0aSAruna Ramakrishna - Sun Microsystems 
17813fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(dip->pr_valsize);
1782e7801d59Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
1783e7801d59Ssowmini 		status = dladm_errno2status(errno);
1784e7801d59Ssowmini 		goto done;
1785e7801d59Ssowmini 	}
17863fd94f8cSam223141 	if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0)
1787e7801d59Ssowmini 		status = dladm_errno2status(errno);
1788e7801d59Ssowmini 
1789e7801d59Ssowmini 	(void) close(fd);
1790e7801d59Ssowmini done:
17914045d941Ssowmini 	free(dip);
1792e7801d59Ssowmini 	return (status);
1793e7801d59Ssowmini }
1794e7801d59Ssowmini 
17953fd94f8cSam223141 static dld_ioc_macprop_t *
1796*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags,
17974045d941Ssowmini     dladm_status_t *status)
1798e7801d59Ssowmini {
1799e7801d59Ssowmini 	int fd, dsize;
18003fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
18014045d941Ssowmini 
18024045d941Ssowmini 	*status = DLADM_STATUS_OK;
18034045d941Ssowmini 
1804*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_buf_alloc(0, linkid, prop_name, flags, status);
18054045d941Ssowmini 	if (dip == NULL)
18064045d941Ssowmini 		return (NULL);
1807e7801d59Ssowmini 
18083fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(dip->pr_valsize);
1809e7801d59Ssowmini 
1810e7801d59Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
18114045d941Ssowmini 		*status = dladm_errno2status(errno);
1812e7801d59Ssowmini 		goto done;
1813e7801d59Ssowmini 	}
18143fd94f8cSam223141 	if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) {
18154045d941Ssowmini 		*status = dladm_errno2status(errno);
1816e7801d59Ssowmini 	}
18174045d941Ssowmini 
18184045d941Ssowmini 	(void) close(fd);
1819e7801d59Ssowmini done:
18204045d941Ssowmini 	if (*status != DLADM_STATUS_OK) {
18214045d941Ssowmini 		free(dip);
18224045d941Ssowmini 		return (NULL);
18234045d941Ssowmini 	}
18244045d941Ssowmini 	return (dip);
1825e7801d59Ssowmini }
1826e7801d59Ssowmini 
1827e7801d59Ssowmini /* ARGSUSED */
1828e7801d59Ssowmini static dladm_status_t
1829*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_defmtu_check(struct prop_desc *pd, datalink_id_t linkid,
1830*3bc21d0aSAruna Ramakrishna - Sun Microsystems     char **prop_val, uint_t val_cnt, val_desc_t *v, datalink_media_t media)
1831e7801d59Ssowmini {
1832e7801d59Ssowmini 	if (val_cnt != 1)
1833e7801d59Ssowmini 		return (DLADM_STATUS_BADVAL);
18344045d941Ssowmini 	v->vd_val = atoi(prop_val[0]);
1835e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1836e7801d59Ssowmini }
1837e7801d59Ssowmini 
1838e7801d59Ssowmini /* ARGSUSED */
1839e7801d59Ssowmini static dladm_status_t
1840*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_duplex_get(struct prop_desc *pd, datalink_id_t linkid,
18414045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1842e7801d59Ssowmini {
1843e7801d59Ssowmini 	link_duplex_t   link_duplex;
1844e7801d59Ssowmini 	dladm_status_t  status;
1845e7801d59Ssowmini 
18463fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
18474045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
18484045d941Ssowmini 
1849e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "link_duplex",
1850e7801d59Ssowmini 	    KSTAT_DATA_UINT32, &link_duplex)) != 0)
1851e7801d59Ssowmini 		return (status);
1852e7801d59Ssowmini 
1853e7801d59Ssowmini 	switch (link_duplex) {
1854e7801d59Ssowmini 	case LINK_DUPLEX_FULL:
1855e7801d59Ssowmini 		(void) strcpy(*prop_val, "full");
1856e7801d59Ssowmini 		break;
1857e7801d59Ssowmini 	case LINK_DUPLEX_HALF:
1858e7801d59Ssowmini 		(void) strcpy(*prop_val, "half");
1859e7801d59Ssowmini 		break;
1860e7801d59Ssowmini 	default:
1861e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
1862e7801d59Ssowmini 		break;
1863e7801d59Ssowmini 	}
1864e7801d59Ssowmini 	*val_cnt = 1;
1865e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1866e7801d59Ssowmini }
1867e7801d59Ssowmini 
1868e7801d59Ssowmini /* ARGSUSED */
1869e7801d59Ssowmini static dladm_status_t
1870*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_speed_get(struct prop_desc *pd, datalink_id_t linkid,
18714045d941Ssowmini     char **prop_val, uint_t *val_cnt, uint_t flags)
1872e7801d59Ssowmini {
1873e7801d59Ssowmini 	uint64_t	ifspeed = 0;
1874e7801d59Ssowmini 	dladm_status_t status;
1875e7801d59Ssowmini 
18763fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
18774045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
18784045d941Ssowmini 
1879e7801d59Ssowmini 	if ((status = dladm_get_single_mac_stat(linkid, "ifspeed",
1880e7801d59Ssowmini 	    KSTAT_DATA_UINT64, &ifspeed)) != 0)
1881e7801d59Ssowmini 		return (status);
18824045d941Ssowmini 
18836b9e797cSsowmini 	if ((ifspeed % 1000000) != 0) {
18846b9e797cSsowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
18856b9e797cSsowmini 		    "%llf", ifspeed / (float)1000000); /* Mbps */
18866b9e797cSsowmini 	} else {
1887e7801d59Ssowmini 		(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
1888e7801d59Ssowmini 		    "%llu", ifspeed / 1000000); /* Mbps */
18896b9e797cSsowmini 	}
1890e7801d59Ssowmini 	*val_cnt = 1;
1891e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1892e7801d59Ssowmini }
1893e7801d59Ssowmini 
1894e7801d59Ssowmini /* ARGSUSED */
1895e7801d59Ssowmini static dladm_status_t
1896*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_status_get(struct prop_desc *pd, datalink_id_t linkid,
18974045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1898e7801d59Ssowmini {
1899e7801d59Ssowmini 	link_state_t	link_state;
1900e7801d59Ssowmini 	dladm_status_t	status;
19014045d941Ssowmini 	uchar_t 	*cp;
19023fd94f8cSam223141 	dld_ioc_macprop_t  *dip;
1903e7801d59Ssowmini 
19043fd94f8cSam223141 	if (flags & MAC_PROP_DEFAULT)
19054045d941Ssowmini 		return (DLADM_STATUS_NOTSUP);
1906*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19074045d941Ssowmini 	if (status != DLADM_STATUS_OK)
1908e7801d59Ssowmini 		return (status);
19094045d941Ssowmini 	cp = (uchar_t *)dip->pr_val;
19104045d941Ssowmini 	(void) memcpy(&link_state, cp, sizeof (link_state));
1911e7801d59Ssowmini 
1912e7801d59Ssowmini 	switch (link_state) {
1913e7801d59Ssowmini 	case LINK_STATE_UP:
1914e7801d59Ssowmini 		(void) strcpy(*prop_val, "up");
1915e7801d59Ssowmini 		break;
1916e7801d59Ssowmini 	case LINK_STATE_DOWN:
1917e7801d59Ssowmini 		(void) strcpy(*prop_val, "down");
1918e7801d59Ssowmini 		break;
1919e7801d59Ssowmini 	default:
1920e7801d59Ssowmini 		(void) strcpy(*prop_val, "unknown");
1921e7801d59Ssowmini 		break;
1922e7801d59Ssowmini 	}
1923e7801d59Ssowmini 	*val_cnt = 1;
19244045d941Ssowmini 	free(dip);
1925e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1926e7801d59Ssowmini }
1927e7801d59Ssowmini 
1928e7801d59Ssowmini /* ARGSUSED */
1929e7801d59Ssowmini static dladm_status_t
1930*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_binary_get(struct prop_desc *pd, datalink_id_t linkid,
19314045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1932e7801d59Ssowmini {
19333fd94f8cSam223141 	dld_ioc_macprop_t *dip;
1934e7801d59Ssowmini 	dladm_status_t status;
1935e7801d59Ssowmini 
1936*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19374045d941Ssowmini 	if (dip == NULL)
1938e7801d59Ssowmini 		return (status);
1939e7801d59Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
1940e7801d59Ssowmini 	free(dip);
1941e7801d59Ssowmini 	*val_cnt = 1;
1942e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1943e7801d59Ssowmini }
1944e7801d59Ssowmini 
19456b9e797cSsowmini /* ARGSUSED */
1946e7801d59Ssowmini static dladm_status_t
1947*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_uint32_get(struct prop_desc *pd, datalink_id_t linkid,
19484045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1949e7801d59Ssowmini {
19503fd94f8cSam223141 	dld_ioc_macprop_t *dip;
19514045d941Ssowmini 	uint32_t v  = 0;
1952e7801d59Ssowmini 	uchar_t *cp;
1953e7801d59Ssowmini 	dladm_status_t status;
1954e7801d59Ssowmini 
1955*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19564045d941Ssowmini 	if (dip == NULL)
1957e7801d59Ssowmini 		return (status);
1958e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
1959e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
19604045d941Ssowmini 	(void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%ld", v);
1961e7801d59Ssowmini 	free(dip);
1962e7801d59Ssowmini 	*val_cnt = 1;
1963e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1964e7801d59Ssowmini }
1965e7801d59Ssowmini 
19666b9e797cSsowmini /* ARGSUSED */
1967e7801d59Ssowmini static dladm_status_t
1968*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_flowctl_get(struct prop_desc *pd, datalink_id_t linkid,
19694045d941Ssowmini     char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags)
1970e7801d59Ssowmini {
19713fd94f8cSam223141 	dld_ioc_macprop_t *dip;
1972e7801d59Ssowmini 	link_flowctrl_t v;
1973e7801d59Ssowmini 	dladm_status_t status;
1974e7801d59Ssowmini 	uchar_t *cp;
1975e7801d59Ssowmini 
1976*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_get_public_prop(linkid, pd->pd_name, flags, &status);
19774045d941Ssowmini 	if (dip == NULL)
1978e7801d59Ssowmini 		return (status);
1979e7801d59Ssowmini 	cp = (uchar_t *)dip->pr_val;
1980e7801d59Ssowmini 	(void) memcpy(&v, cp, sizeof (v));
1981e7801d59Ssowmini 	switch (v) {
1982e7801d59Ssowmini 	case LINK_FLOWCTRL_NONE:
1983e7801d59Ssowmini 		(void) sprintf(*prop_val, "no");
1984e7801d59Ssowmini 		break;
1985e7801d59Ssowmini 	case LINK_FLOWCTRL_RX:
1986e7801d59Ssowmini 		(void) sprintf(*prop_val, "rx");
1987e7801d59Ssowmini 		break;
1988e7801d59Ssowmini 	case LINK_FLOWCTRL_TX:
1989e7801d59Ssowmini 		(void) sprintf(*prop_val, "tx");
1990e7801d59Ssowmini 		break;
1991e7801d59Ssowmini 	case LINK_FLOWCTRL_BI:
1992e7801d59Ssowmini 		(void) sprintf(*prop_val, "bi");
1993e7801d59Ssowmini 		break;
1994e7801d59Ssowmini 	}
1995e7801d59Ssowmini 	free(dip);
1996e7801d59Ssowmini 	*val_cnt = 1;
1997e7801d59Ssowmini 	return (DLADM_STATUS_OK);
1998e7801d59Ssowmini }
1999e7801d59Ssowmini 
2000e7801d59Ssowmini 
2001e7801d59Ssowmini /* ARGSUSED */
2002e7801d59Ssowmini static dladm_status_t
2003*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_set_prop(datalink_id_t linkid, const char *prop_name,
2004e7801d59Ssowmini     char **prop_val, uint_t val_cnt, uint_t flags)
2005e7801d59Ssowmini {
2006e7801d59Ssowmini 	int		fd, i, slen;
2007e7801d59Ssowmini 	int 		bufsize = 0, dsize;
20083fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2009e7801d59Ssowmini 	uchar_t 	*dp;
2010*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_public_prop_t *p;
20114045d941Ssowmini 	dladm_status_t	status = DLADM_STATUS_OK;
2012e7801d59Ssowmini 
2013e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2014e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2015e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2016e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
20173fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2018e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2019e7801d59Ssowmini 
2020e7801d59Ssowmini 	/*
2021e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2022e7801d59Ssowmini 	 * allocate a enough space for each property + its separator (',').
2023e7801d59Ssowmini 	 */
2024e7801d59Ssowmini 	for (i = 0; i < val_cnt; i++) {
2025e7801d59Ssowmini 		bufsize += strlen(prop_val[i]) + 1;
2026e7801d59Ssowmini 	}
20274045d941Ssowmini 
20284045d941Ssowmini 	if (prop_val == NULL) {
20294045d941Ssowmini 		/*
20304045d941Ssowmini 		 * getting default value. so use more buffer space.
20314045d941Ssowmini 		 */
20324045d941Ssowmini 		bufsize += 1024;
20334045d941Ssowmini 	}
20344045d941Ssowmini 
2035*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_buf_alloc(bufsize + 1, linkid, prop_name,
20363fd94f8cSam223141 	    (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status);
2037e7801d59Ssowmini 	if (dip == NULL)
2038e7801d59Ssowmini 		return (status);
2039e7801d59Ssowmini 
2040e7801d59Ssowmini 	dp = (uchar_t *)dip->pr_val;
20413fd94f8cSam223141 	dsize = sizeof (dld_ioc_macprop_t) + bufsize;
2042e7801d59Ssowmini 	slen = 0;
20434045d941Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
20444045d941Ssowmini 		status = dladm_errno2status(errno);
20454045d941Ssowmini 		goto done;
20464045d941Ssowmini 	}
20474045d941Ssowmini 	if (prop_val == NULL) {
20483fd94f8cSam223141 		if (i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize) < 0) {
20494045d941Ssowmini 			status = dladm_errno2status(errno);
20504045d941Ssowmini 			goto done;
20514045d941Ssowmini 		}
20524045d941Ssowmini 	} else {
2053e7801d59Ssowmini 		for (i = 0; i < val_cnt; i++) {
2054e7801d59Ssowmini 			int plen = 0;
2055e7801d59Ssowmini 
2056e7801d59Ssowmini 			plen = strlen(prop_val[i]);
2057e7801d59Ssowmini 			bcopy(prop_val[i], dp, plen);
2058e7801d59Ssowmini 			slen += plen;
2059e7801d59Ssowmini 			/*
2060e7801d59Ssowmini 			 * add a "," separator and update dp.
2061e7801d59Ssowmini 			 */
2062e7801d59Ssowmini 			if (i != (val_cnt -1))
2063e7801d59Ssowmini 				dp[slen++] = ',';
2064e7801d59Ssowmini 			dp += (plen + 1);
2065e7801d59Ssowmini 		}
2066e7801d59Ssowmini 	}
20673fd94f8cSam223141 	if (i_dladm_ioctl(fd, DLDIOC_SETMACPROP, dip, dsize) < 0) {
20684045d941Ssowmini 		status = dladm_errno2status(errno);
20694045d941Ssowmini 	}
20704045d941Ssowmini 
20714045d941Ssowmini done:
20724045d941Ssowmini 	if (fd > 0)
20734045d941Ssowmini 		(void) close(fd);
2074e7801d59Ssowmini 	free(dip);
2075e7801d59Ssowmini 	return (status);
2076e7801d59Ssowmini }
2077e7801d59Ssowmini 
2078e7801d59Ssowmini static dladm_status_t
2079*3bc21d0aSAruna Ramakrishna - Sun Microsystems i_dladm_get_prop(datalink_id_t linkid, const char *prop_name,
20804045d941Ssowmini     char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags)
2081e7801d59Ssowmini {
2082e7801d59Ssowmini 	int		fd;
2083e7801d59Ssowmini 	dladm_status_t  status = DLADM_STATUS_OK;
2084e7801d59Ssowmini 	uint_t 		dsize;
20853fd94f8cSam223141 	dld_ioc_macprop_t *dip = NULL;
2086*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dladm_public_prop_t *p;
2087e7801d59Ssowmini 	char tmp = '\0';
2088e7801d59Ssowmini 
2089e7801d59Ssowmini 	if ((prop_name == NULL && prop_val != NULL) ||
2090e7801d59Ssowmini 	    (prop_val != NULL && val_cnt == 0))
2091e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2092e7801d59Ssowmini 
2093e7801d59Ssowmini 	p = dladm_name2prop(prop_name);
20943fd94f8cSam223141 	if (p->pp_id != MAC_PROP_PRIVATE)
2095e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
2096e7801d59Ssowmini 
20974045d941Ssowmini 	if (type == DLADM_PROP_VAL_MODIFIABLE) {
2098e7801d59Ssowmini 		*prop_val = &tmp;
2099e7801d59Ssowmini 		*val_cnt = 1;
2100e7801d59Ssowmini 		return (DLADM_STATUS_OK);
2101e7801d59Ssowmini 	}
2102e7801d59Ssowmini 
2103e7801d59Ssowmini 	/*
2104e7801d59Ssowmini 	 * private properties: all parsing is done in the kernel.
2105e7801d59Ssowmini 	 */
2106*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	dip = i_dladm_buf_alloc(1024, linkid, prop_name, dld_flags, &status);
2107e7801d59Ssowmini 	if (dip == NULL)
2108e7801d59Ssowmini 		return (status);
21093fd94f8cSam223141 	dsize = MAC_PROP_BUFSIZE(dip->pr_valsize);
2110e7801d59Ssowmini 
21114045d941Ssowmini 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
21124045d941Ssowmini 		free(dip);
2113e7801d59Ssowmini 		return (DLADM_STATUS_BADARG);
21144045d941Ssowmini 	}
2115e7801d59Ssowmini 
21163fd94f8cSam223141 	if ((status = i_dladm_ioctl(fd, DLDIOC_GETMACPROP, dip, dsize)) < 0) {
2117e7801d59Ssowmini 		status = dladm_errno2status(errno);
2118e7801d59Ssowmini 	} else {
2119e7801d59Ssowmini 		(void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX);
2120e7801d59Ssowmini 		*val_cnt = 1;
2121e7801d59Ssowmini 	}
21224045d941Ssowmini 
21234045d941Ssowmini 	(void) close(fd);
21244045d941Ssowmini 	free(dip);
21254045d941Ssowmini 	return (status);
21264045d941Ssowmini }
21274045d941Ssowmini 
21284045d941Ssowmini 
21294045d941Ssowmini static dladm_status_t
21304045d941Ssowmini i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid,
21314045d941Ssowmini     datalink_media_t media, uint_t flags)
21324045d941Ssowmini {
21334045d941Ssowmini 	dladm_status_t status;
21344045d941Ssowmini 	char **prop_vals = NULL, *buf;
21354045d941Ssowmini 	size_t bufsize;
21364045d941Ssowmini 	uint_t cnt;
21374045d941Ssowmini 	int i;
21384045d941Ssowmini 
21394045d941Ssowmini 	/*
21404045d941Ssowmini 	 * Allocate buffer needed for prop_vals array. We can have at most
21414045d941Ssowmini 	 * DLADM_MAX_PROP_VALCNT char *prop_vals[] entries, where
21424045d941Ssowmini 	 * each entry has max size DLADM_PROP_VAL_MAX
21434045d941Ssowmini 	 */
21444045d941Ssowmini 	bufsize =
21454045d941Ssowmini 	    (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
21464045d941Ssowmini 	buf = malloc(bufsize);
21474045d941Ssowmini 	prop_vals = (char **)(void *)buf;
21484045d941Ssowmini 	for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
21494045d941Ssowmini 		prop_vals[i] = buf +
21504045d941Ssowmini 		    sizeof (char *) * DLADM_MAX_PROP_VALCNT +
21514045d941Ssowmini 		    i * DLADM_PROP_VAL_MAX;
21524045d941Ssowmini 	}
215313a55820Sar224390 
215413a55820Sar224390 	/*
2155*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * For properties which have pdp->pd_defval.vd_name as a non-empty
2156*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * string, the "" itself is used to reset the property (exceptions
2157*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * are zone and autopush, which populate vdp->vd_val). So
2158*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm can copy pdp->pd_defval over to the val_desc_t passed
2159*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * down on the setprop using the global values in the table. For
2160*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * other cases (vd_name is ""), doing reset-linkprop will cause
2161*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * libdladm to do a getprop to find the default value and then do
2162*3bc21d0aSAruna Ramakrishna - Sun Microsystems 	 * a setprop to reset the value to default.
216313a55820Sar224390 	 */
21643fd94f8cSam223141 	status = pdp->pd_get(pdp, linkid, prop_vals, &cnt, media,
21653fd94f8cSam223141 	    MAC_PROP_DEFAULT);
21664045d941Ssowmini 	if (status == DLADM_STATUS_OK) {
21674045d941Ssowmini 		status = i_dladm_set_single_prop(linkid, pdp->pd_class,
21684045d941Ssowmini 		    media, pdp, prop_vals, cnt, flags);
21694045d941Ssowmini 	}
21704045d941Ssowmini 	free(buf);
2171e7801d59Ssowmini 	return (status);
2172e7801d59Ssowmini }
2173