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