xref: /titanic_44/usr/src/lib/libdladm/common/linkprop.c (revision f4b3ec61df05330d25f55a36b975b4d7519fdeb1)
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 /*
22*f4b3ec61Sdh155122  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230ba2cbe9Sxc151355  * Use is subject to license terms.
240ba2cbe9Sxc151355  */
250ba2cbe9Sxc151355 
260ba2cbe9Sxc151355 #pragma ident	"%Z%%M%	%I%	%E% SMI"
270ba2cbe9Sxc151355 
280ba2cbe9Sxc151355 #include <stdlib.h>
290ba2cbe9Sxc151355 #include <strings.h>
300ba2cbe9Sxc151355 #include <errno.h>
310ba2cbe9Sxc151355 #include <ctype.h>
32*f4b3ec61Sdh155122 #include <sys/types.h>
330ba2cbe9Sxc151355 #include <sys/stat.h>
34*f4b3ec61Sdh155122 #include <sys/dld.h>
35*f4b3ec61Sdh155122 #include <sys/zone.h>
36*f4b3ec61Sdh155122 #include <fcntl.h>
37*f4b3ec61Sdh155122 #include <unistd.h>
38*f4b3ec61Sdh155122 #include <libdevinfo.h>
39*f4b3ec61Sdh155122 #include <zone.h>
400ba2cbe9Sxc151355 #include <libwladm.h>
410ba2cbe9Sxc151355 #include <libdladm_impl.h>
420ba2cbe9Sxc151355 
43*f4b3ec61Sdh155122 #include <dlfcn.h>
44*f4b3ec61Sdh155122 #include <link.h>
45*f4b3ec61Sdh155122 
460ba2cbe9Sxc151355 static dladm_status_t	i_dladm_set_prop_db(const char *, const char *,
470ba2cbe9Sxc151355 			    char **, uint_t);
480ba2cbe9Sxc151355 static dladm_status_t	i_dladm_get_prop_db(const char *, const char *,
490ba2cbe9Sxc151355 			    char **, uint_t *);
50*f4b3ec61Sdh155122 static dladm_status_t	i_dladm_get_prop_temp(const char *, dladm_prop_type_t,
51*f4b3ec61Sdh155122 			    const char *, char **, uint_t *);
52*f4b3ec61Sdh155122 static dladm_status_t	i_dladm_set_prop_temp(const char *, const char *,
53*f4b3ec61Sdh155122 			    char **, uint_t, uint_t, char **);
54*f4b3ec61Sdh155122 static boolean_t	i_dladm_is_prop_temponly(const char *prop_name,
55*f4b3ec61Sdh155122 			    char **);
56*f4b3ec61Sdh155122 
57*f4b3ec61Sdh155122 typedef struct val_desc {
58*f4b3ec61Sdh155122 	char	*vd_name;
59*f4b3ec61Sdh155122 	void	*vd_val;
60*f4b3ec61Sdh155122 } val_desc_t;
61*f4b3ec61Sdh155122 
62*f4b3ec61Sdh155122 struct prop_desc;
63*f4b3ec61Sdh155122 
64*f4b3ec61Sdh155122 typedef dladm_status_t	pd_getf_t(const char *, char **, uint_t *);
65*f4b3ec61Sdh155122 typedef dladm_status_t	pd_setf_t(const char *, val_desc_t *, uint_t);
66*f4b3ec61Sdh155122 typedef dladm_status_t	pd_checkf_t(struct prop_desc *, char **,
67*f4b3ec61Sdh155122 			    uint_t, val_desc_t **);
68*f4b3ec61Sdh155122 
69*f4b3ec61Sdh155122 static pd_getf_t	do_get_zone;
70*f4b3ec61Sdh155122 static pd_setf_t	do_set_zone;
71*f4b3ec61Sdh155122 static pd_checkf_t	do_check_zone;
72*f4b3ec61Sdh155122 
73*f4b3ec61Sdh155122 typedef struct prop_desc {
74*f4b3ec61Sdh155122 	char		*pd_name;
75*f4b3ec61Sdh155122 	val_desc_t	pd_defval;
76*f4b3ec61Sdh155122 	val_desc_t	*pd_modval;
77*f4b3ec61Sdh155122 	uint_t		pd_nmodval;
78*f4b3ec61Sdh155122 	boolean_t	pd_temponly;
79*f4b3ec61Sdh155122 	pd_setf_t	*pd_set;
80*f4b3ec61Sdh155122 	pd_getf_t	*pd_getmod;
81*f4b3ec61Sdh155122 	pd_getf_t	*pd_get;
82*f4b3ec61Sdh155122 	pd_checkf_t	*pd_check;
83*f4b3ec61Sdh155122 } prop_desc_t;
84*f4b3ec61Sdh155122 
85*f4b3ec61Sdh155122 static prop_desc_t	prop_table[] = {
86*f4b3ec61Sdh155122 	{ "zone",	{ "", NULL }, NULL, 0, B_TRUE,
87*f4b3ec61Sdh155122 	    do_set_zone, NULL,
88*f4b3ec61Sdh155122 	    do_get_zone, do_check_zone}
89*f4b3ec61Sdh155122 };
90*f4b3ec61Sdh155122 
91*f4b3ec61Sdh155122 #define	MAX_PROPS	(sizeof (prop_table) / sizeof (prop_desc_t))
920ba2cbe9Sxc151355 
930ba2cbe9Sxc151355 /*
940ba2cbe9Sxc151355  * Convert a wladm_status_t to a dladm_status_t. This is used by wrappers
950ba2cbe9Sxc151355  * to libwladm routines (e.g. dladm_set_prop()). Note that the mapping is
960ba2cbe9Sxc151355  * not 1-1; whenever possible we try to look for an error code with a
970ba2cbe9Sxc151355  * similar meaning. Error codes with no suitable counterpart in libdladm
980ba2cbe9Sxc151355  * will be mapped to DLADM_STATUS_FAILED. Clients who require clearer error
990ba2cbe9Sxc151355  * reporting should use libwladm directly.
1000ba2cbe9Sxc151355  */
1010ba2cbe9Sxc151355 static dladm_status_t
1020ba2cbe9Sxc151355 dladm_wladmstatus2status(wladm_status_t wstatus)
1030ba2cbe9Sxc151355 {
1040ba2cbe9Sxc151355 	switch (wstatus) {
1050ba2cbe9Sxc151355 	case WLADM_STATUS_OK:
1060ba2cbe9Sxc151355 		return (DLADM_STATUS_OK);
1070ba2cbe9Sxc151355 	case WLADM_STATUS_FAILED:
1080ba2cbe9Sxc151355 		return (DLADM_STATUS_FAILED);
1090ba2cbe9Sxc151355 	case WLADM_STATUS_NOTSUP:
1100ba2cbe9Sxc151355 		return (DLADM_STATUS_NOTSUP);
1110ba2cbe9Sxc151355 	case WLADM_STATUS_BADARG:
1120ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1130ba2cbe9Sxc151355 	case WLADM_STATUS_NOTFOUND:
1140ba2cbe9Sxc151355 		return (DLADM_STATUS_NOTFOUND);
1150ba2cbe9Sxc151355 	case WLADM_STATUS_BADVAL:
1160ba2cbe9Sxc151355 		return (DLADM_STATUS_BADVAL);
1170ba2cbe9Sxc151355 	case WLADM_STATUS_LINKINVAL:
1180ba2cbe9Sxc151355 		return (DLADM_STATUS_LINKINVAL);
1190ba2cbe9Sxc151355 	case WLADM_STATUS_NOMEM:
1200ba2cbe9Sxc151355 		return (DLADM_STATUS_NOMEM);
1210ba2cbe9Sxc151355 	case WLADM_STATUS_PROPRDONLY:
1220ba2cbe9Sxc151355 		return (DLADM_STATUS_PROPRDONLY);
1230ba2cbe9Sxc151355 	case WLADM_STATUS_TOOSMALL:
1240ba2cbe9Sxc151355 		return (DLADM_STATUS_TOOSMALL);
1250ba2cbe9Sxc151355 	case WLADM_STATUS_BADVALCNT:
1260ba2cbe9Sxc151355 		return (DLADM_STATUS_BADVALCNT);
1270ba2cbe9Sxc151355 	default:
1280ba2cbe9Sxc151355 		return (DLADM_STATUS_FAILED);
1290ba2cbe9Sxc151355 	}
1300ba2cbe9Sxc151355 }
1310ba2cbe9Sxc151355 
1320ba2cbe9Sxc151355 dladm_status_t
1330ba2cbe9Sxc151355 dladm_set_prop(const char *link, const char *prop_name, char **prop_val,
134*f4b3ec61Sdh155122     uint_t val_cnt, uint_t flags, char **errprop)
1350ba2cbe9Sxc151355 {
1360ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_BADARG;
1370ba2cbe9Sxc151355 
1380ba2cbe9Sxc151355 	if (link == NULL || (prop_val == NULL && val_cnt > 0) ||
1390ba2cbe9Sxc151355 	    (prop_val != NULL && val_cnt == 0) || flags == 0)
1400ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1410ba2cbe9Sxc151355 
1420ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_TEMP) != 0) {
143*f4b3ec61Sdh155122 		status = i_dladm_set_prop_temp(link, prop_name, prop_val,
144*f4b3ec61Sdh155122 		    val_cnt, flags, errprop);
145*f4b3ec61Sdh155122 		if (status == DLADM_STATUS_TEMPONLY &&
146*f4b3ec61Sdh155122 		    (flags & DLADM_OPT_PERSIST) != 0)
147*f4b3ec61Sdh155122 			return (DLADM_STATUS_TEMPONLY);
148*f4b3ec61Sdh155122 
149*f4b3ec61Sdh155122 		if (status == DLADM_STATUS_NOTFOUND) {
150*f4b3ec61Sdh155122 			status = DLADM_STATUS_BADARG;
1510ba2cbe9Sxc151355 			if (wladm_is_valid(link)) {
1520ba2cbe9Sxc151355 				status = dladm_wladmstatus2status(
1530ba2cbe9Sxc151355 				    wladm_set_prop(link, prop_name,
154*f4b3ec61Sdh155122 				    prop_val, val_cnt, errprop));
155*f4b3ec61Sdh155122 			}
1560ba2cbe9Sxc151355 		}
1570ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK)
1580ba2cbe9Sxc151355 			return (status);
1590ba2cbe9Sxc151355 	}
1600ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
161*f4b3ec61Sdh155122 		if (i_dladm_is_prop_temponly(prop_name, errprop))
162*f4b3ec61Sdh155122 			return (DLADM_STATUS_TEMPONLY);
163*f4b3ec61Sdh155122 
1640ba2cbe9Sxc151355 		status = i_dladm_set_prop_db(link, prop_name,
1650ba2cbe9Sxc151355 		    prop_val, val_cnt);
1660ba2cbe9Sxc151355 	}
1670ba2cbe9Sxc151355 	return (status);
1680ba2cbe9Sxc151355 }
1690ba2cbe9Sxc151355 
1700ba2cbe9Sxc151355 dladm_status_t
1710ba2cbe9Sxc151355 dladm_walk_prop(const char *link, void *arg,
1720ba2cbe9Sxc151355     boolean_t (*func)(void *, const char *))
1730ba2cbe9Sxc151355 {
174*f4b3ec61Sdh155122 	int	i;
175*f4b3ec61Sdh155122 
1760ba2cbe9Sxc151355 	if (link == NULL || func == NULL)
1770ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1780ba2cbe9Sxc151355 
179*f4b3ec61Sdh155122 	/* For wifi links, show wifi properties first */
1800ba2cbe9Sxc151355 	if (wladm_is_valid(link)) {
181*f4b3ec61Sdh155122 		dladm_status_t	status;
182*f4b3ec61Sdh155122 
183*f4b3ec61Sdh155122 		status = dladm_wladmstatus2status(
184*f4b3ec61Sdh155122 		    wladm_walk_prop(link, arg, func));
185*f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
186*f4b3ec61Sdh155122 			return (status);
1870ba2cbe9Sxc151355 	}
188*f4b3ec61Sdh155122 
189*f4b3ec61Sdh155122 	/* Then show data-link properties if there are any */
190*f4b3ec61Sdh155122 	for (i = 0; i < MAX_PROPS; i++) {
191*f4b3ec61Sdh155122 		if (!func(arg, prop_table[i].pd_name))
192*f4b3ec61Sdh155122 			break;
193*f4b3ec61Sdh155122 	}
194*f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1950ba2cbe9Sxc151355 }
1960ba2cbe9Sxc151355 
1970ba2cbe9Sxc151355 dladm_status_t
1980ba2cbe9Sxc151355 dladm_get_prop(const char *link, dladm_prop_type_t type,
1990ba2cbe9Sxc151355     const char *prop_name, char **prop_val, uint_t *val_cntp)
2000ba2cbe9Sxc151355 {
201*f4b3ec61Sdh155122 	dladm_status_t status;
202*f4b3ec61Sdh155122 
2030ba2cbe9Sxc151355 	if (link == NULL || prop_name == NULL || prop_val == NULL ||
2040ba2cbe9Sxc151355 	    val_cntp == NULL || *val_cntp == 0)
2050ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
2060ba2cbe9Sxc151355 
2070ba2cbe9Sxc151355 	if (type == DLADM_PROP_VAL_PERSISTENT) {
2080ba2cbe9Sxc151355 		return (i_dladm_get_prop_db(link, prop_name,
2090ba2cbe9Sxc151355 		    prop_val, val_cntp));
2100ba2cbe9Sxc151355 	}
2110ba2cbe9Sxc151355 
212*f4b3ec61Sdh155122 	status = i_dladm_get_prop_temp(link, type, prop_name,
213*f4b3ec61Sdh155122 	    prop_val, val_cntp);
214*f4b3ec61Sdh155122 	if (status != DLADM_STATUS_NOTFOUND)
215*f4b3ec61Sdh155122 		return (status);
216*f4b3ec61Sdh155122 
2170ba2cbe9Sxc151355 	if (wladm_is_valid(link)) {
2180ba2cbe9Sxc151355 		wladm_prop_type_t	wtype;
2190ba2cbe9Sxc151355 
2200ba2cbe9Sxc151355 		switch (type) {
2210ba2cbe9Sxc151355 		case DLADM_PROP_VAL_CURRENT:
2220ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_CURRENT;
2230ba2cbe9Sxc151355 			break;
2240ba2cbe9Sxc151355 		case DLADM_PROP_VAL_DEFAULT:
2250ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_DEFAULT;
2260ba2cbe9Sxc151355 			break;
2270ba2cbe9Sxc151355 		case DLADM_PROP_VAL_MODIFIABLE:
2280ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_MODIFIABLE;
2290ba2cbe9Sxc151355 			break;
2300ba2cbe9Sxc151355 		default:
2310ba2cbe9Sxc151355 			return (DLADM_STATUS_BADARG);
2320ba2cbe9Sxc151355 		}
2330ba2cbe9Sxc151355 
2340ba2cbe9Sxc151355 		return (dladm_wladmstatus2status(
2350ba2cbe9Sxc151355 		    wladm_get_prop(link, wtype, prop_name,
2360ba2cbe9Sxc151355 		    prop_val, val_cntp)));
2370ba2cbe9Sxc151355 	}
2380ba2cbe9Sxc151355 	return (DLADM_STATUS_BADARG);
2390ba2cbe9Sxc151355 }
2400ba2cbe9Sxc151355 
2410ba2cbe9Sxc151355 /*
2420ba2cbe9Sxc151355  * Data structures used for implementing persistent link properties
2430ba2cbe9Sxc151355  */
2440ba2cbe9Sxc151355 typedef struct linkprop_val {
2450ba2cbe9Sxc151355 	const char		*lv_name;
2460ba2cbe9Sxc151355 	struct linkprop_val	*lv_nextval;
2470ba2cbe9Sxc151355 } linkprop_val_t;
2480ba2cbe9Sxc151355 
2490ba2cbe9Sxc151355 typedef struct linkprop_info {
2500ba2cbe9Sxc151355 	const char		*li_name;
2510ba2cbe9Sxc151355 	struct linkprop_info	*li_nextprop;
2520ba2cbe9Sxc151355 	struct linkprop_val	*li_val;
2530ba2cbe9Sxc151355 } linkprop_info_t;
2540ba2cbe9Sxc151355 
2550ba2cbe9Sxc151355 typedef struct linkprop_db_state	linkprop_db_state_t;
2560ba2cbe9Sxc151355 
2570ba2cbe9Sxc151355 typedef boolean_t (*linkprop_db_op_t)(linkprop_db_state_t *,
2580ba2cbe9Sxc151355     char *, linkprop_info_t *, dladm_status_t *);
2590ba2cbe9Sxc151355 
2600ba2cbe9Sxc151355 struct linkprop_db_state {
2610ba2cbe9Sxc151355 	linkprop_db_op_t	ls_op;
2620ba2cbe9Sxc151355 	const char		*ls_link;
2630ba2cbe9Sxc151355 	const char		*ls_propname;
2640ba2cbe9Sxc151355 	char			**ls_propval;
2650ba2cbe9Sxc151355 	uint_t			*ls_valcntp;
2660ba2cbe9Sxc151355 };
2670ba2cbe9Sxc151355 
2680ba2cbe9Sxc151355 static void
2690ba2cbe9Sxc151355 free_linkprops(linkprop_info_t *lip)
2700ba2cbe9Sxc151355 {
2710ba2cbe9Sxc151355 	linkprop_info_t	*lip_next;
2720ba2cbe9Sxc151355 	linkprop_val_t	*lvp, *lvp_next;
2730ba2cbe9Sxc151355 
2740ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip_next) {
2750ba2cbe9Sxc151355 		lip_next = lip->li_nextprop;
2760ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
2770ba2cbe9Sxc151355 			lvp_next = lvp->lv_nextval;
2780ba2cbe9Sxc151355 			free(lvp);
2790ba2cbe9Sxc151355 		}
2800ba2cbe9Sxc151355 		free(lip);
2810ba2cbe9Sxc151355 	}
2820ba2cbe9Sxc151355 }
2830ba2cbe9Sxc151355 
2840ba2cbe9Sxc151355 /*
2850ba2cbe9Sxc151355  * Generate an entry in the link property database.
2860ba2cbe9Sxc151355  * Each entry has this format:
2870ba2cbe9Sxc151355  * <linkname>	<prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
2880ba2cbe9Sxc151355  */
2890ba2cbe9Sxc151355 static void
2900ba2cbe9Sxc151355 generate_linkprop_line(linkprop_db_state_t *lsp, char *buf,
2910ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
2920ba2cbe9Sxc151355 {
2930ba2cbe9Sxc151355 	char		tmpbuf[MAXLINELEN];
2940ba2cbe9Sxc151355 	char		*ptr, *lim = tmpbuf + MAXLINELEN;
2950ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
2960ba2cbe9Sxc151355 	linkprop_val_t	*lvp = NULL;
2970ba2cbe9Sxc151355 
2980ba2cbe9Sxc151355 	/*
2990ba2cbe9Sxc151355 	 * Delete line if there are no properties left.
3000ba2cbe9Sxc151355 	 */
3010ba2cbe9Sxc151355 	if (lip == NULL ||
3020ba2cbe9Sxc151355 	    (lip->li_val == NULL && lip->li_nextprop == NULL)) {
3030ba2cbe9Sxc151355 		buf[0] = '\0';
3040ba2cbe9Sxc151355 		return;
3050ba2cbe9Sxc151355 	}
3060ba2cbe9Sxc151355 	ptr = tmpbuf;
3070ba2cbe9Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", lsp->ls_link);
3080ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
3090ba2cbe9Sxc151355 		/*
3100ba2cbe9Sxc151355 		 * Skip properties without values.
3110ba2cbe9Sxc151355 		 */
3120ba2cbe9Sxc151355 		if (lip->li_val == NULL)
3130ba2cbe9Sxc151355 			continue;
3140ba2cbe9Sxc151355 
3150ba2cbe9Sxc151355 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s=", lip->li_name);
3160ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
3170ba2cbe9Sxc151355 			ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s%c",
3180ba2cbe9Sxc151355 			    lvp->lv_name,
3190ba2cbe9Sxc151355 			    ((lvp->lv_nextval == NULL) ? ';' : ','));
3200ba2cbe9Sxc151355 		}
3210ba2cbe9Sxc151355 	}
3220ba2cbe9Sxc151355 	if (ptr > lim) {
3230ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
3240ba2cbe9Sxc151355 		return;
3250ba2cbe9Sxc151355 	}
3260ba2cbe9Sxc151355 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
3270ba2cbe9Sxc151355 }
3280ba2cbe9Sxc151355 
3290ba2cbe9Sxc151355 /*
3300ba2cbe9Sxc151355  * This function is used to update or create an entry in the persistent db.
3310ba2cbe9Sxc151355  * process_linkprop_db() will first scan the db for an entry matching the
3320ba2cbe9Sxc151355  * specified link. If a match is found, this function is invoked with the
3330ba2cbe9Sxc151355  * entry's contents (buf) and its linked-list representation (listp). lsp
3340ba2cbe9Sxc151355  * holds the name and values of the property to be added or updated; this
3350ba2cbe9Sxc151355  * information will be merged with listp. Subsequently, an updated entry
3360ba2cbe9Sxc151355  * will be written to buf, which will in turn be written to disk by
3370ba2cbe9Sxc151355  * process_linkprop_db(). If no entry matches the specified link, listp
3380ba2cbe9Sxc151355  * will be NULL; a new entry will be generated in this case and it will
3390ba2cbe9Sxc151355  * contain only the property information in lsp.
3400ba2cbe9Sxc151355  */
3410ba2cbe9Sxc151355 static boolean_t
3420ba2cbe9Sxc151355 process_linkprop_set(linkprop_db_state_t *lsp, char *buf,
3430ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
3440ba2cbe9Sxc151355 {
3450ba2cbe9Sxc151355 	dladm_status_t	status;
3460ba2cbe9Sxc151355 	linkprop_info_t	*lastp = NULL, *lip = listp, *nlip = NULL;
3470ba2cbe9Sxc151355 	linkprop_val_t	**lvpp;
3480ba2cbe9Sxc151355 	int		i;
3490ba2cbe9Sxc151355 
3500ba2cbe9Sxc151355 	if (lsp->ls_propname == NULL) {
3510ba2cbe9Sxc151355 		buf[0] = '\0';
3520ba2cbe9Sxc151355 		return (B_FALSE);
3530ba2cbe9Sxc151355 	}
3540ba2cbe9Sxc151355 
3550ba2cbe9Sxc151355 	/*
3560ba2cbe9Sxc151355 	 * Find the linkprop we want to change.
3570ba2cbe9Sxc151355 	 */
3580ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
3590ba2cbe9Sxc151355 		if (strcmp(lip->li_name, lsp->ls_propname) == 0)
3600ba2cbe9Sxc151355 			break;
3610ba2cbe9Sxc151355 
3620ba2cbe9Sxc151355 		lastp = lip;
3630ba2cbe9Sxc151355 	}
3640ba2cbe9Sxc151355 
3650ba2cbe9Sxc151355 	if (lip == NULL) {
3660ba2cbe9Sxc151355 		/*
3670ba2cbe9Sxc151355 		 * If the linkprop is not found, append it to the list.
3680ba2cbe9Sxc151355 		 */
3690ba2cbe9Sxc151355 		if ((nlip = malloc(sizeof (linkprop_info_t))) == NULL) {
3700ba2cbe9Sxc151355 			status = DLADM_STATUS_NOMEM;
3710ba2cbe9Sxc151355 			goto fail;
3720ba2cbe9Sxc151355 		}
3730ba2cbe9Sxc151355 		/*
3740ba2cbe9Sxc151355 		 * nlip will need to be freed later if there is no list to
3750ba2cbe9Sxc151355 		 * append to.
3760ba2cbe9Sxc151355 		 */
3770ba2cbe9Sxc151355 		if (lastp != NULL)
3780ba2cbe9Sxc151355 			lastp->li_nextprop = nlip;
3790ba2cbe9Sxc151355 		nlip->li_name = lsp->ls_propname;
3800ba2cbe9Sxc151355 		nlip->li_nextprop = NULL;
3810ba2cbe9Sxc151355 		nlip->li_val = NULL;
3820ba2cbe9Sxc151355 		lvpp = &nlip->li_val;
3830ba2cbe9Sxc151355 	} else {
3840ba2cbe9Sxc151355 		linkprop_val_t	*lvp, *lvp_next;
3850ba2cbe9Sxc151355 
3860ba2cbe9Sxc151355 		/*
3870ba2cbe9Sxc151355 		 * If the linkprop is found, delete the existing values from it.
3880ba2cbe9Sxc151355 		 */
3890ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
3900ba2cbe9Sxc151355 			lvp_next = lvp->lv_nextval;
3910ba2cbe9Sxc151355 			free(lvp);
3920ba2cbe9Sxc151355 		}
3930ba2cbe9Sxc151355 		lip->li_val = NULL;
3940ba2cbe9Sxc151355 		lvpp = &lip->li_val;
3950ba2cbe9Sxc151355 	}
3960ba2cbe9Sxc151355 
3970ba2cbe9Sxc151355 	/*
3980ba2cbe9Sxc151355 	 * Fill our linkprop with the specified values.
3990ba2cbe9Sxc151355 	 */
4000ba2cbe9Sxc151355 	for (i = 0; i < *lsp->ls_valcntp; i++) {
4010ba2cbe9Sxc151355 		if ((*lvpp = malloc(sizeof (linkprop_val_t))) == NULL) {
4020ba2cbe9Sxc151355 			status = DLADM_STATUS_NOMEM;
4030ba2cbe9Sxc151355 			goto fail;
4040ba2cbe9Sxc151355 		}
4050ba2cbe9Sxc151355 		(*lvpp)->lv_name = lsp->ls_propval[i];
4060ba2cbe9Sxc151355 		(*lvpp)->lv_nextval = NULL;
4070ba2cbe9Sxc151355 		lvpp = &(*lvpp)->lv_nextval;
4080ba2cbe9Sxc151355 	}
4090ba2cbe9Sxc151355 
4100ba2cbe9Sxc151355 	if (listp != NULL) {
4110ba2cbe9Sxc151355 		generate_linkprop_line(lsp, buf, listp, statusp);
4120ba2cbe9Sxc151355 	} else {
4130ba2cbe9Sxc151355 		generate_linkprop_line(lsp, buf, nlip, statusp);
4140ba2cbe9Sxc151355 		free_linkprops(nlip);
4150ba2cbe9Sxc151355 	}
4160ba2cbe9Sxc151355 	return (B_FALSE);
4170ba2cbe9Sxc151355 
4180ba2cbe9Sxc151355 fail:
4190ba2cbe9Sxc151355 	*statusp = status;
4200ba2cbe9Sxc151355 	if (listp == NULL)
4210ba2cbe9Sxc151355 		free_linkprops(nlip);
4220ba2cbe9Sxc151355 
4230ba2cbe9Sxc151355 	return (B_FALSE);
4240ba2cbe9Sxc151355 }
4250ba2cbe9Sxc151355 
4260ba2cbe9Sxc151355 /*
4270ba2cbe9Sxc151355  * This function is used for retrieving the values for a specific property.
4280ba2cbe9Sxc151355  * It gets called if an entry matching the specified link exists in the db.
4290ba2cbe9Sxc151355  * The entry is converted into a linked-list listp. This list is then scanned
4300ba2cbe9Sxc151355  * for the specified property name; if a matching property exists, its
4310ba2cbe9Sxc151355  * associated values are copied to the array lsp->ls_propval.
4320ba2cbe9Sxc151355  */
4330ba2cbe9Sxc151355 /* ARGSUSED */
4340ba2cbe9Sxc151355 static boolean_t
4350ba2cbe9Sxc151355 process_linkprop_get(linkprop_db_state_t *lsp, char *buf,
4360ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
4370ba2cbe9Sxc151355 {
4380ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
4390ba2cbe9Sxc151355 	linkprop_val_t	*lvp;
4400ba2cbe9Sxc151355 	uint_t		valcnt = 0;
4410ba2cbe9Sxc151355 
4420ba2cbe9Sxc151355 	/*
4430ba2cbe9Sxc151355 	 * Find the linkprop we want to get.
4440ba2cbe9Sxc151355 	 */
4450ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
4460ba2cbe9Sxc151355 		if (strcmp(lip->li_name, lsp->ls_propname) == 0)
4470ba2cbe9Sxc151355 			break;
4480ba2cbe9Sxc151355 	}
4490ba2cbe9Sxc151355 	if (lip == NULL) {
4500ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_NOTFOUND;
4510ba2cbe9Sxc151355 		return (B_FALSE);
4520ba2cbe9Sxc151355 	}
4530ba2cbe9Sxc151355 
4540ba2cbe9Sxc151355 	for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
4550ba2cbe9Sxc151355 		(void) strncpy(lsp->ls_propval[valcnt], lvp->lv_name,
4560ba2cbe9Sxc151355 		    DLADM_PROP_VAL_MAX);
4570ba2cbe9Sxc151355 
4580ba2cbe9Sxc151355 		if (++valcnt >= *lsp->ls_valcntp && lvp->lv_nextval != NULL) {
4590ba2cbe9Sxc151355 			*statusp = DLADM_STATUS_TOOSMALL;
4600ba2cbe9Sxc151355 			return (B_FALSE);
4610ba2cbe9Sxc151355 		}
4620ba2cbe9Sxc151355 	}
4630ba2cbe9Sxc151355 	/*
4640ba2cbe9Sxc151355 	 * This function is meant to be called at most once for each call
4650ba2cbe9Sxc151355 	 * to process_linkprop_db(). For this reason, it's ok to overwrite
4660ba2cbe9Sxc151355 	 * the caller's valcnt array size with the actual number of values
4670ba2cbe9Sxc151355 	 * returned.
4680ba2cbe9Sxc151355 	 */
4690ba2cbe9Sxc151355 	*lsp->ls_valcntp = valcnt;
4700ba2cbe9Sxc151355 	return (B_FALSE);
4710ba2cbe9Sxc151355 }
4720ba2cbe9Sxc151355 
4730ba2cbe9Sxc151355 /*
4740ba2cbe9Sxc151355  * This is used for initializing link properties.
4750ba2cbe9Sxc151355  * Unlike the other routines, this gets called for every entry in the
4760ba2cbe9Sxc151355  * database. lsp->ls_link is not user-specified but instead is set to
4770ba2cbe9Sxc151355  * the current link being processed.
4780ba2cbe9Sxc151355  */
4790ba2cbe9Sxc151355 /* ARGSUSED */
4800ba2cbe9Sxc151355 static boolean_t
4810ba2cbe9Sxc151355 process_linkprop_init(linkprop_db_state_t *lsp, char *buf,
4820ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
4830ba2cbe9Sxc151355 {
4840ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
4850ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
4860ba2cbe9Sxc151355 	linkprop_val_t	*lvp;
4870ba2cbe9Sxc151355 	uint_t		valcnt, i;
4880ba2cbe9Sxc151355 	char		**propval;
4890ba2cbe9Sxc151355 
4900ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
4910ba2cbe9Sxc151355 		/*
4920ba2cbe9Sxc151355 		 * Construct the propval array and fill it with
4930ba2cbe9Sxc151355 		 * values from listp.
4940ba2cbe9Sxc151355 		 */
4950ba2cbe9Sxc151355 		for (lvp = lip->li_val, valcnt = 0;
4960ba2cbe9Sxc151355 		    lvp != NULL; lvp = lvp->lv_nextval, valcnt++);
4970ba2cbe9Sxc151355 
4980ba2cbe9Sxc151355 		propval = malloc(sizeof (char *) * valcnt);
4990ba2cbe9Sxc151355 		if (propval == NULL) {
5000ba2cbe9Sxc151355 			*statusp = DLADM_STATUS_NOMEM;
5010ba2cbe9Sxc151355 			break;
5020ba2cbe9Sxc151355 		}
5030ba2cbe9Sxc151355 		lvp = lip->li_val;
5040ba2cbe9Sxc151355 		for (i = 0; i < valcnt; i++, lvp = lvp->lv_nextval)
5050ba2cbe9Sxc151355 			propval[i] = (char *)lvp->lv_name;
5060ba2cbe9Sxc151355 
5070ba2cbe9Sxc151355 		status = dladm_set_prop(lsp->ls_link, lip->li_name,
508*f4b3ec61Sdh155122 		    propval, valcnt, DLADM_OPT_TEMP, NULL);
5090ba2cbe9Sxc151355 
5100ba2cbe9Sxc151355 		/*
5110ba2cbe9Sxc151355 		 * We continue with initializing other properties even
5120ba2cbe9Sxc151355 		 * after encountering an error. This error will be
5130ba2cbe9Sxc151355 		 * propagated to the caller via 'statusp'.
5140ba2cbe9Sxc151355 		 */
5150ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK)
5160ba2cbe9Sxc151355 			*statusp = status;
5170ba2cbe9Sxc151355 
5180ba2cbe9Sxc151355 		free(propval);
5190ba2cbe9Sxc151355 	}
5200ba2cbe9Sxc151355 	return (B_TRUE);
5210ba2cbe9Sxc151355 }
5220ba2cbe9Sxc151355 
5230ba2cbe9Sxc151355 static int
5240ba2cbe9Sxc151355 parse_linkprops(char *buf, linkprop_info_t **lipp)
5250ba2cbe9Sxc151355 {
5260ba2cbe9Sxc151355 	int			i, len;
5270ba2cbe9Sxc151355 	char			*curr;
5280ba2cbe9Sxc151355 	linkprop_info_t		*lip = NULL;
5290ba2cbe9Sxc151355 	linkprop_info_t		**tailp = lipp;
5300ba2cbe9Sxc151355 	linkprop_val_t		*lvp = NULL;
5310ba2cbe9Sxc151355 	linkprop_val_t		**vtailp = NULL;
5320ba2cbe9Sxc151355 
5330ba2cbe9Sxc151355 	curr = buf;
5340ba2cbe9Sxc151355 	len = strlen(buf);
5350ba2cbe9Sxc151355 	for (i = 0; i < len; i++) {
5360ba2cbe9Sxc151355 		char		c = buf[i];
5370ba2cbe9Sxc151355 		boolean_t	match = (c == '=' || c == ',' || c == ';');
5380ba2cbe9Sxc151355 
5390ba2cbe9Sxc151355 		/*
5400ba2cbe9Sxc151355 		 * Move to the next character if there is no match and
5410ba2cbe9Sxc151355 		 * if we have not reached the last character.
5420ba2cbe9Sxc151355 		 */
5430ba2cbe9Sxc151355 		if (!match && i != len - 1)
5440ba2cbe9Sxc151355 			continue;
5450ba2cbe9Sxc151355 
5460ba2cbe9Sxc151355 		if (match) {
5470ba2cbe9Sxc151355 			/*
5480ba2cbe9Sxc151355 			 * Nul-terminate the string pointed to by 'curr'.
5490ba2cbe9Sxc151355 			 */
5500ba2cbe9Sxc151355 			buf[i] = '\0';
5510ba2cbe9Sxc151355 			if (*curr == '\0')
5520ba2cbe9Sxc151355 				goto fail;
5530ba2cbe9Sxc151355 		}
5540ba2cbe9Sxc151355 
5550ba2cbe9Sxc151355 		if (lip != NULL) {
5560ba2cbe9Sxc151355 			/*
5570ba2cbe9Sxc151355 			 * We get here after we have processed the "<prop>="
5580ba2cbe9Sxc151355 			 * pattern. The pattern we are now interested in is
5590ba2cbe9Sxc151355 			 * "<val0>,<val1>,...,<valn>;". For each value we
5600ba2cbe9Sxc151355 			 * find, a linkprop_val_t will be allocated and
5610ba2cbe9Sxc151355 			 * added to the current 'lip'.
5620ba2cbe9Sxc151355 			 */
5630ba2cbe9Sxc151355 			if (c == '=')
5640ba2cbe9Sxc151355 				goto fail;
5650ba2cbe9Sxc151355 
5660ba2cbe9Sxc151355 			lvp = malloc(sizeof (*lvp));
5670ba2cbe9Sxc151355 			if (lvp == NULL)
5680ba2cbe9Sxc151355 				goto fail;
5690ba2cbe9Sxc151355 
5700ba2cbe9Sxc151355 			lvp->lv_name = curr;
5710ba2cbe9Sxc151355 			lvp->lv_nextval = NULL;
5720ba2cbe9Sxc151355 			*vtailp = lvp;
5730ba2cbe9Sxc151355 			vtailp = &lvp->lv_nextval;
5740ba2cbe9Sxc151355 
5750ba2cbe9Sxc151355 			if (c == ';') {
5760ba2cbe9Sxc151355 				tailp = &lip->li_nextprop;
5770ba2cbe9Sxc151355 				vtailp = NULL;
5780ba2cbe9Sxc151355 				lip = NULL;
5790ba2cbe9Sxc151355 			}
5800ba2cbe9Sxc151355 		} else {
5810ba2cbe9Sxc151355 			/*
5820ba2cbe9Sxc151355 			 * lip == NULL indicates that 'curr' must be refering
5830ba2cbe9Sxc151355 			 * to a property name. We allocate a new linkprop_info_t
5840ba2cbe9Sxc151355 			 * append it to the list given by the caller.
5850ba2cbe9Sxc151355 			 */
5860ba2cbe9Sxc151355 			if (c != '=')
5870ba2cbe9Sxc151355 				goto fail;
5880ba2cbe9Sxc151355 
5890ba2cbe9Sxc151355 			lip = malloc(sizeof (*lip));
5900ba2cbe9Sxc151355 			if (lip == NULL)
5910ba2cbe9Sxc151355 				goto fail;
5920ba2cbe9Sxc151355 
5930ba2cbe9Sxc151355 			lip->li_name = curr;
5940ba2cbe9Sxc151355 			lip->li_val = NULL;
5950ba2cbe9Sxc151355 			lip->li_nextprop = NULL;
5960ba2cbe9Sxc151355 			*tailp = lip;
5970ba2cbe9Sxc151355 			vtailp = &lip->li_val;
5980ba2cbe9Sxc151355 		}
5990ba2cbe9Sxc151355 		curr = buf + i + 1;
6000ba2cbe9Sxc151355 	}
6010ba2cbe9Sxc151355 	/*
6020ba2cbe9Sxc151355 	 * The list must be non-empty and the last character must be ';'.
6030ba2cbe9Sxc151355 	 */
6040ba2cbe9Sxc151355 	if (*lipp == NULL || lip != NULL)
6050ba2cbe9Sxc151355 		goto fail;
6060ba2cbe9Sxc151355 
6070ba2cbe9Sxc151355 	return (0);
6080ba2cbe9Sxc151355 
6090ba2cbe9Sxc151355 fail:
6100ba2cbe9Sxc151355 	free_linkprops(*lipp);
6110ba2cbe9Sxc151355 	*lipp = NULL;
6120ba2cbe9Sxc151355 	return (-1);
6130ba2cbe9Sxc151355 }
6140ba2cbe9Sxc151355 
6150ba2cbe9Sxc151355 static boolean_t
6160ba2cbe9Sxc151355 process_linkprop_line(linkprop_db_state_t *lsp, char *buf,
6170ba2cbe9Sxc151355     dladm_status_t *statusp)
6180ba2cbe9Sxc151355 {
6190ba2cbe9Sxc151355 	linkprop_info_t		*lip = NULL;
6200ba2cbe9Sxc151355 	int			i, len, llen;
6210ba2cbe9Sxc151355 	char			*str, *lasts;
6220ba2cbe9Sxc151355 	boolean_t		cont, nolink = B_FALSE;
6230ba2cbe9Sxc151355 
6240ba2cbe9Sxc151355 	/*
6250ba2cbe9Sxc151355 	 * Skip leading spaces, blank lines, and comments.
6260ba2cbe9Sxc151355 	 */
6270ba2cbe9Sxc151355 	len = strlen(buf);
6280ba2cbe9Sxc151355 	for (i = 0; i < len; i++) {
6290ba2cbe9Sxc151355 		if (!isspace(buf[i]))
6300ba2cbe9Sxc151355 			break;
6310ba2cbe9Sxc151355 	}
6320ba2cbe9Sxc151355 	if (i == len || buf[i] == '#')
6330ba2cbe9Sxc151355 		return (B_TRUE);
6340ba2cbe9Sxc151355 
6350ba2cbe9Sxc151355 	str = buf + i;
6360ba2cbe9Sxc151355 	if (lsp->ls_link != NULL) {
6370ba2cbe9Sxc151355 		/*
6380ba2cbe9Sxc151355 		 * Skip links we're not interested in.
6390ba2cbe9Sxc151355 		 * Note that strncmp() and isspace() are used here
6400ba2cbe9Sxc151355 		 * instead of strtok() and strcmp() because we don't
6410ba2cbe9Sxc151355 		 * want to modify buf in case it does not contain the
6420ba2cbe9Sxc151355 		 * specified link.
6430ba2cbe9Sxc151355 		 */
6440ba2cbe9Sxc151355 		llen = strlen(lsp->ls_link);
6450ba2cbe9Sxc151355 		if (strncmp(str, lsp->ls_link, llen) != 0 ||
6460ba2cbe9Sxc151355 		    !isspace(str[llen]))
6470ba2cbe9Sxc151355 			return (B_TRUE);
6480ba2cbe9Sxc151355 	} else {
6490ba2cbe9Sxc151355 		/*
6500ba2cbe9Sxc151355 		 * If a link is not specified, find the link name
6510ba2cbe9Sxc151355 		 * and assign it to lsp->ls_link.
6520ba2cbe9Sxc151355 		 */
6530ba2cbe9Sxc151355 		if (strtok_r(str, " \n\t", &lasts) == NULL)
6540ba2cbe9Sxc151355 			goto fail;
6550ba2cbe9Sxc151355 
6560ba2cbe9Sxc151355 		llen = strlen(str);
6570ba2cbe9Sxc151355 		lsp->ls_link = str;
6580ba2cbe9Sxc151355 		nolink = B_TRUE;
6590ba2cbe9Sxc151355 	}
6600ba2cbe9Sxc151355 	str += llen + 1;
6610ba2cbe9Sxc151355 	if (str >= buf + len)
6620ba2cbe9Sxc151355 		goto fail;
6630ba2cbe9Sxc151355 
6640ba2cbe9Sxc151355 	/*
6650ba2cbe9Sxc151355 	 * Now find the list of link properties.
6660ba2cbe9Sxc151355 	 */
6670ba2cbe9Sxc151355 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
6680ba2cbe9Sxc151355 		goto fail;
6690ba2cbe9Sxc151355 
6700ba2cbe9Sxc151355 	if (parse_linkprops(str, &lip) < 0)
6710ba2cbe9Sxc151355 		goto fail;
6720ba2cbe9Sxc151355 
6730ba2cbe9Sxc151355 	cont = (*lsp->ls_op)(lsp, buf, lip, statusp);
6740ba2cbe9Sxc151355 	free_linkprops(lip);
6750ba2cbe9Sxc151355 	if (nolink)
6760ba2cbe9Sxc151355 		lsp->ls_link = NULL;
6770ba2cbe9Sxc151355 	return (cont);
6780ba2cbe9Sxc151355 
6790ba2cbe9Sxc151355 fail:
6800ba2cbe9Sxc151355 	free_linkprops(lip);
6810ba2cbe9Sxc151355 	if (nolink)
6820ba2cbe9Sxc151355 		lsp->ls_link = NULL;
6830ba2cbe9Sxc151355 
6840ba2cbe9Sxc151355 	/*
6850ba2cbe9Sxc151355 	 * Delete corrupted line.
6860ba2cbe9Sxc151355 	 */
6870ba2cbe9Sxc151355 	buf[0] = '\0';
6880ba2cbe9Sxc151355 	return (B_TRUE);
6890ba2cbe9Sxc151355 }
6900ba2cbe9Sxc151355 
6910ba2cbe9Sxc151355 static dladm_status_t
6920ba2cbe9Sxc151355 process_linkprop_db(void *arg, FILE *fp, FILE *nfp)
6930ba2cbe9Sxc151355 {
6940ba2cbe9Sxc151355 	linkprop_db_state_t	*lsp = arg;
6950ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
6960ba2cbe9Sxc151355 	char			buf[MAXLINELEN];
6970ba2cbe9Sxc151355 	boolean_t		cont = B_TRUE;
6980ba2cbe9Sxc151355 
6990ba2cbe9Sxc151355 	/*
7000ba2cbe9Sxc151355 	 * This loop processes each line of the configuration file.
7010ba2cbe9Sxc151355 	 * buf can potentially be modified by process_linkprop_line().
7020ba2cbe9Sxc151355 	 * If this is a write operation and buf is not truncated, buf will
7030ba2cbe9Sxc151355 	 * be written to disk. process_linkprop_line() will no longer be
7040ba2cbe9Sxc151355 	 * called after it returns B_FALSE; at which point the remainder
7050ba2cbe9Sxc151355 	 * of the file will continue to be read and, if necessary, written
7060ba2cbe9Sxc151355 	 * to disk as well.
7070ba2cbe9Sxc151355 	 */
7080ba2cbe9Sxc151355 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
7090ba2cbe9Sxc151355 		if (cont)
7100ba2cbe9Sxc151355 			cont = process_linkprop_line(lsp, buf, &status);
7110ba2cbe9Sxc151355 
7120ba2cbe9Sxc151355 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
7130ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
7140ba2cbe9Sxc151355 			break;
7150ba2cbe9Sxc151355 		}
7160ba2cbe9Sxc151355 	}
7170ba2cbe9Sxc151355 
7180ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK || !cont)
7190ba2cbe9Sxc151355 		return (status);
7200ba2cbe9Sxc151355 
7210ba2cbe9Sxc151355 	if (lsp->ls_op == process_linkprop_set) {
7220ba2cbe9Sxc151355 		/*
7230ba2cbe9Sxc151355 		 * If the specified link is not found above, we add the
7240ba2cbe9Sxc151355 		 * link and its properties to the configuration file.
7250ba2cbe9Sxc151355 		 */
7260ba2cbe9Sxc151355 		(void) (*lsp->ls_op)(lsp, buf, NULL, &status);
7270ba2cbe9Sxc151355 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
7280ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
7290ba2cbe9Sxc151355 	}
7300ba2cbe9Sxc151355 
7310ba2cbe9Sxc151355 	if (lsp->ls_op == process_linkprop_get)
7320ba2cbe9Sxc151355 		status = DLADM_STATUS_NOTFOUND;
7330ba2cbe9Sxc151355 
7340ba2cbe9Sxc151355 	return (status);
7350ba2cbe9Sxc151355 }
7360ba2cbe9Sxc151355 
7370ba2cbe9Sxc151355 #define	LINKPROP_RW_DB(statep, writeop) \
7380ba2cbe9Sxc151355 	(i_dladm_rw_db("/etc/dladm/linkprop.conf", \
7390ba2cbe9Sxc151355 	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_linkprop_db, \
7400ba2cbe9Sxc151355 	(statep), (writeop)))
7410ba2cbe9Sxc151355 
7420ba2cbe9Sxc151355 static dladm_status_t
7430ba2cbe9Sxc151355 i_dladm_set_prop_db(const char *link, const char *prop_name,
7440ba2cbe9Sxc151355     char **prop_val, uint_t val_cnt)
7450ba2cbe9Sxc151355 {
7460ba2cbe9Sxc151355 	linkprop_db_state_t	state;
7470ba2cbe9Sxc151355 
7480ba2cbe9Sxc151355 	state.ls_op = process_linkprop_set;
7490ba2cbe9Sxc151355 	state.ls_link = link;
7500ba2cbe9Sxc151355 	state.ls_propname = prop_name;
7510ba2cbe9Sxc151355 	state.ls_propval = prop_val;
7520ba2cbe9Sxc151355 	state.ls_valcntp = &val_cnt;
7530ba2cbe9Sxc151355 
7540ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_TRUE));
7550ba2cbe9Sxc151355 }
7560ba2cbe9Sxc151355 
7570ba2cbe9Sxc151355 static dladm_status_t
7580ba2cbe9Sxc151355 i_dladm_get_prop_db(const char *link, const char *prop_name,
7590ba2cbe9Sxc151355     char **prop_val, uint_t *val_cntp)
7600ba2cbe9Sxc151355 {
7610ba2cbe9Sxc151355 	linkprop_db_state_t	state;
7620ba2cbe9Sxc151355 
7630ba2cbe9Sxc151355 	state.ls_op = process_linkprop_get;
7640ba2cbe9Sxc151355 	state.ls_link = link;
7650ba2cbe9Sxc151355 	state.ls_propname = prop_name;
7660ba2cbe9Sxc151355 	state.ls_propval = prop_val;
7670ba2cbe9Sxc151355 	state.ls_valcntp = val_cntp;
7680ba2cbe9Sxc151355 
7690ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_FALSE));
7700ba2cbe9Sxc151355 }
7710ba2cbe9Sxc151355 
7720ba2cbe9Sxc151355 dladm_status_t
7730ba2cbe9Sxc151355 dladm_init_linkprop(void)
7740ba2cbe9Sxc151355 {
7750ba2cbe9Sxc151355 	linkprop_db_state_t	state;
7760ba2cbe9Sxc151355 
7770ba2cbe9Sxc151355 	state.ls_op = process_linkprop_init;
7780ba2cbe9Sxc151355 	state.ls_link = NULL;
7790ba2cbe9Sxc151355 	state.ls_propname = NULL;
7800ba2cbe9Sxc151355 	state.ls_propval = NULL;
7810ba2cbe9Sxc151355 	state.ls_valcntp = NULL;
7820ba2cbe9Sxc151355 
7830ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_FALSE));
7840ba2cbe9Sxc151355 }
785*f4b3ec61Sdh155122 
786*f4b3ec61Sdh155122 static dladm_status_t
787*f4b3ec61Sdh155122 i_dladm_get_zoneid(const char *link, zoneid_t *zidp)
788*f4b3ec61Sdh155122 {
789*f4b3ec61Sdh155122 	int fd;
790*f4b3ec61Sdh155122 	dld_hold_vlan_t	dhv;
791*f4b3ec61Sdh155122 
792*f4b3ec61Sdh155122 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
793*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
794*f4b3ec61Sdh155122 
795*f4b3ec61Sdh155122 	bzero(&dhv, sizeof (dld_hold_vlan_t));
796*f4b3ec61Sdh155122 	(void) strlcpy(dhv.dhv_name, link, IFNAMSIZ);
797*f4b3ec61Sdh155122 	dhv.dhv_zid = -1;
798*f4b3ec61Sdh155122 
799*f4b3ec61Sdh155122 	if (i_dladm_ioctl(fd, DLDIOCZIDGET, &dhv, sizeof (dhv)) < 0 &&
800*f4b3ec61Sdh155122 	    errno != ENOENT) {
801*f4b3ec61Sdh155122 		dladm_status_t status = dladm_errno2status(errno);
802*f4b3ec61Sdh155122 
803*f4b3ec61Sdh155122 		(void) close(fd);
804*f4b3ec61Sdh155122 		return (status);
805*f4b3ec61Sdh155122 	}
806*f4b3ec61Sdh155122 
807*f4b3ec61Sdh155122 	if (errno == ENOENT)
808*f4b3ec61Sdh155122 		*zidp = GLOBAL_ZONEID;
809*f4b3ec61Sdh155122 	else
810*f4b3ec61Sdh155122 		*zidp = dhv.dhv_zid;
811*f4b3ec61Sdh155122 
812*f4b3ec61Sdh155122 	(void) close(fd);
813*f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
814*f4b3ec61Sdh155122 }
815*f4b3ec61Sdh155122 
816*f4b3ec61Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t);
817*f4b3ec61Sdh155122 
818*f4b3ec61Sdh155122 static int
819*f4b3ec61Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
820*f4b3ec61Sdh155122 {
821*f4b3ec61Sdh155122 	char			root[MAXPATHLEN];
822*f4b3ec61Sdh155122 	zone_get_devroot_t	real_zone_get_devroot;
823*f4b3ec61Sdh155122 	void			*dlhandle;
824*f4b3ec61Sdh155122 	void			*sym;
825*f4b3ec61Sdh155122 	int			ret;
826*f4b3ec61Sdh155122 
827*f4b3ec61Sdh155122 	if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL)
828*f4b3ec61Sdh155122 		return (-1);
829*f4b3ec61Sdh155122 
830*f4b3ec61Sdh155122 	if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) {
831*f4b3ec61Sdh155122 		(void) dlclose(dlhandle);
832*f4b3ec61Sdh155122 		return (-1);
833*f4b3ec61Sdh155122 	}
834*f4b3ec61Sdh155122 
835*f4b3ec61Sdh155122 	real_zone_get_devroot = (zone_get_devroot_t)sym;
836*f4b3ec61Sdh155122 
837*f4b3ec61Sdh155122 	if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0)
838*f4b3ec61Sdh155122 		(void) snprintf(dev, devlen, "%s%s", root, "/dev");
839*f4b3ec61Sdh155122 	(void) dlclose(dlhandle);
840*f4b3ec61Sdh155122 	return (ret);
841*f4b3ec61Sdh155122 }
842*f4b3ec61Sdh155122 
843*f4b3ec61Sdh155122 static dladm_status_t
844*f4b3ec61Sdh155122 i_dladm_add_deventry(zoneid_t zid, const char *link)
845*f4b3ec61Sdh155122 {
846*f4b3ec61Sdh155122 	char		path[MAXPATHLEN];
847*f4b3ec61Sdh155122 	di_prof_t	prof = NULL;
848*f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
849*f4b3ec61Sdh155122 	dladm_status_t	status;
850*f4b3ec61Sdh155122 
851*f4b3ec61Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
852*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
853*f4b3ec61Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
854*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
855*f4b3ec61Sdh155122 	if (di_prof_init(path, &prof) != 0)
856*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
857*f4b3ec61Sdh155122 
858*f4b3ec61Sdh155122 	status = DLADM_STATUS_OK;
859*f4b3ec61Sdh155122 	if (di_prof_add_dev(prof, link) != 0) {
860*f4b3ec61Sdh155122 		status = dladm_errno2status(errno);
861*f4b3ec61Sdh155122 		goto cleanup;
862*f4b3ec61Sdh155122 	}
863*f4b3ec61Sdh155122 	if (di_prof_commit(prof) != 0)
864*f4b3ec61Sdh155122 		status = dladm_errno2status(errno);
865*f4b3ec61Sdh155122 cleanup:
866*f4b3ec61Sdh155122 	if (prof)
867*f4b3ec61Sdh155122 		di_prof_fini(prof);
868*f4b3ec61Sdh155122 
869*f4b3ec61Sdh155122 	return (status);
870*f4b3ec61Sdh155122 }
871*f4b3ec61Sdh155122 
872*f4b3ec61Sdh155122 static dladm_status_t
873*f4b3ec61Sdh155122 i_dladm_remove_deventry(zoneid_t zid, const char *link)
874*f4b3ec61Sdh155122 {
875*f4b3ec61Sdh155122 	char		path[MAXPATHLEN];
876*f4b3ec61Sdh155122 	di_prof_t	prof = NULL;
877*f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
878*f4b3ec61Sdh155122 	dladm_status_t	status;
879*f4b3ec61Sdh155122 
880*f4b3ec61Sdh155122 	if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
881*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
882*f4b3ec61Sdh155122 	if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
883*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
884*f4b3ec61Sdh155122 	if (di_prof_init(path, &prof) != 0)
885*f4b3ec61Sdh155122 		return (dladm_errno2status(errno));
886*f4b3ec61Sdh155122 
887*f4b3ec61Sdh155122 	status = DLADM_STATUS_OK;
888*f4b3ec61Sdh155122 	if (di_prof_add_exclude(prof, link) != 0) {
889*f4b3ec61Sdh155122 		status = dladm_errno2status(errno);
890*f4b3ec61Sdh155122 		goto cleanup;
891*f4b3ec61Sdh155122 	}
892*f4b3ec61Sdh155122 	if (di_prof_commit(prof) != 0)
893*f4b3ec61Sdh155122 		status = dladm_errno2status(errno);
894*f4b3ec61Sdh155122 cleanup:
895*f4b3ec61Sdh155122 	if (prof)
896*f4b3ec61Sdh155122 		di_prof_fini(prof);
897*f4b3ec61Sdh155122 
898*f4b3ec61Sdh155122 	return (status);
899*f4b3ec61Sdh155122 }
900*f4b3ec61Sdh155122 
901*f4b3ec61Sdh155122 static dladm_status_t
902*f4b3ec61Sdh155122 do_get_zone(const char *link, char **prop_val, uint_t *val_cnt)
903*f4b3ec61Sdh155122 {
904*f4b3ec61Sdh155122 	char		zone_name[ZONENAME_MAX];
905*f4b3ec61Sdh155122 	zoneid_t	zid;
906*f4b3ec61Sdh155122 	dladm_status_t	status;
907*f4b3ec61Sdh155122 
908*f4b3ec61Sdh155122 	status = i_dladm_get_zoneid(link, &zid);
909*f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
910*f4b3ec61Sdh155122 		return (status);
911*f4b3ec61Sdh155122 
912*f4b3ec61Sdh155122 	*val_cnt = 1;
913*f4b3ec61Sdh155122 	if (zid != GLOBAL_ZONEID) {
914*f4b3ec61Sdh155122 		if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
915*f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
916*f4b3ec61Sdh155122 
917*f4b3ec61Sdh155122 		(void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
918*f4b3ec61Sdh155122 	} else {
919*f4b3ec61Sdh155122 		*prop_val[0] = '\0';
920*f4b3ec61Sdh155122 	}
921*f4b3ec61Sdh155122 
922*f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
923*f4b3ec61Sdh155122 }
924*f4b3ec61Sdh155122 
925*f4b3ec61Sdh155122 static dladm_status_t
926*f4b3ec61Sdh155122 do_set_zone(const char *link, val_desc_t *vdp, uint_t val_cnt)
927*f4b3ec61Sdh155122 {
928*f4b3ec61Sdh155122 	dladm_status_t	status;
929*f4b3ec61Sdh155122 	zoneid_t	zid_old, zid_new;
930*f4b3ec61Sdh155122 	char		buff[IF_NAMESIZE + 1];
931*f4b3ec61Sdh155122 	struct stat	st;
932*f4b3ec61Sdh155122 
933*f4b3ec61Sdh155122 	if (val_cnt != 1)
934*f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
935*f4b3ec61Sdh155122 
936*f4b3ec61Sdh155122 	status = i_dladm_get_zoneid(link, &zid_old);
937*f4b3ec61Sdh155122 	if (status != DLADM_STATUS_OK)
938*f4b3ec61Sdh155122 		return (status);
939*f4b3ec61Sdh155122 
940*f4b3ec61Sdh155122 	/* Do nothing if setting to current value */
941*f4b3ec61Sdh155122 	zid_new = (zoneid_t)vdp->vd_val;
942*f4b3ec61Sdh155122 	if (zid_new == zid_old)
943*f4b3ec61Sdh155122 		return (DLADM_STATUS_OK);
944*f4b3ec61Sdh155122 
945*f4b3ec61Sdh155122 	/* Do a stat to get the vlan created by MAC, if it's not there */
946*f4b3ec61Sdh155122 	(void) strcpy(buff, "/dev/");
947*f4b3ec61Sdh155122 	(void) strlcat(buff, link, IF_NAMESIZE);
948*f4b3ec61Sdh155122 	(void) stat(buff, &st);
949*f4b3ec61Sdh155122 
950*f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID) {
951*f4b3ec61Sdh155122 		if (dladm_rele_link(link, GLOBAL_ZONEID, B_TRUE) < 0)
952*f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
953*f4b3ec61Sdh155122 
954*f4b3ec61Sdh155122 		if (zone_remove_datalink(zid_old, (char *)link) != 0 &&
955*f4b3ec61Sdh155122 		    errno != ENXIO) {
956*f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
957*f4b3ec61Sdh155122 			goto rollback1;
958*f4b3ec61Sdh155122 		}
959*f4b3ec61Sdh155122 
960*f4b3ec61Sdh155122 		status = i_dladm_remove_deventry(zid_old, link);
961*f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
962*f4b3ec61Sdh155122 			goto rollback2;
963*f4b3ec61Sdh155122 	}
964*f4b3ec61Sdh155122 
965*f4b3ec61Sdh155122 	if (zid_new != GLOBAL_ZONEID) {
966*f4b3ec61Sdh155122 		if (zone_add_datalink(zid_new, (char *)link) != 0) {
967*f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
968*f4b3ec61Sdh155122 			goto rollback3;
969*f4b3ec61Sdh155122 		}
970*f4b3ec61Sdh155122 
971*f4b3ec61Sdh155122 		if (dladm_hold_link(link, zid_new, B_TRUE) < 0) {
972*f4b3ec61Sdh155122 			(void) zone_remove_datalink(zid_new, (char *)link);
973*f4b3ec61Sdh155122 			status = dladm_errno2status(errno);
974*f4b3ec61Sdh155122 			goto rollback3;
975*f4b3ec61Sdh155122 		}
976*f4b3ec61Sdh155122 
977*f4b3ec61Sdh155122 		status = i_dladm_add_deventry(zid_new, link);
978*f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK) {
979*f4b3ec61Sdh155122 			(void) dladm_rele_link(link, GLOBAL_ZONEID, B_FALSE);
980*f4b3ec61Sdh155122 			(void) zone_remove_datalink(zid_new, (char *)link);
981*f4b3ec61Sdh155122 			goto rollback3;
982*f4b3ec61Sdh155122 		}
983*f4b3ec61Sdh155122 	}
984*f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
985*f4b3ec61Sdh155122 
986*f4b3ec61Sdh155122 rollback3:
987*f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID)
988*f4b3ec61Sdh155122 		(void) i_dladm_add_deventry(zid_old, link);
989*f4b3ec61Sdh155122 rollback2:
990*f4b3ec61Sdh155122 	if (zid_old != GLOBAL_ZONEID)
991*f4b3ec61Sdh155122 		(void) zone_add_datalink(zid_old, (char *)link);
992*f4b3ec61Sdh155122 rollback1:
993*f4b3ec61Sdh155122 	(void) dladm_hold_link(link, zid_old, B_FALSE);
994*f4b3ec61Sdh155122 cleanexit:
995*f4b3ec61Sdh155122 	return (status);
996*f4b3ec61Sdh155122 }
997*f4b3ec61Sdh155122 
998*f4b3ec61Sdh155122 /* ARGSUSED */
999*f4b3ec61Sdh155122 static dladm_status_t
1000*f4b3ec61Sdh155122 do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
1001*f4b3ec61Sdh155122     val_desc_t **vdpp)
1002*f4b3ec61Sdh155122 {
1003*f4b3ec61Sdh155122 	zoneid_t 	zid;
1004*f4b3ec61Sdh155122 	val_desc_t	*vdp = NULL;
1005*f4b3ec61Sdh155122 
1006*f4b3ec61Sdh155122 	if (val_cnt != 1)
1007*f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVALCNT);
1008*f4b3ec61Sdh155122 
1009*f4b3ec61Sdh155122 	if ((zid = getzoneidbyname(*prop_val)) == -1)
1010*f4b3ec61Sdh155122 		return (DLADM_STATUS_BADVAL);
1011*f4b3ec61Sdh155122 
1012*f4b3ec61Sdh155122 	if (zid != GLOBAL_ZONEID) {
1013*f4b3ec61Sdh155122 		ushort_t	flags;
1014*f4b3ec61Sdh155122 
1015*f4b3ec61Sdh155122 		if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
1016*f4b3ec61Sdh155122 		    sizeof (flags)) < 0) {
1017*f4b3ec61Sdh155122 			return (dladm_errno2status(errno));
1018*f4b3ec61Sdh155122 		}
1019*f4b3ec61Sdh155122 
1020*f4b3ec61Sdh155122 		if (!(flags & ZF_NET_EXCL)) {
1021*f4b3ec61Sdh155122 			return (DLADM_STATUS_BADVAL);
1022*f4b3ec61Sdh155122 		}
1023*f4b3ec61Sdh155122 	}
1024*f4b3ec61Sdh155122 
1025*f4b3ec61Sdh155122 	vdp = malloc(sizeof (val_desc_t));
1026*f4b3ec61Sdh155122 	if (vdp == NULL)
1027*f4b3ec61Sdh155122 		return (DLADM_STATUS_NOMEM);
1028*f4b3ec61Sdh155122 
1029*f4b3ec61Sdh155122 	vdp->vd_val = (void *)zid;
1030*f4b3ec61Sdh155122 	*vdpp = vdp;
1031*f4b3ec61Sdh155122 	return (DLADM_STATUS_OK);
1032*f4b3ec61Sdh155122 }
1033*f4b3ec61Sdh155122 
1034*f4b3ec61Sdh155122 static dladm_status_t
1035*f4b3ec61Sdh155122 i_dladm_get_prop_temp(const char *link, dladm_prop_type_t type,
1036*f4b3ec61Sdh155122     const char *prop_name, char **prop_val, uint_t *val_cntp)
1037*f4b3ec61Sdh155122 {
1038*f4b3ec61Sdh155122 	int 		i;
1039*f4b3ec61Sdh155122 	dladm_status_t	status;
1040*f4b3ec61Sdh155122 	uint_t		cnt;
1041*f4b3ec61Sdh155122 	prop_desc_t	*pdp;
1042*f4b3ec61Sdh155122 
1043*f4b3ec61Sdh155122 	if (link == NULL || prop_name == NULL || prop_val == NULL ||
1044*f4b3ec61Sdh155122 	    val_cntp == NULL || *val_cntp == 0)
1045*f4b3ec61Sdh155122 		return (DLADM_STATUS_BADARG);
1046*f4b3ec61Sdh155122 
1047*f4b3ec61Sdh155122 	for (i = 0; i < MAX_PROPS; i++)
1048*f4b3ec61Sdh155122 		if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
1049*f4b3ec61Sdh155122 			break;
1050*f4b3ec61Sdh155122 
1051*f4b3ec61Sdh155122 	if (i == MAX_PROPS)
1052*f4b3ec61Sdh155122 		return (DLADM_STATUS_NOTFOUND);
1053*f4b3ec61Sdh155122 
1054*f4b3ec61Sdh155122 	pdp = &prop_table[i];
1055*f4b3ec61Sdh155122 	status = DLADM_STATUS_OK;
1056*f4b3ec61Sdh155122 
1057*f4b3ec61Sdh155122 	switch (type) {
1058*f4b3ec61Sdh155122 	case DLADM_PROP_VAL_CURRENT:
1059*f4b3ec61Sdh155122 		status = pdp->pd_get(link, prop_val, val_cntp);
1060*f4b3ec61Sdh155122 		break;
1061*f4b3ec61Sdh155122 	case DLADM_PROP_VAL_DEFAULT:
1062*f4b3ec61Sdh155122 		if (pdp->pd_defval.vd_name == NULL) {
1063*f4b3ec61Sdh155122 			status = DLADM_STATUS_NOTSUP;
1064*f4b3ec61Sdh155122 			break;
1065*f4b3ec61Sdh155122 		}
1066*f4b3ec61Sdh155122 		(void) strcpy(*prop_val, pdp->pd_defval.vd_name);
1067*f4b3ec61Sdh155122 		*val_cntp = 1;
1068*f4b3ec61Sdh155122 		break;
1069*f4b3ec61Sdh155122 
1070*f4b3ec61Sdh155122 	case DLADM_PROP_VAL_MODIFIABLE:
1071*f4b3ec61Sdh155122 		if (pdp->pd_getmod != NULL) {
1072*f4b3ec61Sdh155122 			status = pdp->pd_getmod(link, prop_val, val_cntp);
1073*f4b3ec61Sdh155122 			break;
1074*f4b3ec61Sdh155122 		}
1075*f4b3ec61Sdh155122 		cnt = pdp->pd_nmodval;
1076*f4b3ec61Sdh155122 		if (cnt == 0) {
1077*f4b3ec61Sdh155122 			status = DLADM_STATUS_NOTSUP;
1078*f4b3ec61Sdh155122 		} else if (cnt > *val_cntp) {
1079*f4b3ec61Sdh155122 			status = DLADM_STATUS_TOOSMALL;
1080*f4b3ec61Sdh155122 		} else {
1081*f4b3ec61Sdh155122 			for (i = 0; i < cnt; i++) {
1082*f4b3ec61Sdh155122 				(void) strcpy(prop_val[i],
1083*f4b3ec61Sdh155122 				    pdp->pd_modval[i].vd_name);
1084*f4b3ec61Sdh155122 			}
1085*f4b3ec61Sdh155122 			*val_cntp = cnt;
1086*f4b3ec61Sdh155122 		}
1087*f4b3ec61Sdh155122 		break;
1088*f4b3ec61Sdh155122 	default:
1089*f4b3ec61Sdh155122 		status = DLADM_STATUS_BADARG;
1090*f4b3ec61Sdh155122 		break;
1091*f4b3ec61Sdh155122 	}
1092*f4b3ec61Sdh155122 
1093*f4b3ec61Sdh155122 	return (status);
1094*f4b3ec61Sdh155122 }
1095*f4b3ec61Sdh155122 
1096*f4b3ec61Sdh155122 static dladm_status_t
1097*f4b3ec61Sdh155122 i_dladm_set_one_prop_temp(const char *link, prop_desc_t *pdp, char **prop_val,
1098*f4b3ec61Sdh155122     uint_t val_cnt, uint_t flags)
1099*f4b3ec61Sdh155122 {
1100*f4b3ec61Sdh155122 	dladm_status_t	status;
1101*f4b3ec61Sdh155122 	val_desc_t	*vdp = NULL;
1102*f4b3ec61Sdh155122 	uint_t		cnt;
1103*f4b3ec61Sdh155122 
1104*f4b3ec61Sdh155122 	if (pdp->pd_temponly && (flags & DLADM_OPT_PERSIST) != 0)
1105*f4b3ec61Sdh155122 		return (DLADM_STATUS_TEMPONLY);
1106*f4b3ec61Sdh155122 
1107*f4b3ec61Sdh155122 	if (pdp->pd_set == NULL)
1108*f4b3ec61Sdh155122 		return (DLADM_STATUS_PROPRDONLY);
1109*f4b3ec61Sdh155122 
1110*f4b3ec61Sdh155122 	if (prop_val != NULL) {
1111*f4b3ec61Sdh155122 		if (pdp->pd_check != NULL)
1112*f4b3ec61Sdh155122 			status = pdp->pd_check(pdp, prop_val, val_cnt, &vdp);
1113*f4b3ec61Sdh155122 		else
1114*f4b3ec61Sdh155122 			status = DLADM_STATUS_BADARG;
1115*f4b3ec61Sdh155122 
1116*f4b3ec61Sdh155122 		if (status != DLADM_STATUS_OK)
1117*f4b3ec61Sdh155122 			return (status);
1118*f4b3ec61Sdh155122 
1119*f4b3ec61Sdh155122 		cnt = val_cnt;
1120*f4b3ec61Sdh155122 	} else {
1121*f4b3ec61Sdh155122 		if (pdp->pd_defval.vd_name == NULL)
1122*f4b3ec61Sdh155122 			return (DLADM_STATUS_NOTSUP);
1123*f4b3ec61Sdh155122 
1124*f4b3ec61Sdh155122 		if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
1125*f4b3ec61Sdh155122 			return (DLADM_STATUS_NOMEM);
1126*f4b3ec61Sdh155122 
1127*f4b3ec61Sdh155122 		(void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t));
1128*f4b3ec61Sdh155122 		cnt = 1;
1129*f4b3ec61Sdh155122 	}
1130*f4b3ec61Sdh155122 
1131*f4b3ec61Sdh155122 	status = pdp->pd_set(link, vdp, cnt);
1132*f4b3ec61Sdh155122 
1133*f4b3ec61Sdh155122 	free(vdp);
1134*f4b3ec61Sdh155122 	return (status);
1135*f4b3ec61Sdh155122 }
1136*f4b3ec61Sdh155122 
1137*f4b3ec61Sdh155122 static dladm_status_t
1138*f4b3ec61Sdh155122 i_dladm_set_prop_temp(const char *link, const char *prop_name, char **prop_val,
1139*f4b3ec61Sdh155122     uint_t val_cnt, uint_t flags, char **errprop)
1140*f4b3ec61Sdh155122 {
1141*f4b3ec61Sdh155122 	int 		i;
1142*f4b3ec61Sdh155122 	dladm_status_t	status = DLADM_STATUS_OK;
1143*f4b3ec61Sdh155122 	boolean_t	found = B_FALSE;
1144*f4b3ec61Sdh155122 
1145*f4b3ec61Sdh155122 	for (i = 0; i < MAX_PROPS; i++) {
1146*f4b3ec61Sdh155122 		prop_desc_t	*pdp = &prop_table[i];
1147*f4b3ec61Sdh155122 		dladm_status_t	s;
1148*f4b3ec61Sdh155122 
1149*f4b3ec61Sdh155122 		if (prop_name != NULL &&
1150*f4b3ec61Sdh155122 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
1151*f4b3ec61Sdh155122 			continue;
1152*f4b3ec61Sdh155122 
1153*f4b3ec61Sdh155122 		found = B_TRUE;
1154*f4b3ec61Sdh155122 		s = i_dladm_set_one_prop_temp(link, pdp, prop_val, val_cnt,
1155*f4b3ec61Sdh155122 		    flags);
1156*f4b3ec61Sdh155122 
1157*f4b3ec61Sdh155122 		if (prop_name != NULL) {
1158*f4b3ec61Sdh155122 			status = s;
1159*f4b3ec61Sdh155122 			break;
1160*f4b3ec61Sdh155122 		} else {
1161*f4b3ec61Sdh155122 			if (s != DLADM_STATUS_OK &&
1162*f4b3ec61Sdh155122 			    s != DLADM_STATUS_NOTSUP) {
1163*f4b3ec61Sdh155122 				if (errprop != NULL)
1164*f4b3ec61Sdh155122 					*errprop = pdp->pd_name;
1165*f4b3ec61Sdh155122 				status = s;
1166*f4b3ec61Sdh155122 				break;
1167*f4b3ec61Sdh155122 			}
1168*f4b3ec61Sdh155122 		}
1169*f4b3ec61Sdh155122 	}
1170*f4b3ec61Sdh155122 
1171*f4b3ec61Sdh155122 	if (!found)
1172*f4b3ec61Sdh155122 		status = DLADM_STATUS_NOTFOUND;
1173*f4b3ec61Sdh155122 
1174*f4b3ec61Sdh155122 	return (status);
1175*f4b3ec61Sdh155122 }
1176*f4b3ec61Sdh155122 
1177*f4b3ec61Sdh155122 static boolean_t
1178*f4b3ec61Sdh155122 i_dladm_is_prop_temponly(const char *prop_name, char **errprop)
1179*f4b3ec61Sdh155122 {
1180*f4b3ec61Sdh155122 	int 		i;
1181*f4b3ec61Sdh155122 
1182*f4b3ec61Sdh155122 	for (i = 0; i < MAX_PROPS; i++) {
1183*f4b3ec61Sdh155122 		prop_desc_t	*pdp = &prop_table[i];
1184*f4b3ec61Sdh155122 
1185*f4b3ec61Sdh155122 		if (prop_name != NULL &&
1186*f4b3ec61Sdh155122 		    (strcasecmp(prop_name, pdp->pd_name) != 0))
1187*f4b3ec61Sdh155122 			continue;
1188*f4b3ec61Sdh155122 
1189*f4b3ec61Sdh155122 		if (errprop != NULL)
1190*f4b3ec61Sdh155122 			*errprop = pdp->pd_name;
1191*f4b3ec61Sdh155122 
1192*f4b3ec61Sdh155122 		if (pdp->pd_temponly)
1193*f4b3ec61Sdh155122 			return (B_TRUE);
1194*f4b3ec61Sdh155122 	}
1195*f4b3ec61Sdh155122 
1196*f4b3ec61Sdh155122 	return (B_FALSE);
1197*f4b3ec61Sdh155122 }
1198*f4b3ec61Sdh155122 
1199*f4b3ec61Sdh155122 boolean_t
1200*f4b3ec61Sdh155122 dladm_is_prop_temponly(const char *prop_name, char **errprop)
1201*f4b3ec61Sdh155122 {
1202*f4b3ec61Sdh155122 	return (i_dladm_is_prop_temponly(prop_name, errprop));
1203*f4b3ec61Sdh155122 }
1204