1*d62bc4baSyz /*
2*d62bc4baSyz  * CDDL HEADER START
3*d62bc4baSyz  *
4*d62bc4baSyz  * The contents of this file are subject to the terms of the
5*d62bc4baSyz  * Common Development and Distribution License (the "License").
6*d62bc4baSyz  * You may not use this file except in compliance with the License.
7*d62bc4baSyz  *
8*d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10*d62bc4baSyz  * See the License for the specific language governing permissions
11*d62bc4baSyz  * and limitations under the License.
12*d62bc4baSyz  *
13*d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14*d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16*d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17*d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18*d62bc4baSyz  *
19*d62bc4baSyz  * CDDL HEADER END
20*d62bc4baSyz  */
21*d62bc4baSyz /*
22*d62bc4baSyz  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*d62bc4baSyz  * Use is subject to license terms.
24*d62bc4baSyz  */
25*d62bc4baSyz 
26*d62bc4baSyz #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*d62bc4baSyz 
28*d62bc4baSyz #include <door.h>
29*d62bc4baSyz #include <errno.h>
30*d62bc4baSyz #include <assert.h>
31*d62bc4baSyz #include <stdio.h>
32*d62bc4baSyz #include <stdlib.h>
33*d62bc4baSyz #include <unistd.h>
34*d62bc4baSyz #include <string.h>
35*d62bc4baSyz #include <strings.h>
36*d62bc4baSyz #include <sys/types.h>
37*d62bc4baSyz #include <sys/stat.h>
38*d62bc4baSyz #include <sys/aggr.h>
39*d62bc4baSyz #include <fcntl.h>
40*d62bc4baSyz #include <libdladm.h>
41*d62bc4baSyz #include <libdladm_impl.h>
42*d62bc4baSyz #include <libdllink.h>
43*d62bc4baSyz #include <libdlmgmt.h>
44*d62bc4baSyz 
45*d62bc4baSyz /*
46*d62bc4baSyz  * Table of data type sizes indexed by dladm_datatype_t.
47*d62bc4baSyz  */
48*d62bc4baSyz static size_t dladm_datatype_size[] = {
49*d62bc4baSyz 	0,				/* DLADM_TYPE_STR, use strnlen() */
50*d62bc4baSyz 	sizeof (boolean_t),		/* DLADM_TYPE_BOOLEAN */
51*d62bc4baSyz 	sizeof (uint64_t)		/* DLADM_TYPE_UINT64 */
52*d62bc4baSyz };
53*d62bc4baSyz 
54*d62bc4baSyz static dladm_status_t
55*d62bc4baSyz dladm_door_call(void *arg, size_t asize, void *rbuf, size_t *rsizep)
56*d62bc4baSyz {
57*d62bc4baSyz 	door_arg_t	darg;
58*d62bc4baSyz 	dlmgmt_retval_t	*retvalp = rbuf;
59*d62bc4baSyz 	int		fd;
60*d62bc4baSyz 	dladm_status_t	status = DLADM_STATUS_OK;
61*d62bc4baSyz 
62*d62bc4baSyz 	if ((fd = open(DLMGMT_DOOR, O_RDONLY)) == -1)
63*d62bc4baSyz 		return (dladm_errno2status(errno));
64*d62bc4baSyz 
65*d62bc4baSyz 	darg.data_ptr	= arg;
66*d62bc4baSyz 	darg.data_size	= asize;
67*d62bc4baSyz 	darg.desc_ptr	= NULL;
68*d62bc4baSyz 	darg.desc_num	= 0;
69*d62bc4baSyz 	darg.rbuf	= rbuf;
70*d62bc4baSyz 	darg.rsize	= *rsizep;
71*d62bc4baSyz 
72*d62bc4baSyz 	if (door_call(fd, &darg) == -1)
73*d62bc4baSyz 		status = dladm_errno2status(errno);
74*d62bc4baSyz 	(void) close(fd);
75*d62bc4baSyz 
76*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
77*d62bc4baSyz 		return (status);
78*d62bc4baSyz 
79*d62bc4baSyz 	if (darg.rbuf != rbuf) {
80*d62bc4baSyz 		/*
81*d62bc4baSyz 		 * The size of the input rbuf is not big enough so that
82*d62bc4baSyz 		 * the door allocate the rbuf itself. In this case, simply
83*d62bc4baSyz 		 * think something wrong with the door call.
84*d62bc4baSyz 		 */
85*d62bc4baSyz 		(void) munmap(darg.rbuf, darg.rsize);
86*d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
87*d62bc4baSyz 	}
88*d62bc4baSyz 	if (darg.rsize > *rsizep || darg.rsize < sizeof (uint_t))
89*d62bc4baSyz 		return (DLADM_STATUS_FAILED);
90*d62bc4baSyz 
91*d62bc4baSyz 	if (retvalp->lr_err != 0)
92*d62bc4baSyz 		status = dladm_errno2status(retvalp->lr_err);
93*d62bc4baSyz 	else
94*d62bc4baSyz 		*rsizep = darg.rsize;
95*d62bc4baSyz 	return (status);
96*d62bc4baSyz }
97*d62bc4baSyz 
98*d62bc4baSyz /*
99*d62bc4baSyz  * Allocate a new linkid with the given name. Return the new linkid.
100*d62bc4baSyz  */
101*d62bc4baSyz dladm_status_t
102*d62bc4baSyz dladm_create_datalink_id(const char *link, datalink_class_t class,
103*d62bc4baSyz     uint32_t media, uint32_t flags, datalink_id_t *linkidp)
104*d62bc4baSyz {
105*d62bc4baSyz 	dlmgmt_door_createid_t createid;
106*d62bc4baSyz 	dlmgmt_createid_retval_t retval;
107*d62bc4baSyz 	uint32_t dlmgmt_flags;
108*d62bc4baSyz 	dladm_status_t status;
109*d62bc4baSyz 	size_t rsize;
110*d62bc4baSyz 
111*d62bc4baSyz 	if (link == NULL || *link == '\0' || class == DATALINK_CLASS_ALL ||
112*d62bc4baSyz 	    !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
113*d62bc4baSyz 	    linkidp == NULL) {
114*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
115*d62bc4baSyz 	}
116*d62bc4baSyz 
117*d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
118*d62bc4baSyz 	dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
119*d62bc4baSyz 
120*d62bc4baSyz 	(void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
121*d62bc4baSyz 	createid.ld_class = class;
122*d62bc4baSyz 	createid.ld_media = media;
123*d62bc4baSyz 	createid.ld_flags = dlmgmt_flags;
124*d62bc4baSyz 	createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
125*d62bc4baSyz 	createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
126*d62bc4baSyz 	rsize = sizeof (retval);
127*d62bc4baSyz 
128*d62bc4baSyz 	status = dladm_door_call(&createid, sizeof (createid), &retval, &rsize);
129*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
130*d62bc4baSyz 		return (status);
131*d62bc4baSyz 
132*d62bc4baSyz 	if (rsize != sizeof (retval))
133*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
134*d62bc4baSyz 
135*d62bc4baSyz 	*linkidp = retval.lr_linkid;
136*d62bc4baSyz 	return (DLADM_STATUS_OK);
137*d62bc4baSyz }
138*d62bc4baSyz 
139*d62bc4baSyz /*
140*d62bc4baSyz  * Destroy the given link ID.
141*d62bc4baSyz  */
142*d62bc4baSyz dladm_status_t
143*d62bc4baSyz dladm_destroy_datalink_id(datalink_id_t linkid, uint32_t flags)
144*d62bc4baSyz {
145*d62bc4baSyz 	dlmgmt_door_destroyid_t		destroyid;
146*d62bc4baSyz 	dlmgmt_destroyid_retval_t	retval;
147*d62bc4baSyz 	uint32_t			dlmgmt_flags;
148*d62bc4baSyz 	size_t				rsize;
149*d62bc4baSyz 	dladm_status_t			status;
150*d62bc4baSyz 
151*d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
152*d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
153*d62bc4baSyz 
154*d62bc4baSyz 	destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
155*d62bc4baSyz 	destroyid.ld_linkid = linkid;
156*d62bc4baSyz 	destroyid.ld_flags = dlmgmt_flags;
157*d62bc4baSyz 	rsize = sizeof (retval);
158*d62bc4baSyz 
159*d62bc4baSyz 	status = dladm_door_call(&destroyid, sizeof (destroyid), &retval,
160*d62bc4baSyz 	    &rsize);
161*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
162*d62bc4baSyz 		return (status);
163*d62bc4baSyz 
164*d62bc4baSyz 	if (rsize != sizeof (retval))
165*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
166*d62bc4baSyz 
167*d62bc4baSyz 	return (DLADM_STATUS_OK);
168*d62bc4baSyz }
169*d62bc4baSyz 
170*d62bc4baSyz /*
171*d62bc4baSyz  * Remap a given link ID to a new name.
172*d62bc4baSyz  */
173*d62bc4baSyz dladm_status_t
174*d62bc4baSyz dladm_remap_datalink_id(datalink_id_t linkid, const char *link)
175*d62bc4baSyz {
176*d62bc4baSyz 	dlmgmt_door_remapid_t	remapid;
177*d62bc4baSyz 	dlmgmt_remapid_retval_t	retval;
178*d62bc4baSyz 	size_t			rsize;
179*d62bc4baSyz 	dladm_status_t		status;
180*d62bc4baSyz 
181*d62bc4baSyz 	remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
182*d62bc4baSyz 	remapid.ld_linkid = linkid;
183*d62bc4baSyz 	(void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
184*d62bc4baSyz 	rsize = sizeof (retval);
185*d62bc4baSyz 
186*d62bc4baSyz 	status = dladm_door_call(&remapid, sizeof (remapid), &retval, &rsize);
187*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
188*d62bc4baSyz 		return (status);
189*d62bc4baSyz 
190*d62bc4baSyz 	if (rsize != sizeof (retval))
191*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
192*d62bc4baSyz 
193*d62bc4baSyz 	return (DLADM_STATUS_OK);
194*d62bc4baSyz }
195*d62bc4baSyz 
196*d62bc4baSyz /*
197*d62bc4baSyz  * Make a given link ID active.
198*d62bc4baSyz  */
199*d62bc4baSyz dladm_status_t
200*d62bc4baSyz dladm_up_datalink_id(datalink_id_t linkid)
201*d62bc4baSyz {
202*d62bc4baSyz 	dlmgmt_door_upid_t		upid;
203*d62bc4baSyz 	dlmgmt_upid_retval_t		retval;
204*d62bc4baSyz 	size_t				rsize;
205*d62bc4baSyz 	dladm_status_t			status;
206*d62bc4baSyz 
207*d62bc4baSyz 	upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
208*d62bc4baSyz 	upid.ld_linkid = linkid;
209*d62bc4baSyz 	rsize = sizeof (retval);
210*d62bc4baSyz 
211*d62bc4baSyz 	status = dladm_door_call(&upid, sizeof (upid), &retval, &rsize);
212*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
213*d62bc4baSyz 		return (status);
214*d62bc4baSyz 
215*d62bc4baSyz 	if (rsize != sizeof (retval))
216*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
217*d62bc4baSyz 
218*d62bc4baSyz 	return (DLADM_STATUS_OK);
219*d62bc4baSyz }
220*d62bc4baSyz 
221*d62bc4baSyz /*
222*d62bc4baSyz  * Create a new link with the given name.  Return the new link's handle
223*d62bc4baSyz  */
224*d62bc4baSyz dladm_status_t
225*d62bc4baSyz dladm_create_conf(const char *link, datalink_id_t linkid,
226*d62bc4baSyz     datalink_class_t class, uint32_t media, dladm_conf_t *confp)
227*d62bc4baSyz {
228*d62bc4baSyz 	dlmgmt_door_createconf_t createconf;
229*d62bc4baSyz 	dlmgmt_createconf_retval_t retval;
230*d62bc4baSyz 	dladm_status_t status;
231*d62bc4baSyz 	size_t rsize;
232*d62bc4baSyz 
233*d62bc4baSyz 	if (link == NULL || *link == '\0' || confp == NULL)
234*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
235*d62bc4baSyz 
236*d62bc4baSyz 	(void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
237*d62bc4baSyz 	createconf.ld_class = class;
238*d62bc4baSyz 	createconf.ld_media = media;
239*d62bc4baSyz 	createconf.ld_linkid = linkid;
240*d62bc4baSyz 	createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
241*d62bc4baSyz 	rsize = sizeof (retval);
242*d62bc4baSyz 
243*d62bc4baSyz 	status = dladm_door_call(&createconf, sizeof (createconf), &retval,
244*d62bc4baSyz 	    &rsize);
245*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
246*d62bc4baSyz 		return (status);
247*d62bc4baSyz 
248*d62bc4baSyz 	if (rsize != sizeof (retval))
249*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
250*d62bc4baSyz 
251*d62bc4baSyz 	*confp = retval.lr_conf;
252*d62bc4baSyz 	return (DLADM_STATUS_OK);
253*d62bc4baSyz }
254*d62bc4baSyz 
255*d62bc4baSyz /*
256*d62bc4baSyz  * An active physical link reported by the dlmgmtd daemon might not be active
257*d62bc4baSyz  * anymore as this link might be removed during system shutdown. Check its
258*d62bc4baSyz  * real status by calling dladm_phys_info().
259*d62bc4baSyz  */
260*d62bc4baSyz dladm_status_t
261*d62bc4baSyz i_dladm_phys_status(datalink_id_t linkid, uint32_t *flagsp)
262*d62bc4baSyz {
263*d62bc4baSyz 	dladm_phys_attr_t	dpa;
264*d62bc4baSyz 	dladm_status_t		status;
265*d62bc4baSyz 
266*d62bc4baSyz 	assert((*flagsp) & DLMGMT_ACTIVE);
267*d62bc4baSyz 
268*d62bc4baSyz 	status = dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE);
269*d62bc4baSyz 	if (status == DLADM_STATUS_NOTFOUND) {
270*d62bc4baSyz 		/*
271*d62bc4baSyz 		 * No active status, this link was removed. Update its status
272*d62bc4baSyz 		 * in the daemon and delete all active linkprops.
273*d62bc4baSyz 		 */
274*d62bc4baSyz 		(void) dladm_destroy_datalink_id(linkid, DLADM_OPT_ACTIVE);
275*d62bc4baSyz 		(void) dladm_set_linkprop(linkid, NULL, NULL, 0,
276*d62bc4baSyz 		    DLADM_OPT_ACTIVE);
277*d62bc4baSyz 
278*d62bc4baSyz 		(*flagsp) &= ~DLMGMT_ACTIVE;
279*d62bc4baSyz 		status = DLADM_STATUS_OK;
280*d62bc4baSyz 	}
281*d62bc4baSyz 	return (status);
282*d62bc4baSyz }
283*d62bc4baSyz 
284*d62bc4baSyz /*
285*d62bc4baSyz  * Walk each entry in the data link configuration repository and
286*d62bc4baSyz  * call fn on the linkid and arg.
287*d62bc4baSyz  */
288*d62bc4baSyz dladm_status_t
289*d62bc4baSyz dladm_walk_datalink_id(int (*fn)(datalink_id_t, void *), void *argp,
290*d62bc4baSyz     datalink_class_t class, datalink_media_t dmedia, uint32_t flags)
291*d62bc4baSyz {
292*d62bc4baSyz 	dlmgmt_door_getnext_t	getnext;
293*d62bc4baSyz 	dlmgmt_getnext_retval_t	retval;
294*d62bc4baSyz 	uint32_t 		dlmgmt_flags;
295*d62bc4baSyz 	size_t			rsize;
296*d62bc4baSyz 	datalink_id_t		linkid = DATALINK_INVALID_LINKID;
297*d62bc4baSyz 	dladm_status_t		status = DLADM_STATUS_OK;
298*d62bc4baSyz 
299*d62bc4baSyz 	if (fn == NULL)
300*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
301*d62bc4baSyz 
302*d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
303*d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
304*d62bc4baSyz 
305*d62bc4baSyz 	getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
306*d62bc4baSyz 	getnext.ld_class = class;
307*d62bc4baSyz 	getnext.ld_dmedia = dmedia;
308*d62bc4baSyz 	getnext.ld_flags = dlmgmt_flags;
309*d62bc4baSyz 	rsize = sizeof (retval);
310*d62bc4baSyz 
311*d62bc4baSyz 	do {
312*d62bc4baSyz 		getnext.ld_linkid = linkid;
313*d62bc4baSyz 		status = dladm_door_call(&getnext, sizeof (getnext),
314*d62bc4baSyz 		    &retval, &rsize);
315*d62bc4baSyz 		if (status != DLADM_STATUS_OK) {
316*d62bc4baSyz 			/*
317*d62bc4baSyz 			 * done with walking
318*d62bc4baSyz 			 */
319*d62bc4baSyz 			break;
320*d62bc4baSyz 		}
321*d62bc4baSyz 
322*d62bc4baSyz 		if (rsize != sizeof (retval)) {
323*d62bc4baSyz 			status = DLADM_STATUS_BADARG;
324*d62bc4baSyz 			break;
325*d62bc4baSyz 		}
326*d62bc4baSyz 
327*d62bc4baSyz 		linkid = retval.lr_linkid;
328*d62bc4baSyz 		if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
329*d62bc4baSyz 		    (retval.lr_flags & DLMGMT_ACTIVE)) {
330*d62bc4baSyz 			/*
331*d62bc4baSyz 			 * An active physical link reported by the dlmgmtd
332*d62bc4baSyz 			 * daemon might not be active anymore. Check its
333*d62bc4baSyz 			 * real status.
334*d62bc4baSyz 			 */
335*d62bc4baSyz 			if (i_dladm_phys_status(linkid, &retval.lr_flags) !=
336*d62bc4baSyz 			    DLADM_STATUS_OK) {
337*d62bc4baSyz 				continue;
338*d62bc4baSyz 			}
339*d62bc4baSyz 
340*d62bc4baSyz 			if (!(dlmgmt_flags & retval.lr_flags))
341*d62bc4baSyz 				continue;
342*d62bc4baSyz 		}
343*d62bc4baSyz 
344*d62bc4baSyz 		if (fn(linkid, argp) == DLADM_WALK_TERMINATE)
345*d62bc4baSyz 			break;
346*d62bc4baSyz 	} while (linkid != DATALINK_INVALID_LINKID);
347*d62bc4baSyz 
348*d62bc4baSyz 	return (status);
349*d62bc4baSyz }
350*d62bc4baSyz 
351*d62bc4baSyz /*
352*d62bc4baSyz  * Get the link properties structure for the given link.
353*d62bc4baSyz  */
354*d62bc4baSyz dladm_status_t
355*d62bc4baSyz dladm_read_conf(datalink_id_t linkid, dladm_conf_t *confp)
356*d62bc4baSyz {
357*d62bc4baSyz 	dlmgmt_door_readconf_t 		readconf;
358*d62bc4baSyz 	dlmgmt_readconf_retval_t	retval;
359*d62bc4baSyz 	dladm_status_t			status;
360*d62bc4baSyz 	size_t				rsize;
361*d62bc4baSyz 
362*d62bc4baSyz 	if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
363*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
364*d62bc4baSyz 
365*d62bc4baSyz 	readconf.ld_linkid = linkid;
366*d62bc4baSyz 	readconf.ld_cmd = DLMGMT_CMD_READCONF;
367*d62bc4baSyz 	rsize = sizeof (retval);
368*d62bc4baSyz 
369*d62bc4baSyz 	status = dladm_door_call(&readconf, sizeof (readconf), &retval,
370*d62bc4baSyz 	    &rsize);
371*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
372*d62bc4baSyz 		return (status);
373*d62bc4baSyz 
374*d62bc4baSyz 	if (rsize != sizeof (retval))
375*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
376*d62bc4baSyz 
377*d62bc4baSyz 	*confp = retval.lr_conf;
378*d62bc4baSyz 	return (DLADM_STATUS_OK);
379*d62bc4baSyz }
380*d62bc4baSyz 
381*d62bc4baSyz /*
382*d62bc4baSyz  * Commit the given link to the data link configuration repository so
383*d62bc4baSyz  * that it will persist across reboots.
384*d62bc4baSyz  */
385*d62bc4baSyz dladm_status_t
386*d62bc4baSyz dladm_write_conf(dladm_conf_t conf)
387*d62bc4baSyz {
388*d62bc4baSyz 	dlmgmt_door_writeconf_t		writeconf;
389*d62bc4baSyz 	dlmgmt_writeconf_retval_t	retval;
390*d62bc4baSyz 	dladm_status_t			status;
391*d62bc4baSyz 	size_t				rsize;
392*d62bc4baSyz 
393*d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
394*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
395*d62bc4baSyz 
396*d62bc4baSyz 	writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
397*d62bc4baSyz 	writeconf.ld_conf = conf;
398*d62bc4baSyz 	rsize = sizeof (retval);
399*d62bc4baSyz 
400*d62bc4baSyz 	status = dladm_door_call(&writeconf, sizeof (writeconf), &retval,
401*d62bc4baSyz 	    &rsize);
402*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
403*d62bc4baSyz 		return (status);
404*d62bc4baSyz 
405*d62bc4baSyz 	if (rsize != sizeof (retval))
406*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
407*d62bc4baSyz 
408*d62bc4baSyz 	return (DLADM_STATUS_OK);
409*d62bc4baSyz }
410*d62bc4baSyz 
411*d62bc4baSyz /*
412*d62bc4baSyz  * Given a link ID and a key, get the matching information from
413*d62bc4baSyz  * data link configuration repository.
414*d62bc4baSyz  */
415*d62bc4baSyz dladm_status_t
416*d62bc4baSyz dladm_get_conf_field(dladm_conf_t conf, const char *attr, void *attrval,
417*d62bc4baSyz     size_t attrsz)
418*d62bc4baSyz {
419*d62bc4baSyz 	dlmgmt_door_getattr_t getattr;
420*d62bc4baSyz 	dlmgmt_getattr_retval_t *retvalp;
421*d62bc4baSyz 	dladm_status_t status = DLADM_STATUS_OK;
422*d62bc4baSyz 	size_t oldsize, size;
423*d62bc4baSyz 
424*d62bc4baSyz 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
425*d62bc4baSyz 	    attrsz == 0 || attr == NULL || *attr == '\0') {
426*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
427*d62bc4baSyz 	}
428*d62bc4baSyz 
429*d62bc4baSyz 	getattr.ld_cmd = DLMGMT_CMD_GETATTR;
430*d62bc4baSyz 	getattr.ld_conf = conf;
431*d62bc4baSyz 	(void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
432*d62bc4baSyz 
433*d62bc4baSyz 	oldsize = size = attrsz + sizeof (dlmgmt_getattr_retval_t) - 1;
434*d62bc4baSyz 	if ((retvalp = calloc(1, oldsize)) == NULL)
435*d62bc4baSyz 		return (DLADM_STATUS_NOMEM);
436*d62bc4baSyz 
437*d62bc4baSyz 	status = dladm_door_call(&getattr, sizeof (getattr), retvalp, &size);
438*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
439*d62bc4baSyz 		goto done;
440*d62bc4baSyz 
441*d62bc4baSyz 	assert(size <= oldsize);
442*d62bc4baSyz 	size = size + 1 - sizeof (dlmgmt_getattr_retval_t);
443*d62bc4baSyz 	bcopy(retvalp->lr_attr, attrval, size);
444*d62bc4baSyz done:
445*d62bc4baSyz 	free(retvalp);
446*d62bc4baSyz 	return (status);
447*d62bc4baSyz }
448*d62bc4baSyz 
449*d62bc4baSyz /*
450*d62bc4baSyz  * Get the link ID that is associated with the given name.
451*d62bc4baSyz  */
452*d62bc4baSyz dladm_status_t
453*d62bc4baSyz dladm_name2info(const char *link, datalink_id_t *linkidp, uint32_t *flagp,
454*d62bc4baSyz     datalink_class_t *classp, uint32_t *mediap)
455*d62bc4baSyz {
456*d62bc4baSyz 	dlmgmt_door_getlinkid_t		getlinkid;
457*d62bc4baSyz 	dlmgmt_getlinkid_retval_t	retval;
458*d62bc4baSyz 	datalink_id_t			linkid;
459*d62bc4baSyz 	size_t				rsize;
460*d62bc4baSyz 	dladm_status_t			status;
461*d62bc4baSyz 
462*d62bc4baSyz 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
463*d62bc4baSyz 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
464*d62bc4baSyz 	rsize = sizeof (retval);
465*d62bc4baSyz 
466*d62bc4baSyz 	status = dladm_door_call(&getlinkid, sizeof (getlinkid), &retval,
467*d62bc4baSyz 	    &rsize);
468*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
469*d62bc4baSyz 		return (status);
470*d62bc4baSyz 
471*d62bc4baSyz 	if (rsize != sizeof (retval))
472*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
473*d62bc4baSyz 
474*d62bc4baSyz 	linkid = retval.lr_linkid;
475*d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
476*d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
477*d62bc4baSyz 		/*
478*d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
479*d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
480*d62bc4baSyz 		 */
481*d62bc4baSyz 		status = i_dladm_phys_status(linkid, &retval.lr_flags);
482*d62bc4baSyz 		if (status != DLADM_STATUS_OK)
483*d62bc4baSyz 			return (status);
484*d62bc4baSyz 	}
485*d62bc4baSyz 
486*d62bc4baSyz 	if (linkidp != NULL)
487*d62bc4baSyz 		*linkidp = linkid;
488*d62bc4baSyz 	if (flagp != NULL) {
489*d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
490*d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
491*d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
492*d62bc4baSyz 	}
493*d62bc4baSyz 	if (classp != NULL)
494*d62bc4baSyz 		*classp = retval.lr_class;
495*d62bc4baSyz 	if (mediap != NULL)
496*d62bc4baSyz 		*mediap = retval.lr_media;
497*d62bc4baSyz 
498*d62bc4baSyz 	return (DLADM_STATUS_OK);
499*d62bc4baSyz }
500*d62bc4baSyz 
501*d62bc4baSyz /*
502*d62bc4baSyz  * Get the link name that is associated with the given id.
503*d62bc4baSyz  */
504*d62bc4baSyz dladm_status_t
505*d62bc4baSyz dladm_datalink_id2info(datalink_id_t linkid, uint32_t *flagp,
506*d62bc4baSyz     datalink_class_t *classp, uint32_t *mediap, char *link, size_t len)
507*d62bc4baSyz {
508*d62bc4baSyz 	dlmgmt_door_getname_t		getname;
509*d62bc4baSyz 	dlmgmt_getname_retval_t		retval;
510*d62bc4baSyz 	size_t				rsize;
511*d62bc4baSyz 	dladm_status_t			status;
512*d62bc4baSyz 
513*d62bc4baSyz 	if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) ||
514*d62bc4baSyz 	    (link == NULL && len != 0)) {
515*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
516*d62bc4baSyz 	}
517*d62bc4baSyz 
518*d62bc4baSyz 	getname.ld_cmd = DLMGMT_CMD_GETNAME;
519*d62bc4baSyz 	getname.ld_linkid = linkid;
520*d62bc4baSyz 	rsize = sizeof (retval);
521*d62bc4baSyz 	status = dladm_door_call(&getname, sizeof (getname), &retval, &rsize);
522*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
523*d62bc4baSyz 		return (status);
524*d62bc4baSyz 
525*d62bc4baSyz 	if ((rsize != sizeof (retval)) ||
526*d62bc4baSyz 	    (len != 0 && (strlen(retval.lr_link) + 1 > len))) {
527*d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
528*d62bc4baSyz 	}
529*d62bc4baSyz 
530*d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
531*d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
532*d62bc4baSyz 		/*
533*d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
534*d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
535*d62bc4baSyz 		 */
536*d62bc4baSyz 		status = i_dladm_phys_status(linkid, &retval.lr_flags);
537*d62bc4baSyz 		if (status != DLADM_STATUS_OK)
538*d62bc4baSyz 			return (status);
539*d62bc4baSyz 	}
540*d62bc4baSyz 
541*d62bc4baSyz 	if (link != NULL)
542*d62bc4baSyz 		(void) strlcpy(link, retval.lr_link, len);
543*d62bc4baSyz 	if (classp != NULL)
544*d62bc4baSyz 		*classp = retval.lr_class;
545*d62bc4baSyz 	if (mediap != NULL)
546*d62bc4baSyz 		*mediap = retval.lr_media;
547*d62bc4baSyz 	if (flagp != NULL) {
548*d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ?
549*d62bc4baSyz 		    DLADM_OPT_ACTIVE : 0;
550*d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
551*d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
552*d62bc4baSyz 	}
553*d62bc4baSyz 	return (DLADM_STATUS_OK);
554*d62bc4baSyz }
555*d62bc4baSyz 
556*d62bc4baSyz /*
557*d62bc4baSyz  * Set the given attr with the given attrval for the given link.
558*d62bc4baSyz  */
559*d62bc4baSyz dladm_status_t
560*d62bc4baSyz dladm_set_conf_field(dladm_conf_t conf, const char *attr,
561*d62bc4baSyz     dladm_datatype_t type, const void *attrval)
562*d62bc4baSyz {
563*d62bc4baSyz 	dlmgmt_door_setattr_t		*setattrp;
564*d62bc4baSyz 	dlmgmt_setattr_retval_t		retval;
565*d62bc4baSyz 	dladm_status_t			status;
566*d62bc4baSyz 	size_t				asize, attrsz, rsize;
567*d62bc4baSyz 
568*d62bc4baSyz 	if (attr == NULL || attr == '\0' || attrval == NULL)
569*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
570*d62bc4baSyz 
571*d62bc4baSyz 	if (type == DLADM_TYPE_STR)
572*d62bc4baSyz 		attrsz = strlen(attrval) + 1;
573*d62bc4baSyz 	else
574*d62bc4baSyz 		attrsz = dladm_datatype_size[type];
575*d62bc4baSyz 
576*d62bc4baSyz 	asize = sizeof (dlmgmt_door_setattr_t) + attrsz - 1;
577*d62bc4baSyz 	if ((setattrp = calloc(1, asize)) == NULL)
578*d62bc4baSyz 		return (DLADM_STATUS_NOMEM);
579*d62bc4baSyz 
580*d62bc4baSyz 	setattrp->ld_cmd = DLMGMT_CMD_SETATTR;
581*d62bc4baSyz 	setattrp->ld_conf = conf;
582*d62bc4baSyz 	(void) strlcpy(setattrp->ld_attr, attr, MAXLINKATTRLEN);
583*d62bc4baSyz 	setattrp->ld_attrsz = attrsz;
584*d62bc4baSyz 	setattrp->ld_type = type;
585*d62bc4baSyz 	bcopy(attrval, &setattrp->ld_attrval, attrsz);
586*d62bc4baSyz 	rsize = sizeof (retval);
587*d62bc4baSyz 
588*d62bc4baSyz 	status = dladm_door_call(setattrp, asize, &retval, &rsize);
589*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
590*d62bc4baSyz 		goto done;
591*d62bc4baSyz 
592*d62bc4baSyz 	if (rsize != sizeof (retval))
593*d62bc4baSyz 		status = DLADM_STATUS_BADARG;
594*d62bc4baSyz 
595*d62bc4baSyz done:
596*d62bc4baSyz 	free(setattrp);
597*d62bc4baSyz 	return (status);
598*d62bc4baSyz }
599*d62bc4baSyz 
600*d62bc4baSyz /*
601*d62bc4baSyz  * Unset the given attr the given link.
602*d62bc4baSyz  */
603*d62bc4baSyz dladm_status_t
604*d62bc4baSyz dladm_unset_conf_field(dladm_conf_t conf, const char *attr)
605*d62bc4baSyz {
606*d62bc4baSyz 	dlmgmt_door_unsetattr_t		unsetattr;
607*d62bc4baSyz 	dlmgmt_unsetattr_retval_t	retval;
608*d62bc4baSyz 	dladm_status_t			status;
609*d62bc4baSyz 	size_t				rsize;
610*d62bc4baSyz 
611*d62bc4baSyz 	if (attr == NULL || attr == '\0')
612*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
613*d62bc4baSyz 
614*d62bc4baSyz 	unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR;
615*d62bc4baSyz 	unsetattr.ld_conf = conf;
616*d62bc4baSyz 	(void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN);
617*d62bc4baSyz 	rsize = sizeof (retval);
618*d62bc4baSyz 
619*d62bc4baSyz 	status = dladm_door_call(&unsetattr, sizeof (unsetattr), &retval,
620*d62bc4baSyz 	    &rsize);
621*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
622*d62bc4baSyz 		return (status);
623*d62bc4baSyz 
624*d62bc4baSyz 	if (rsize != sizeof (retval))
625*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
626*d62bc4baSyz 
627*d62bc4baSyz 	return (DLADM_STATUS_OK);
628*d62bc4baSyz }
629*d62bc4baSyz 
630*d62bc4baSyz /*
631*d62bc4baSyz  * Remove the given link ID and its entry from the data link configuration
632*d62bc4baSyz  * repository.
633*d62bc4baSyz  */
634*d62bc4baSyz dladm_status_t
635*d62bc4baSyz dladm_remove_conf(datalink_id_t linkid)
636*d62bc4baSyz {
637*d62bc4baSyz 	dlmgmt_door_removeconf_t	removeconf;
638*d62bc4baSyz 	dlmgmt_removeconf_retval_t	retval;
639*d62bc4baSyz 	size_t				rsize;
640*d62bc4baSyz 	dladm_status_t			status;
641*d62bc4baSyz 
642*d62bc4baSyz 	removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF;
643*d62bc4baSyz 	removeconf.ld_linkid = linkid;
644*d62bc4baSyz 	rsize = sizeof (retval);
645*d62bc4baSyz 
646*d62bc4baSyz 	status = dladm_door_call(&removeconf, sizeof (removeconf), &retval,
647*d62bc4baSyz 	    &rsize);
648*d62bc4baSyz 	if (status != DLADM_STATUS_OK)
649*d62bc4baSyz 		return (status);
650*d62bc4baSyz 
651*d62bc4baSyz 	if (rsize != sizeof (retval))
652*d62bc4baSyz 		return (DLADM_STATUS_BADARG);
653*d62bc4baSyz 
654*d62bc4baSyz 	return (DLADM_STATUS_OK);
655*d62bc4baSyz }
656*d62bc4baSyz 
657*d62bc4baSyz /*
658*d62bc4baSyz  * Free the contents of the link structure.
659*d62bc4baSyz  */
660*d62bc4baSyz void
661*d62bc4baSyz dladm_destroy_conf(dladm_conf_t conf)
662*d62bc4baSyz {
663*d62bc4baSyz 	dlmgmt_door_destroyconf_t	destroyconf;
664*d62bc4baSyz 	dlmgmt_destroyconf_retval_t	retval;
665*d62bc4baSyz 	size_t				rsize;
666*d62bc4baSyz 
667*d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
668*d62bc4baSyz 		return;
669*d62bc4baSyz 
670*d62bc4baSyz 	destroyconf.ld_cmd = DLMGMT_CMD_DESTROYCONF;
671*d62bc4baSyz 	destroyconf.ld_conf = conf;
672*d62bc4baSyz 	rsize = sizeof (retval);
673*d62bc4baSyz 
674*d62bc4baSyz 	(void) dladm_door_call(&destroyconf, sizeof (destroyconf), &retval,
675*d62bc4baSyz 	    &rsize);
676*d62bc4baSyz }
677