xref: /titanic_44/usr/src/lib/libdladm/common/linkprop.c (revision 0ba2cbe97e0678a691742f98d2532caed0a2c4aa)
1*0ba2cbe9Sxc151355 /*
2*0ba2cbe9Sxc151355  * CDDL HEADER START
3*0ba2cbe9Sxc151355  *
4*0ba2cbe9Sxc151355  * The contents of this file are subject to the terms of the
5*0ba2cbe9Sxc151355  * Common Development and Distribution License (the "License").
6*0ba2cbe9Sxc151355  * You may not use this file except in compliance with the License.
7*0ba2cbe9Sxc151355  *
8*0ba2cbe9Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*0ba2cbe9Sxc151355  * or http://www.opensolaris.org/os/licensing.
10*0ba2cbe9Sxc151355  * See the License for the specific language governing permissions
11*0ba2cbe9Sxc151355  * and limitations under the License.
12*0ba2cbe9Sxc151355  *
13*0ba2cbe9Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
14*0ba2cbe9Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*0ba2cbe9Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
16*0ba2cbe9Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
17*0ba2cbe9Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
18*0ba2cbe9Sxc151355  *
19*0ba2cbe9Sxc151355  * CDDL HEADER END
20*0ba2cbe9Sxc151355  */
21*0ba2cbe9Sxc151355 /*
22*0ba2cbe9Sxc151355  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*0ba2cbe9Sxc151355  * Use is subject to license terms.
24*0ba2cbe9Sxc151355  */
25*0ba2cbe9Sxc151355 
26*0ba2cbe9Sxc151355 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0ba2cbe9Sxc151355 
28*0ba2cbe9Sxc151355 #include <stdlib.h>
29*0ba2cbe9Sxc151355 #include <strings.h>
30*0ba2cbe9Sxc151355 #include <errno.h>
31*0ba2cbe9Sxc151355 #include <ctype.h>
32*0ba2cbe9Sxc151355 #include <sys/stat.h>
33*0ba2cbe9Sxc151355 #include <libwladm.h>
34*0ba2cbe9Sxc151355 #include <libdladm_impl.h>
35*0ba2cbe9Sxc151355 
36*0ba2cbe9Sxc151355 static dladm_status_t	i_dladm_set_prop_db(const char *, const char *,
37*0ba2cbe9Sxc151355 			    char **, uint_t);
38*0ba2cbe9Sxc151355 static dladm_status_t	i_dladm_get_prop_db(const char *, const char *,
39*0ba2cbe9Sxc151355 			    char **, uint_t *);
40*0ba2cbe9Sxc151355 
41*0ba2cbe9Sxc151355 /*
42*0ba2cbe9Sxc151355  * Convert a wladm_status_t to a dladm_status_t. This is used by wrappers
43*0ba2cbe9Sxc151355  * to libwladm routines (e.g. dladm_set_prop()). Note that the mapping is
44*0ba2cbe9Sxc151355  * not 1-1; whenever possible we try to look for an error code with a
45*0ba2cbe9Sxc151355  * similar meaning. Error codes with no suitable counterpart in libdladm
46*0ba2cbe9Sxc151355  * will be mapped to DLADM_STATUS_FAILED. Clients who require clearer error
47*0ba2cbe9Sxc151355  * reporting should use libwladm directly.
48*0ba2cbe9Sxc151355  */
49*0ba2cbe9Sxc151355 static dladm_status_t
50*0ba2cbe9Sxc151355 dladm_wladmstatus2status(wladm_status_t wstatus)
51*0ba2cbe9Sxc151355 {
52*0ba2cbe9Sxc151355 	switch (wstatus) {
53*0ba2cbe9Sxc151355 	case WLADM_STATUS_OK:
54*0ba2cbe9Sxc151355 		return (DLADM_STATUS_OK);
55*0ba2cbe9Sxc151355 	case WLADM_STATUS_FAILED:
56*0ba2cbe9Sxc151355 		return (DLADM_STATUS_FAILED);
57*0ba2cbe9Sxc151355 	case WLADM_STATUS_NOTSUP:
58*0ba2cbe9Sxc151355 		return (DLADM_STATUS_NOTSUP);
59*0ba2cbe9Sxc151355 	case WLADM_STATUS_BADARG:
60*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
61*0ba2cbe9Sxc151355 	case WLADM_STATUS_NOTFOUND:
62*0ba2cbe9Sxc151355 		return (DLADM_STATUS_NOTFOUND);
63*0ba2cbe9Sxc151355 	case WLADM_STATUS_BADVAL:
64*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADVAL);
65*0ba2cbe9Sxc151355 	case WLADM_STATUS_LINKINVAL:
66*0ba2cbe9Sxc151355 		return (DLADM_STATUS_LINKINVAL);
67*0ba2cbe9Sxc151355 	case WLADM_STATUS_NOMEM:
68*0ba2cbe9Sxc151355 		return (DLADM_STATUS_NOMEM);
69*0ba2cbe9Sxc151355 	case WLADM_STATUS_PROPRDONLY:
70*0ba2cbe9Sxc151355 		return (DLADM_STATUS_PROPRDONLY);
71*0ba2cbe9Sxc151355 	case WLADM_STATUS_TOOSMALL:
72*0ba2cbe9Sxc151355 		return (DLADM_STATUS_TOOSMALL);
73*0ba2cbe9Sxc151355 	case WLADM_STATUS_BADVALCNT:
74*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADVALCNT);
75*0ba2cbe9Sxc151355 	default:
76*0ba2cbe9Sxc151355 		return (DLADM_STATUS_FAILED);
77*0ba2cbe9Sxc151355 	}
78*0ba2cbe9Sxc151355 }
79*0ba2cbe9Sxc151355 
80*0ba2cbe9Sxc151355 dladm_status_t
81*0ba2cbe9Sxc151355 dladm_set_prop(const char *link, const char *prop_name, char **prop_val,
82*0ba2cbe9Sxc151355     uint_t val_cnt, uint_t flags)
83*0ba2cbe9Sxc151355 {
84*0ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_BADARG;
85*0ba2cbe9Sxc151355 
86*0ba2cbe9Sxc151355 	if (link == NULL || (prop_val == NULL && val_cnt > 0) ||
87*0ba2cbe9Sxc151355 	    (prop_val != NULL && val_cnt == 0) || flags == 0)
88*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
89*0ba2cbe9Sxc151355 
90*0ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_TEMP) != 0) {
91*0ba2cbe9Sxc151355 		if (wladm_is_valid(link)) {
92*0ba2cbe9Sxc151355 			status = dladm_wladmstatus2status(
93*0ba2cbe9Sxc151355 			    wladm_set_prop(link, prop_name,
94*0ba2cbe9Sxc151355 			    prop_val, val_cnt));
95*0ba2cbe9Sxc151355 		}
96*0ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK)
97*0ba2cbe9Sxc151355 			return (status);
98*0ba2cbe9Sxc151355 	}
99*0ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
100*0ba2cbe9Sxc151355 		status = i_dladm_set_prop_db(link, prop_name,
101*0ba2cbe9Sxc151355 		    prop_val, val_cnt);
102*0ba2cbe9Sxc151355 	}
103*0ba2cbe9Sxc151355 	return (status);
104*0ba2cbe9Sxc151355 }
105*0ba2cbe9Sxc151355 
106*0ba2cbe9Sxc151355 dladm_status_t
107*0ba2cbe9Sxc151355 dladm_walk_prop(const char *link, void *arg,
108*0ba2cbe9Sxc151355     boolean_t (*func)(void *, const char *))
109*0ba2cbe9Sxc151355 {
110*0ba2cbe9Sxc151355 	if (link == NULL || func == NULL)
111*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
112*0ba2cbe9Sxc151355 
113*0ba2cbe9Sxc151355 	if (wladm_is_valid(link)) {
114*0ba2cbe9Sxc151355 		return (dladm_wladmstatus2status(
115*0ba2cbe9Sxc151355 		    wladm_walk_prop(link, arg, func)));
116*0ba2cbe9Sxc151355 	}
117*0ba2cbe9Sxc151355 	return (DLADM_STATUS_BADARG);
118*0ba2cbe9Sxc151355 }
119*0ba2cbe9Sxc151355 
120*0ba2cbe9Sxc151355 dladm_status_t
121*0ba2cbe9Sxc151355 dladm_get_prop(const char *link, dladm_prop_type_t type,
122*0ba2cbe9Sxc151355     const char *prop_name, char **prop_val, uint_t *val_cntp)
123*0ba2cbe9Sxc151355 {
124*0ba2cbe9Sxc151355 	if (link == NULL || prop_name == NULL || prop_val == NULL ||
125*0ba2cbe9Sxc151355 	    val_cntp == NULL || *val_cntp == 0)
126*0ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
127*0ba2cbe9Sxc151355 
128*0ba2cbe9Sxc151355 	if (type == DLADM_PROP_VAL_PERSISTENT) {
129*0ba2cbe9Sxc151355 		return (i_dladm_get_prop_db(link, prop_name,
130*0ba2cbe9Sxc151355 		    prop_val, val_cntp));
131*0ba2cbe9Sxc151355 	}
132*0ba2cbe9Sxc151355 
133*0ba2cbe9Sxc151355 	if (wladm_is_valid(link)) {
134*0ba2cbe9Sxc151355 		wladm_prop_type_t	wtype;
135*0ba2cbe9Sxc151355 
136*0ba2cbe9Sxc151355 		switch (type) {
137*0ba2cbe9Sxc151355 		case DLADM_PROP_VAL_CURRENT:
138*0ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_CURRENT;
139*0ba2cbe9Sxc151355 			break;
140*0ba2cbe9Sxc151355 		case DLADM_PROP_VAL_DEFAULT:
141*0ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_DEFAULT;
142*0ba2cbe9Sxc151355 			break;
143*0ba2cbe9Sxc151355 		case DLADM_PROP_VAL_MODIFIABLE:
144*0ba2cbe9Sxc151355 			wtype = WLADM_PROP_VAL_MODIFIABLE;
145*0ba2cbe9Sxc151355 			break;
146*0ba2cbe9Sxc151355 		default:
147*0ba2cbe9Sxc151355 			return (DLADM_STATUS_BADARG);
148*0ba2cbe9Sxc151355 		}
149*0ba2cbe9Sxc151355 
150*0ba2cbe9Sxc151355 		return (dladm_wladmstatus2status(
151*0ba2cbe9Sxc151355 		    wladm_get_prop(link, wtype, prop_name,
152*0ba2cbe9Sxc151355 		    prop_val, val_cntp)));
153*0ba2cbe9Sxc151355 	}
154*0ba2cbe9Sxc151355 	return (DLADM_STATUS_BADARG);
155*0ba2cbe9Sxc151355 }
156*0ba2cbe9Sxc151355 
157*0ba2cbe9Sxc151355 /*
158*0ba2cbe9Sxc151355  * Data structures used for implementing persistent link properties
159*0ba2cbe9Sxc151355  */
160*0ba2cbe9Sxc151355 typedef struct linkprop_val {
161*0ba2cbe9Sxc151355 	const char		*lv_name;
162*0ba2cbe9Sxc151355 	struct linkprop_val	*lv_nextval;
163*0ba2cbe9Sxc151355 } linkprop_val_t;
164*0ba2cbe9Sxc151355 
165*0ba2cbe9Sxc151355 typedef struct linkprop_info {
166*0ba2cbe9Sxc151355 	const char		*li_name;
167*0ba2cbe9Sxc151355 	struct linkprop_info	*li_nextprop;
168*0ba2cbe9Sxc151355 	struct linkprop_val	*li_val;
169*0ba2cbe9Sxc151355 } linkprop_info_t;
170*0ba2cbe9Sxc151355 
171*0ba2cbe9Sxc151355 typedef struct linkprop_db_state	linkprop_db_state_t;
172*0ba2cbe9Sxc151355 
173*0ba2cbe9Sxc151355 typedef boolean_t (*linkprop_db_op_t)(linkprop_db_state_t *,
174*0ba2cbe9Sxc151355     char *, linkprop_info_t *, dladm_status_t *);
175*0ba2cbe9Sxc151355 
176*0ba2cbe9Sxc151355 struct linkprop_db_state {
177*0ba2cbe9Sxc151355 	linkprop_db_op_t	ls_op;
178*0ba2cbe9Sxc151355 	const char		*ls_link;
179*0ba2cbe9Sxc151355 	const char		*ls_propname;
180*0ba2cbe9Sxc151355 	char			**ls_propval;
181*0ba2cbe9Sxc151355 	uint_t			*ls_valcntp;
182*0ba2cbe9Sxc151355 };
183*0ba2cbe9Sxc151355 
184*0ba2cbe9Sxc151355 static void
185*0ba2cbe9Sxc151355 free_linkprops(linkprop_info_t *lip)
186*0ba2cbe9Sxc151355 {
187*0ba2cbe9Sxc151355 	linkprop_info_t	*lip_next;
188*0ba2cbe9Sxc151355 	linkprop_val_t	*lvp, *lvp_next;
189*0ba2cbe9Sxc151355 
190*0ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip_next) {
191*0ba2cbe9Sxc151355 		lip_next = lip->li_nextprop;
192*0ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
193*0ba2cbe9Sxc151355 			lvp_next = lvp->lv_nextval;
194*0ba2cbe9Sxc151355 			free(lvp);
195*0ba2cbe9Sxc151355 		}
196*0ba2cbe9Sxc151355 		free(lip);
197*0ba2cbe9Sxc151355 	}
198*0ba2cbe9Sxc151355 }
199*0ba2cbe9Sxc151355 
200*0ba2cbe9Sxc151355 /*
201*0ba2cbe9Sxc151355  * Generate an entry in the link property database.
202*0ba2cbe9Sxc151355  * Each entry has this format:
203*0ba2cbe9Sxc151355  * <linkname>	<prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
204*0ba2cbe9Sxc151355  */
205*0ba2cbe9Sxc151355 static void
206*0ba2cbe9Sxc151355 generate_linkprop_line(linkprop_db_state_t *lsp, char *buf,
207*0ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
208*0ba2cbe9Sxc151355 {
209*0ba2cbe9Sxc151355 	char		tmpbuf[MAXLINELEN];
210*0ba2cbe9Sxc151355 	char		*ptr, *lim = tmpbuf + MAXLINELEN;
211*0ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
212*0ba2cbe9Sxc151355 	linkprop_val_t	*lvp = NULL;
213*0ba2cbe9Sxc151355 
214*0ba2cbe9Sxc151355 	/*
215*0ba2cbe9Sxc151355 	 * Delete line if there are no properties left.
216*0ba2cbe9Sxc151355 	 */
217*0ba2cbe9Sxc151355 	if (lip == NULL ||
218*0ba2cbe9Sxc151355 	    (lip->li_val == NULL && lip->li_nextprop == NULL)) {
219*0ba2cbe9Sxc151355 		buf[0] = '\0';
220*0ba2cbe9Sxc151355 		return;
221*0ba2cbe9Sxc151355 	}
222*0ba2cbe9Sxc151355 	ptr = tmpbuf;
223*0ba2cbe9Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", lsp->ls_link);
224*0ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
225*0ba2cbe9Sxc151355 		/*
226*0ba2cbe9Sxc151355 		 * Skip properties without values.
227*0ba2cbe9Sxc151355 		 */
228*0ba2cbe9Sxc151355 		if (lip->li_val == NULL)
229*0ba2cbe9Sxc151355 			continue;
230*0ba2cbe9Sxc151355 
231*0ba2cbe9Sxc151355 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s=", lip->li_name);
232*0ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
233*0ba2cbe9Sxc151355 			ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s%c",
234*0ba2cbe9Sxc151355 			    lvp->lv_name,
235*0ba2cbe9Sxc151355 			    ((lvp->lv_nextval == NULL) ? ';' : ','));
236*0ba2cbe9Sxc151355 		}
237*0ba2cbe9Sxc151355 	}
238*0ba2cbe9Sxc151355 	if (ptr > lim) {
239*0ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
240*0ba2cbe9Sxc151355 		return;
241*0ba2cbe9Sxc151355 	}
242*0ba2cbe9Sxc151355 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
243*0ba2cbe9Sxc151355 }
244*0ba2cbe9Sxc151355 
245*0ba2cbe9Sxc151355 /*
246*0ba2cbe9Sxc151355  * This function is used to update or create an entry in the persistent db.
247*0ba2cbe9Sxc151355  * process_linkprop_db() will first scan the db for an entry matching the
248*0ba2cbe9Sxc151355  * specified link. If a match is found, this function is invoked with the
249*0ba2cbe9Sxc151355  * entry's contents (buf) and its linked-list representation (listp). lsp
250*0ba2cbe9Sxc151355  * holds the name and values of the property to be added or updated; this
251*0ba2cbe9Sxc151355  * information will be merged with listp. Subsequently, an updated entry
252*0ba2cbe9Sxc151355  * will be written to buf, which will in turn be written to disk by
253*0ba2cbe9Sxc151355  * process_linkprop_db(). If no entry matches the specified link, listp
254*0ba2cbe9Sxc151355  * will be NULL; a new entry will be generated in this case and it will
255*0ba2cbe9Sxc151355  * contain only the property information in lsp.
256*0ba2cbe9Sxc151355  */
257*0ba2cbe9Sxc151355 static boolean_t
258*0ba2cbe9Sxc151355 process_linkprop_set(linkprop_db_state_t *lsp, char *buf,
259*0ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
260*0ba2cbe9Sxc151355 {
261*0ba2cbe9Sxc151355 	dladm_status_t	status;
262*0ba2cbe9Sxc151355 	linkprop_info_t	*lastp = NULL, *lip = listp, *nlip = NULL;
263*0ba2cbe9Sxc151355 	linkprop_val_t	**lvpp;
264*0ba2cbe9Sxc151355 	int		i;
265*0ba2cbe9Sxc151355 
266*0ba2cbe9Sxc151355 	if (lsp->ls_propname == NULL) {
267*0ba2cbe9Sxc151355 		buf[0] = '\0';
268*0ba2cbe9Sxc151355 		return (B_FALSE);
269*0ba2cbe9Sxc151355 	}
270*0ba2cbe9Sxc151355 
271*0ba2cbe9Sxc151355 	/*
272*0ba2cbe9Sxc151355 	 * Find the linkprop we want to change.
273*0ba2cbe9Sxc151355 	 */
274*0ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
275*0ba2cbe9Sxc151355 		if (strcmp(lip->li_name, lsp->ls_propname) == 0)
276*0ba2cbe9Sxc151355 			break;
277*0ba2cbe9Sxc151355 
278*0ba2cbe9Sxc151355 		lastp = lip;
279*0ba2cbe9Sxc151355 	}
280*0ba2cbe9Sxc151355 
281*0ba2cbe9Sxc151355 	if (lip == NULL) {
282*0ba2cbe9Sxc151355 		/*
283*0ba2cbe9Sxc151355 		 * If the linkprop is not found, append it to the list.
284*0ba2cbe9Sxc151355 		 */
285*0ba2cbe9Sxc151355 		if ((nlip = malloc(sizeof (linkprop_info_t))) == NULL) {
286*0ba2cbe9Sxc151355 			status = DLADM_STATUS_NOMEM;
287*0ba2cbe9Sxc151355 			goto fail;
288*0ba2cbe9Sxc151355 		}
289*0ba2cbe9Sxc151355 		/*
290*0ba2cbe9Sxc151355 		 * nlip will need to be freed later if there is no list to
291*0ba2cbe9Sxc151355 		 * append to.
292*0ba2cbe9Sxc151355 		 */
293*0ba2cbe9Sxc151355 		if (lastp != NULL)
294*0ba2cbe9Sxc151355 			lastp->li_nextprop = nlip;
295*0ba2cbe9Sxc151355 		nlip->li_name = lsp->ls_propname;
296*0ba2cbe9Sxc151355 		nlip->li_nextprop = NULL;
297*0ba2cbe9Sxc151355 		nlip->li_val = NULL;
298*0ba2cbe9Sxc151355 		lvpp = &nlip->li_val;
299*0ba2cbe9Sxc151355 	} else {
300*0ba2cbe9Sxc151355 		linkprop_val_t	*lvp, *lvp_next;
301*0ba2cbe9Sxc151355 
302*0ba2cbe9Sxc151355 		/*
303*0ba2cbe9Sxc151355 		 * If the linkprop is found, delete the existing values from it.
304*0ba2cbe9Sxc151355 		 */
305*0ba2cbe9Sxc151355 		for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
306*0ba2cbe9Sxc151355 			lvp_next = lvp->lv_nextval;
307*0ba2cbe9Sxc151355 			free(lvp);
308*0ba2cbe9Sxc151355 		}
309*0ba2cbe9Sxc151355 		lip->li_val = NULL;
310*0ba2cbe9Sxc151355 		lvpp = &lip->li_val;
311*0ba2cbe9Sxc151355 	}
312*0ba2cbe9Sxc151355 
313*0ba2cbe9Sxc151355 	/*
314*0ba2cbe9Sxc151355 	 * Fill our linkprop with the specified values.
315*0ba2cbe9Sxc151355 	 */
316*0ba2cbe9Sxc151355 	for (i = 0; i < *lsp->ls_valcntp; i++) {
317*0ba2cbe9Sxc151355 		if ((*lvpp = malloc(sizeof (linkprop_val_t))) == NULL) {
318*0ba2cbe9Sxc151355 			status = DLADM_STATUS_NOMEM;
319*0ba2cbe9Sxc151355 			goto fail;
320*0ba2cbe9Sxc151355 		}
321*0ba2cbe9Sxc151355 		(*lvpp)->lv_name = lsp->ls_propval[i];
322*0ba2cbe9Sxc151355 		(*lvpp)->lv_nextval = NULL;
323*0ba2cbe9Sxc151355 		lvpp = &(*lvpp)->lv_nextval;
324*0ba2cbe9Sxc151355 	}
325*0ba2cbe9Sxc151355 
326*0ba2cbe9Sxc151355 	if (listp != NULL) {
327*0ba2cbe9Sxc151355 		generate_linkprop_line(lsp, buf, listp, statusp);
328*0ba2cbe9Sxc151355 	} else {
329*0ba2cbe9Sxc151355 		generate_linkprop_line(lsp, buf, nlip, statusp);
330*0ba2cbe9Sxc151355 		free_linkprops(nlip);
331*0ba2cbe9Sxc151355 	}
332*0ba2cbe9Sxc151355 	return (B_FALSE);
333*0ba2cbe9Sxc151355 
334*0ba2cbe9Sxc151355 fail:
335*0ba2cbe9Sxc151355 	*statusp = status;
336*0ba2cbe9Sxc151355 	if (listp == NULL)
337*0ba2cbe9Sxc151355 		free_linkprops(nlip);
338*0ba2cbe9Sxc151355 
339*0ba2cbe9Sxc151355 	return (B_FALSE);
340*0ba2cbe9Sxc151355 }
341*0ba2cbe9Sxc151355 
342*0ba2cbe9Sxc151355 /*
343*0ba2cbe9Sxc151355  * This function is used for retrieving the values for a specific property.
344*0ba2cbe9Sxc151355  * It gets called if an entry matching the specified link exists in the db.
345*0ba2cbe9Sxc151355  * The entry is converted into a linked-list listp. This list is then scanned
346*0ba2cbe9Sxc151355  * for the specified property name; if a matching property exists, its
347*0ba2cbe9Sxc151355  * associated values are copied to the array lsp->ls_propval.
348*0ba2cbe9Sxc151355  */
349*0ba2cbe9Sxc151355 /* ARGSUSED */
350*0ba2cbe9Sxc151355 static boolean_t
351*0ba2cbe9Sxc151355 process_linkprop_get(linkprop_db_state_t *lsp, char *buf,
352*0ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
353*0ba2cbe9Sxc151355 {
354*0ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
355*0ba2cbe9Sxc151355 	linkprop_val_t	*lvp;
356*0ba2cbe9Sxc151355 	uint_t		valcnt = 0;
357*0ba2cbe9Sxc151355 
358*0ba2cbe9Sxc151355 	/*
359*0ba2cbe9Sxc151355 	 * Find the linkprop we want to get.
360*0ba2cbe9Sxc151355 	 */
361*0ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
362*0ba2cbe9Sxc151355 		if (strcmp(lip->li_name, lsp->ls_propname) == 0)
363*0ba2cbe9Sxc151355 			break;
364*0ba2cbe9Sxc151355 	}
365*0ba2cbe9Sxc151355 	if (lip == NULL) {
366*0ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_NOTFOUND;
367*0ba2cbe9Sxc151355 		return (B_FALSE);
368*0ba2cbe9Sxc151355 	}
369*0ba2cbe9Sxc151355 
370*0ba2cbe9Sxc151355 	for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
371*0ba2cbe9Sxc151355 		(void) strncpy(lsp->ls_propval[valcnt], lvp->lv_name,
372*0ba2cbe9Sxc151355 		    DLADM_PROP_VAL_MAX);
373*0ba2cbe9Sxc151355 
374*0ba2cbe9Sxc151355 		if (++valcnt >= *lsp->ls_valcntp && lvp->lv_nextval != NULL) {
375*0ba2cbe9Sxc151355 			*statusp = DLADM_STATUS_TOOSMALL;
376*0ba2cbe9Sxc151355 			return (B_FALSE);
377*0ba2cbe9Sxc151355 		}
378*0ba2cbe9Sxc151355 	}
379*0ba2cbe9Sxc151355 	/*
380*0ba2cbe9Sxc151355 	 * This function is meant to be called at most once for each call
381*0ba2cbe9Sxc151355 	 * to process_linkprop_db(). For this reason, it's ok to overwrite
382*0ba2cbe9Sxc151355 	 * the caller's valcnt array size with the actual number of values
383*0ba2cbe9Sxc151355 	 * returned.
384*0ba2cbe9Sxc151355 	 */
385*0ba2cbe9Sxc151355 	*lsp->ls_valcntp = valcnt;
386*0ba2cbe9Sxc151355 	return (B_FALSE);
387*0ba2cbe9Sxc151355 }
388*0ba2cbe9Sxc151355 
389*0ba2cbe9Sxc151355 /*
390*0ba2cbe9Sxc151355  * This is used for initializing link properties.
391*0ba2cbe9Sxc151355  * Unlike the other routines, this gets called for every entry in the
392*0ba2cbe9Sxc151355  * database. lsp->ls_link is not user-specified but instead is set to
393*0ba2cbe9Sxc151355  * the current link being processed.
394*0ba2cbe9Sxc151355  */
395*0ba2cbe9Sxc151355 /* ARGSUSED */
396*0ba2cbe9Sxc151355 static boolean_t
397*0ba2cbe9Sxc151355 process_linkprop_init(linkprop_db_state_t *lsp, char *buf,
398*0ba2cbe9Sxc151355     linkprop_info_t *listp, dladm_status_t *statusp)
399*0ba2cbe9Sxc151355 {
400*0ba2cbe9Sxc151355 	dladm_status_t	status = DLADM_STATUS_OK;
401*0ba2cbe9Sxc151355 	linkprop_info_t	*lip = listp;
402*0ba2cbe9Sxc151355 	linkprop_val_t	*lvp;
403*0ba2cbe9Sxc151355 	uint_t		valcnt, i;
404*0ba2cbe9Sxc151355 	char		**propval;
405*0ba2cbe9Sxc151355 
406*0ba2cbe9Sxc151355 	for (; lip != NULL; lip = lip->li_nextprop) {
407*0ba2cbe9Sxc151355 		/*
408*0ba2cbe9Sxc151355 		 * Construct the propval array and fill it with
409*0ba2cbe9Sxc151355 		 * values from listp.
410*0ba2cbe9Sxc151355 		 */
411*0ba2cbe9Sxc151355 		for (lvp = lip->li_val, valcnt = 0;
412*0ba2cbe9Sxc151355 		    lvp != NULL; lvp = lvp->lv_nextval, valcnt++);
413*0ba2cbe9Sxc151355 
414*0ba2cbe9Sxc151355 		propval = malloc(sizeof (char *) * valcnt);
415*0ba2cbe9Sxc151355 		if (propval == NULL) {
416*0ba2cbe9Sxc151355 			*statusp = DLADM_STATUS_NOMEM;
417*0ba2cbe9Sxc151355 			break;
418*0ba2cbe9Sxc151355 		}
419*0ba2cbe9Sxc151355 		lvp = lip->li_val;
420*0ba2cbe9Sxc151355 		for (i = 0; i < valcnt; i++, lvp = lvp->lv_nextval)
421*0ba2cbe9Sxc151355 			propval[i] = (char *)lvp->lv_name;
422*0ba2cbe9Sxc151355 
423*0ba2cbe9Sxc151355 		status = dladm_set_prop(lsp->ls_link, lip->li_name,
424*0ba2cbe9Sxc151355 		    propval, valcnt, DLADM_OPT_TEMP);
425*0ba2cbe9Sxc151355 
426*0ba2cbe9Sxc151355 		/*
427*0ba2cbe9Sxc151355 		 * We continue with initializing other properties even
428*0ba2cbe9Sxc151355 		 * after encountering an error. This error will be
429*0ba2cbe9Sxc151355 		 * propagated to the caller via 'statusp'.
430*0ba2cbe9Sxc151355 		 */
431*0ba2cbe9Sxc151355 		if (status != DLADM_STATUS_OK)
432*0ba2cbe9Sxc151355 			*statusp = status;
433*0ba2cbe9Sxc151355 
434*0ba2cbe9Sxc151355 		free(propval);
435*0ba2cbe9Sxc151355 	}
436*0ba2cbe9Sxc151355 	return (B_TRUE);
437*0ba2cbe9Sxc151355 }
438*0ba2cbe9Sxc151355 
439*0ba2cbe9Sxc151355 static int
440*0ba2cbe9Sxc151355 parse_linkprops(char *buf, linkprop_info_t **lipp)
441*0ba2cbe9Sxc151355 {
442*0ba2cbe9Sxc151355 	int			i, len;
443*0ba2cbe9Sxc151355 	char			*curr;
444*0ba2cbe9Sxc151355 	linkprop_info_t		*lip = NULL;
445*0ba2cbe9Sxc151355 	linkprop_info_t		**tailp = lipp;
446*0ba2cbe9Sxc151355 	linkprop_val_t		*lvp = NULL;
447*0ba2cbe9Sxc151355 	linkprop_val_t		**vtailp = NULL;
448*0ba2cbe9Sxc151355 
449*0ba2cbe9Sxc151355 	curr = buf;
450*0ba2cbe9Sxc151355 	len = strlen(buf);
451*0ba2cbe9Sxc151355 	for (i = 0; i < len; i++) {
452*0ba2cbe9Sxc151355 		char		c = buf[i];
453*0ba2cbe9Sxc151355 		boolean_t	match = (c == '=' || c == ',' || c == ';');
454*0ba2cbe9Sxc151355 
455*0ba2cbe9Sxc151355 		/*
456*0ba2cbe9Sxc151355 		 * Move to the next character if there is no match and
457*0ba2cbe9Sxc151355 		 * if we have not reached the last character.
458*0ba2cbe9Sxc151355 		 */
459*0ba2cbe9Sxc151355 		if (!match && i != len - 1)
460*0ba2cbe9Sxc151355 			continue;
461*0ba2cbe9Sxc151355 
462*0ba2cbe9Sxc151355 		if (match) {
463*0ba2cbe9Sxc151355 			/*
464*0ba2cbe9Sxc151355 			 * Nul-terminate the string pointed to by 'curr'.
465*0ba2cbe9Sxc151355 			 */
466*0ba2cbe9Sxc151355 			buf[i] = '\0';
467*0ba2cbe9Sxc151355 			if (*curr == '\0')
468*0ba2cbe9Sxc151355 				goto fail;
469*0ba2cbe9Sxc151355 		}
470*0ba2cbe9Sxc151355 
471*0ba2cbe9Sxc151355 		if (lip != NULL) {
472*0ba2cbe9Sxc151355 			/*
473*0ba2cbe9Sxc151355 			 * We get here after we have processed the "<prop>="
474*0ba2cbe9Sxc151355 			 * pattern. The pattern we are now interested in is
475*0ba2cbe9Sxc151355 			 * "<val0>,<val1>,...,<valn>;". For each value we
476*0ba2cbe9Sxc151355 			 * find, a linkprop_val_t will be allocated and
477*0ba2cbe9Sxc151355 			 * added to the current 'lip'.
478*0ba2cbe9Sxc151355 			 */
479*0ba2cbe9Sxc151355 			if (c == '=')
480*0ba2cbe9Sxc151355 				goto fail;
481*0ba2cbe9Sxc151355 
482*0ba2cbe9Sxc151355 			lvp = malloc(sizeof (*lvp));
483*0ba2cbe9Sxc151355 			if (lvp == NULL)
484*0ba2cbe9Sxc151355 				goto fail;
485*0ba2cbe9Sxc151355 
486*0ba2cbe9Sxc151355 			lvp->lv_name = curr;
487*0ba2cbe9Sxc151355 			lvp->lv_nextval = NULL;
488*0ba2cbe9Sxc151355 			*vtailp = lvp;
489*0ba2cbe9Sxc151355 			vtailp = &lvp->lv_nextval;
490*0ba2cbe9Sxc151355 
491*0ba2cbe9Sxc151355 			if (c == ';') {
492*0ba2cbe9Sxc151355 				tailp = &lip->li_nextprop;
493*0ba2cbe9Sxc151355 				vtailp = NULL;
494*0ba2cbe9Sxc151355 				lip = NULL;
495*0ba2cbe9Sxc151355 			}
496*0ba2cbe9Sxc151355 		} else {
497*0ba2cbe9Sxc151355 			/*
498*0ba2cbe9Sxc151355 			 * lip == NULL indicates that 'curr' must be refering
499*0ba2cbe9Sxc151355 			 * to a property name. We allocate a new linkprop_info_t
500*0ba2cbe9Sxc151355 			 * append it to the list given by the caller.
501*0ba2cbe9Sxc151355 			 */
502*0ba2cbe9Sxc151355 			if (c != '=')
503*0ba2cbe9Sxc151355 				goto fail;
504*0ba2cbe9Sxc151355 
505*0ba2cbe9Sxc151355 			lip = malloc(sizeof (*lip));
506*0ba2cbe9Sxc151355 			if (lip == NULL)
507*0ba2cbe9Sxc151355 				goto fail;
508*0ba2cbe9Sxc151355 
509*0ba2cbe9Sxc151355 			lip->li_name = curr;
510*0ba2cbe9Sxc151355 			lip->li_val = NULL;
511*0ba2cbe9Sxc151355 			lip->li_nextprop = NULL;
512*0ba2cbe9Sxc151355 			*tailp = lip;
513*0ba2cbe9Sxc151355 			vtailp = &lip->li_val;
514*0ba2cbe9Sxc151355 		}
515*0ba2cbe9Sxc151355 		curr = buf + i + 1;
516*0ba2cbe9Sxc151355 	}
517*0ba2cbe9Sxc151355 	/*
518*0ba2cbe9Sxc151355 	 * The list must be non-empty and the last character must be ';'.
519*0ba2cbe9Sxc151355 	 */
520*0ba2cbe9Sxc151355 	if (*lipp == NULL || lip != NULL)
521*0ba2cbe9Sxc151355 		goto fail;
522*0ba2cbe9Sxc151355 
523*0ba2cbe9Sxc151355 	return (0);
524*0ba2cbe9Sxc151355 
525*0ba2cbe9Sxc151355 fail:
526*0ba2cbe9Sxc151355 	free_linkprops(*lipp);
527*0ba2cbe9Sxc151355 	*lipp = NULL;
528*0ba2cbe9Sxc151355 	return (-1);
529*0ba2cbe9Sxc151355 }
530*0ba2cbe9Sxc151355 
531*0ba2cbe9Sxc151355 static boolean_t
532*0ba2cbe9Sxc151355 process_linkprop_line(linkprop_db_state_t *lsp, char *buf,
533*0ba2cbe9Sxc151355     dladm_status_t *statusp)
534*0ba2cbe9Sxc151355 {
535*0ba2cbe9Sxc151355 	linkprop_info_t		*lip = NULL;
536*0ba2cbe9Sxc151355 	int			i, len, llen;
537*0ba2cbe9Sxc151355 	char			*str, *lasts;
538*0ba2cbe9Sxc151355 	boolean_t		cont, nolink = B_FALSE;
539*0ba2cbe9Sxc151355 
540*0ba2cbe9Sxc151355 	/*
541*0ba2cbe9Sxc151355 	 * Skip leading spaces, blank lines, and comments.
542*0ba2cbe9Sxc151355 	 */
543*0ba2cbe9Sxc151355 	len = strlen(buf);
544*0ba2cbe9Sxc151355 	for (i = 0; i < len; i++) {
545*0ba2cbe9Sxc151355 		if (!isspace(buf[i]))
546*0ba2cbe9Sxc151355 			break;
547*0ba2cbe9Sxc151355 	}
548*0ba2cbe9Sxc151355 	if (i == len || buf[i] == '#')
549*0ba2cbe9Sxc151355 		return (B_TRUE);
550*0ba2cbe9Sxc151355 
551*0ba2cbe9Sxc151355 	str = buf + i;
552*0ba2cbe9Sxc151355 	if (lsp->ls_link != NULL) {
553*0ba2cbe9Sxc151355 		/*
554*0ba2cbe9Sxc151355 		 * Skip links we're not interested in.
555*0ba2cbe9Sxc151355 		 * Note that strncmp() and isspace() are used here
556*0ba2cbe9Sxc151355 		 * instead of strtok() and strcmp() because we don't
557*0ba2cbe9Sxc151355 		 * want to modify buf in case it does not contain the
558*0ba2cbe9Sxc151355 		 * specified link.
559*0ba2cbe9Sxc151355 		 */
560*0ba2cbe9Sxc151355 		llen = strlen(lsp->ls_link);
561*0ba2cbe9Sxc151355 		if (strncmp(str, lsp->ls_link, llen) != 0 ||
562*0ba2cbe9Sxc151355 		    !isspace(str[llen]))
563*0ba2cbe9Sxc151355 			return (B_TRUE);
564*0ba2cbe9Sxc151355 	} else {
565*0ba2cbe9Sxc151355 		/*
566*0ba2cbe9Sxc151355 		 * If a link is not specified, find the link name
567*0ba2cbe9Sxc151355 		 * and assign it to lsp->ls_link.
568*0ba2cbe9Sxc151355 		 */
569*0ba2cbe9Sxc151355 		if (strtok_r(str, " \n\t", &lasts) == NULL)
570*0ba2cbe9Sxc151355 			goto fail;
571*0ba2cbe9Sxc151355 
572*0ba2cbe9Sxc151355 		llen = strlen(str);
573*0ba2cbe9Sxc151355 		lsp->ls_link = str;
574*0ba2cbe9Sxc151355 		nolink = B_TRUE;
575*0ba2cbe9Sxc151355 	}
576*0ba2cbe9Sxc151355 	str += llen + 1;
577*0ba2cbe9Sxc151355 	if (str >= buf + len)
578*0ba2cbe9Sxc151355 		goto fail;
579*0ba2cbe9Sxc151355 
580*0ba2cbe9Sxc151355 	/*
581*0ba2cbe9Sxc151355 	 * Now find the list of link properties.
582*0ba2cbe9Sxc151355 	 */
583*0ba2cbe9Sxc151355 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
584*0ba2cbe9Sxc151355 		goto fail;
585*0ba2cbe9Sxc151355 
586*0ba2cbe9Sxc151355 	if (parse_linkprops(str, &lip) < 0)
587*0ba2cbe9Sxc151355 		goto fail;
588*0ba2cbe9Sxc151355 
589*0ba2cbe9Sxc151355 	cont = (*lsp->ls_op)(lsp, buf, lip, statusp);
590*0ba2cbe9Sxc151355 	free_linkprops(lip);
591*0ba2cbe9Sxc151355 	if (nolink)
592*0ba2cbe9Sxc151355 		lsp->ls_link = NULL;
593*0ba2cbe9Sxc151355 	return (cont);
594*0ba2cbe9Sxc151355 
595*0ba2cbe9Sxc151355 fail:
596*0ba2cbe9Sxc151355 	free_linkprops(lip);
597*0ba2cbe9Sxc151355 	if (nolink)
598*0ba2cbe9Sxc151355 		lsp->ls_link = NULL;
599*0ba2cbe9Sxc151355 
600*0ba2cbe9Sxc151355 	/*
601*0ba2cbe9Sxc151355 	 * Delete corrupted line.
602*0ba2cbe9Sxc151355 	 */
603*0ba2cbe9Sxc151355 	buf[0] = '\0';
604*0ba2cbe9Sxc151355 	return (B_TRUE);
605*0ba2cbe9Sxc151355 }
606*0ba2cbe9Sxc151355 
607*0ba2cbe9Sxc151355 static dladm_status_t
608*0ba2cbe9Sxc151355 process_linkprop_db(void *arg, FILE *fp, FILE *nfp)
609*0ba2cbe9Sxc151355 {
610*0ba2cbe9Sxc151355 	linkprop_db_state_t	*lsp = arg;
611*0ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
612*0ba2cbe9Sxc151355 	char			buf[MAXLINELEN];
613*0ba2cbe9Sxc151355 	boolean_t		cont = B_TRUE;
614*0ba2cbe9Sxc151355 
615*0ba2cbe9Sxc151355 	/*
616*0ba2cbe9Sxc151355 	 * This loop processes each line of the configuration file.
617*0ba2cbe9Sxc151355 	 * buf can potentially be modified by process_linkprop_line().
618*0ba2cbe9Sxc151355 	 * If this is a write operation and buf is not truncated, buf will
619*0ba2cbe9Sxc151355 	 * be written to disk. process_linkprop_line() will no longer be
620*0ba2cbe9Sxc151355 	 * called after it returns B_FALSE; at which point the remainder
621*0ba2cbe9Sxc151355 	 * of the file will continue to be read and, if necessary, written
622*0ba2cbe9Sxc151355 	 * to disk as well.
623*0ba2cbe9Sxc151355 	 */
624*0ba2cbe9Sxc151355 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
625*0ba2cbe9Sxc151355 		if (cont)
626*0ba2cbe9Sxc151355 			cont = process_linkprop_line(lsp, buf, &status);
627*0ba2cbe9Sxc151355 
628*0ba2cbe9Sxc151355 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
629*0ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
630*0ba2cbe9Sxc151355 			break;
631*0ba2cbe9Sxc151355 		}
632*0ba2cbe9Sxc151355 	}
633*0ba2cbe9Sxc151355 
634*0ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK || !cont)
635*0ba2cbe9Sxc151355 		return (status);
636*0ba2cbe9Sxc151355 
637*0ba2cbe9Sxc151355 	if (lsp->ls_op == process_linkprop_set) {
638*0ba2cbe9Sxc151355 		/*
639*0ba2cbe9Sxc151355 		 * If the specified link is not found above, we add the
640*0ba2cbe9Sxc151355 		 * link and its properties to the configuration file.
641*0ba2cbe9Sxc151355 		 */
642*0ba2cbe9Sxc151355 		(void) (*lsp->ls_op)(lsp, buf, NULL, &status);
643*0ba2cbe9Sxc151355 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
644*0ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
645*0ba2cbe9Sxc151355 	}
646*0ba2cbe9Sxc151355 
647*0ba2cbe9Sxc151355 	if (lsp->ls_op == process_linkprop_get)
648*0ba2cbe9Sxc151355 		status = DLADM_STATUS_NOTFOUND;
649*0ba2cbe9Sxc151355 
650*0ba2cbe9Sxc151355 	return (status);
651*0ba2cbe9Sxc151355 }
652*0ba2cbe9Sxc151355 
653*0ba2cbe9Sxc151355 #define	LINKPROP_RW_DB(statep, writeop) \
654*0ba2cbe9Sxc151355 	(i_dladm_rw_db("/etc/dladm/linkprop.conf", \
655*0ba2cbe9Sxc151355 	S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_linkprop_db, \
656*0ba2cbe9Sxc151355 	(statep), (writeop)))
657*0ba2cbe9Sxc151355 
658*0ba2cbe9Sxc151355 static dladm_status_t
659*0ba2cbe9Sxc151355 i_dladm_set_prop_db(const char *link, const char *prop_name,
660*0ba2cbe9Sxc151355     char **prop_val, uint_t val_cnt)
661*0ba2cbe9Sxc151355 {
662*0ba2cbe9Sxc151355 	linkprop_db_state_t	state;
663*0ba2cbe9Sxc151355 
664*0ba2cbe9Sxc151355 	state.ls_op = process_linkprop_set;
665*0ba2cbe9Sxc151355 	state.ls_link = link;
666*0ba2cbe9Sxc151355 	state.ls_propname = prop_name;
667*0ba2cbe9Sxc151355 	state.ls_propval = prop_val;
668*0ba2cbe9Sxc151355 	state.ls_valcntp = &val_cnt;
669*0ba2cbe9Sxc151355 
670*0ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_TRUE));
671*0ba2cbe9Sxc151355 }
672*0ba2cbe9Sxc151355 
673*0ba2cbe9Sxc151355 static dladm_status_t
674*0ba2cbe9Sxc151355 i_dladm_get_prop_db(const char *link, const char *prop_name,
675*0ba2cbe9Sxc151355     char **prop_val, uint_t *val_cntp)
676*0ba2cbe9Sxc151355 {
677*0ba2cbe9Sxc151355 	linkprop_db_state_t	state;
678*0ba2cbe9Sxc151355 
679*0ba2cbe9Sxc151355 	state.ls_op = process_linkprop_get;
680*0ba2cbe9Sxc151355 	state.ls_link = link;
681*0ba2cbe9Sxc151355 	state.ls_propname = prop_name;
682*0ba2cbe9Sxc151355 	state.ls_propval = prop_val;
683*0ba2cbe9Sxc151355 	state.ls_valcntp = val_cntp;
684*0ba2cbe9Sxc151355 
685*0ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_FALSE));
686*0ba2cbe9Sxc151355 }
687*0ba2cbe9Sxc151355 
688*0ba2cbe9Sxc151355 dladm_status_t
689*0ba2cbe9Sxc151355 dladm_init_linkprop(void)
690*0ba2cbe9Sxc151355 {
691*0ba2cbe9Sxc151355 	linkprop_db_state_t	state;
692*0ba2cbe9Sxc151355 
693*0ba2cbe9Sxc151355 	state.ls_op = process_linkprop_init;
694*0ba2cbe9Sxc151355 	state.ls_link = NULL;
695*0ba2cbe9Sxc151355 	state.ls_propname = NULL;
696*0ba2cbe9Sxc151355 	state.ls_propval = NULL;
697*0ba2cbe9Sxc151355 	state.ls_valcntp = NULL;
698*0ba2cbe9Sxc151355 
699*0ba2cbe9Sxc151355 	return (LINKPROP_RW_DB(&state, B_FALSE));
700*0ba2cbe9Sxc151355 }
701