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