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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <door.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <zone.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/aggr.h>
38 #include <sys/mman.h>
39 #include <fcntl.h>
40 #include <libdladm.h>
41 #include <libdladm_impl.h>
42 #include <libdllink.h>
43 #include <libdlmgmt.h>
44 
45 /*
46  * Table of data type sizes indexed by dladm_datatype_t.
47  */
48 static size_t dladm_datatype_size[] = {
49 	0,				/* DLADM_TYPE_STR, use strnlen() */
50 	sizeof (boolean_t),		/* DLADM_TYPE_BOOLEAN */
51 	sizeof (uint64_t)		/* DLADM_TYPE_UINT64 */
52 };
53 
54 static dladm_status_t
55 dladm_door_call(dladm_handle_t handle, void *arg, size_t asize, void *rbuf,
56     size_t rsize)
57 {
58 	door_arg_t	darg;
59 	int		door_fd;
60 	dladm_status_t	status = DLADM_STATUS_OK;
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	= rsize;
68 
69 	/* The door descriptor is opened if it isn't already */
70 	if ((status = dladm_door_fd(handle, &door_fd)) != DLADM_STATUS_OK)
71 		return (status);
72 	if (door_call(door_fd, &darg) == -1)
73 		status = dladm_errno2status(errno);
74 	if (status != DLADM_STATUS_OK)
75 		return (status);
76 
77 	if (darg.rbuf != rbuf) {
78 		/*
79 		 * The size of the input rbuf is not big enough so that
80 		 * the door allocate the rbuf itself. In this case, simply
81 		 * think something wrong with the door call.
82 		 */
83 		(void) munmap(darg.rbuf, darg.rsize);
84 		return (DLADM_STATUS_TOOSMALL);
85 	}
86 	if (darg.rsize != rsize)
87 		return (DLADM_STATUS_FAILED);
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 
105 	if (link == NULL || class == DATALINK_CLASS_ALL ||
106 	    !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
107 	    linkidp == NULL) {
108 		return (DLADM_STATUS_BADARG);
109 	}
110 
111 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
112 	dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
113 
114 	(void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
115 	createid.ld_class = class;
116 	createid.ld_media = media;
117 	createid.ld_flags = dlmgmt_flags;
118 	createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
119 	createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
120 
121 	if ((status = dladm_door_call(handle, &createid, sizeof (createid),
122 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
123 		*linkidp = retval.lr_linkid;
124 	}
125 	return (status);
126 }
127 
128 /*
129  * Destroy the given link ID.
130  */
131 dladm_status_t
132 dladm_destroy_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
133     uint32_t flags)
134 {
135 	dlmgmt_door_destroyid_t		destroyid;
136 	dlmgmt_destroyid_retval_t	retval;
137 	uint32_t			dlmgmt_flags;
138 
139 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
140 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
141 
142 	destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
143 	destroyid.ld_linkid = linkid;
144 	destroyid.ld_flags = dlmgmt_flags;
145 
146 	return (dladm_door_call(handle, &destroyid, sizeof (destroyid), &retval,
147 	    sizeof (retval)));
148 }
149 
150 /*
151  * Remap a given link ID to a new name.
152  */
153 dladm_status_t
154 dladm_remap_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
155     const char *link)
156 {
157 	dlmgmt_door_remapid_t	remapid;
158 	dlmgmt_remapid_retval_t	retval;
159 
160 	remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
161 	remapid.ld_linkid = linkid;
162 	(void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
163 
164 	return (dladm_door_call(handle, &remapid, sizeof (remapid), &retval,
165 	    sizeof (retval)));
166 }
167 
168 /*
169  * Make a given link ID active.
170  */
171 dladm_status_t
172 dladm_up_datalink_id(dladm_handle_t handle, datalink_id_t linkid)
173 {
174 	dlmgmt_door_upid_t	upid;
175 	dlmgmt_upid_retval_t	retval;
176 
177 	upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
178 	upid.ld_linkid = linkid;
179 
180 	return (dladm_door_call(handle, &upid, sizeof (upid), &retval,
181 	    sizeof (retval)));
182 }
183 
184 /*
185  * Create a new link with the given name.  Return the new link's handle
186  */
187 dladm_status_t
188 dladm_create_conf(dladm_handle_t handle, const char *link, datalink_id_t linkid,
189     datalink_class_t class, uint32_t media, dladm_conf_t *confp)
190 {
191 	dlmgmt_door_createconf_t	createconf;
192 	dlmgmt_createconf_retval_t	retval;
193 	dladm_status_t			status;
194 
195 	if (link == NULL || confp == NULL)
196 		return (DLADM_STATUS_BADARG);
197 
198 	(void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
199 	createconf.ld_class = class;
200 	createconf.ld_media = media;
201 	createconf.ld_linkid = linkid;
202 	createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
203 
204 	if ((status = dladm_door_call(handle, &createconf, sizeof (createconf),
205 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
206 		*confp = retval.lr_conf;
207 	}
208 	return (status);
209 }
210 
211 /*
212  * An active physical link reported by the dlmgmtd daemon might not be active
213  * anymore as this link might be removed during system shutdown. Check its
214  * real status by calling dladm_phys_info().
215  */
216 dladm_status_t
217 i_dladm_phys_status(dladm_handle_t handle, datalink_id_t linkid,
218     uint32_t *flagsp)
219 {
220 	dladm_phys_attr_t	dpa;
221 	dladm_status_t		status;
222 
223 	assert((*flagsp) & DLMGMT_ACTIVE);
224 
225 	status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE);
226 	if (status == DLADM_STATUS_NOTFOUND) {
227 		/*
228 		 * No active status, this link was removed. Update its status
229 		 * in the daemon and delete all active linkprops.
230 		 *
231 		 * Note that the operation could fail. If it does, return
232 		 * failure now since otherwise dladm_set_linkprop() might
233 		 * call back to i_dladm_phys_status() recursively.
234 		 */
235 		if ((status = dladm_destroy_datalink_id(handle, linkid,
236 		    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
237 			return (status);
238 
239 		(void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
240 		    DLADM_OPT_ACTIVE);
241 
242 		(*flagsp) &= ~DLMGMT_ACTIVE;
243 		status = DLADM_STATUS_OK;
244 	}
245 	return (status);
246 }
247 
248 /*
249  * Walk each entry in the data link configuration repository and
250  * call fn on the linkid and arg.
251  */
252 dladm_status_t
253 dladm_walk_datalink_id(int (*fn)(dladm_handle_t, datalink_id_t, void *),
254     dladm_handle_t handle, void *argp, datalink_class_t class,
255     datalink_media_t dmedia, uint32_t flags)
256 {
257 	dlmgmt_door_getnext_t	getnext;
258 	dlmgmt_getnext_retval_t	retval;
259 	uint32_t 		dlmgmt_flags;
260 	datalink_id_t		linkid = DATALINK_INVALID_LINKID;
261 	dladm_status_t		status = DLADM_STATUS_OK;
262 
263 	if (fn == NULL)
264 		return (DLADM_STATUS_BADARG);
265 
266 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
267 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
268 
269 	getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
270 	getnext.ld_class = class;
271 	getnext.ld_dmedia = dmedia;
272 	getnext.ld_flags = dlmgmt_flags;
273 
274 	do {
275 		getnext.ld_linkid = linkid;
276 		if ((status = dladm_door_call(handle, &getnext,
277 		    sizeof (getnext), &retval, sizeof (retval))) !=
278 		    DLADM_STATUS_OK) {
279 			/*
280 			 * Done with walking. If no next datalink is found,
281 			 * return success.
282 			 */
283 			if (status == DLADM_STATUS_NOTFOUND)
284 				status = DLADM_STATUS_OK;
285 			break;
286 		}
287 
288 		linkid = retval.lr_linkid;
289 		if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
290 		    (retval.lr_flags & DLMGMT_ACTIVE)) {
291 			/*
292 			 * An active physical link reported by the dlmgmtd
293 			 * daemon might not be active anymore. Check its
294 			 * real status.
295 			 */
296 			if (i_dladm_phys_status(handle, linkid,
297 			    &retval.lr_flags) != DLADM_STATUS_OK) {
298 				continue;
299 			}
300 
301 			if (!(dlmgmt_flags & retval.lr_flags))
302 				continue;
303 		}
304 
305 		if (fn(handle, linkid, argp) == DLADM_WALK_TERMINATE)
306 			break;
307 	} while (linkid != DATALINK_INVALID_LINKID);
308 
309 	return (status);
310 }
311 
312 /*
313  * Get the link properties structure for the given link.
314  */
315 dladm_status_t
316 dladm_read_conf(dladm_handle_t handle, datalink_id_t linkid,
317     dladm_conf_t *confp)
318 {
319 	dlmgmt_door_readconf_t		readconf;
320 	dlmgmt_readconf_retval_t	retval;
321 	dladm_status_t			status;
322 
323 	if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
324 		return (DLADM_STATUS_BADARG);
325 
326 	readconf.ld_linkid = linkid;
327 	readconf.ld_cmd = DLMGMT_CMD_READCONF;
328 
329 	if ((status = dladm_door_call(handle, &readconf, sizeof (readconf),
330 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
331 		*confp = retval.lr_conf;
332 	}
333 	return (status);
334 }
335 
336 /*
337  * Commit the given link to the data link configuration repository so
338  * that it will persist across reboots.
339  */
340 dladm_status_t
341 dladm_write_conf(dladm_handle_t handle, dladm_conf_t conf)
342 {
343 	dlmgmt_door_writeconf_t		writeconf;
344 	dlmgmt_writeconf_retval_t	retval;
345 
346 	if (conf == DLADM_INVALID_CONF)
347 		return (DLADM_STATUS_BADARG);
348 
349 	writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
350 	writeconf.ld_conf = conf;
351 
352 	return (dladm_door_call(handle, &writeconf, sizeof (writeconf), &retval,
353 	    sizeof (retval)));
354 }
355 
356 /*
357  * Given a link ID and a key, get the matching information from
358  * data link configuration repository.
359  */
360 dladm_status_t
361 dladm_get_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr,
362     void *attrval, size_t attrsz)
363 {
364 	dlmgmt_door_getattr_t	getattr;
365 	dlmgmt_getattr_retval_t	retval;
366 	dladm_status_t		status;
367 
368 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
369 	    attrsz == 0 || attr == NULL) {
370 		return (DLADM_STATUS_BADARG);
371 	}
372 
373 	getattr.ld_cmd = DLMGMT_CMD_GETATTR;
374 	getattr.ld_conf = conf;
375 	(void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
376 
377 	if ((status = dladm_door_call(handle, &getattr, sizeof (getattr),
378 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
379 		return (status);
380 	}
381 
382 	if (retval.lr_attrsz > attrsz)
383 		return (DLADM_STATUS_TOOSMALL);
384 
385 	bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
386 	return (DLADM_STATUS_OK);
387 }
388 
389 /*
390  * Get next property attribute from data link configuration repository.
391  */
392 dladm_status_t
393 dladm_getnext_conf_linkprop(dladm_handle_t handle, dladm_conf_t conf,
394     const char *last_attr, char *attr, void *attrval, size_t attrsz,
395     size_t *attrszp)
396 {
397 	dlmgmt_door_linkprop_getnext_t		getnext;
398 	dlmgmt_linkprop_getnext_retval_t	retval;
399 	dladm_status_t				status;
400 
401 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
402 	    attrsz == 0 || attr == NULL) {
403 		return (DLADM_STATUS_BADARG);
404 	}
405 
406 	getnext.ld_cmd = DLMGMT_CMD_LINKPROP_GETNEXT;
407 	getnext.ld_conf = conf;
408 	(void) strlcpy(getnext.ld_last_attr, last_attr, MAXLINKATTRLEN);
409 
410 	if ((status = dladm_door_call(handle, &getnext, sizeof (getnext),
411 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
412 		return (status);
413 	}
414 
415 	*attrszp = retval.lr_attrsz;
416 	if (retval.lr_attrsz > attrsz) {
417 		return (DLADM_STATUS_TOOSMALL);
418 	}
419 
420 	(void) strlcpy(attr, retval.lr_attr, MAXLINKATTRLEN);
421 	bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
422 	return (DLADM_STATUS_OK);
423 }
424 
425 /*
426  * Get the link ID that is associated with the given name.
427  */
428 dladm_status_t
429 dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp,
430     uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap)
431 {
432 	dlmgmt_door_getlinkid_t		getlinkid;
433 	dlmgmt_getlinkid_retval_t	retval;
434 	datalink_id_t			linkid;
435 	dladm_status_t			status;
436 
437 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
438 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
439 
440 	if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid),
441 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
442 		return (status);
443 	}
444 
445 	linkid = retval.lr_linkid;
446 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
447 	    retval.lr_flags & DLMGMT_ACTIVE) {
448 		/*
449 		 * An active physical link reported by the dlmgmtd daemon
450 		 * might not be active anymore. Check and set its real status.
451 		 */
452 		status = i_dladm_phys_status(handle, linkid, &retval.lr_flags);
453 		if (status != DLADM_STATUS_OK)
454 			return (status);
455 	}
456 
457 	if (linkidp != NULL)
458 		*linkidp = linkid;
459 	if (flagp != NULL) {
460 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
461 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
462 		    DLADM_OPT_PERSIST : 0;
463 	}
464 	if (classp != NULL)
465 		*classp = retval.lr_class;
466 	if (mediap != NULL)
467 		*mediap = retval.lr_media;
468 
469 	return (DLADM_STATUS_OK);
470 }
471 
472 /*
473  * Get the link name that is associated with the given id.
474  */
475 dladm_status_t
476 dladm_datalink_id2info(dladm_handle_t handle, datalink_id_t linkid,
477     uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap, char *link,
478     size_t len)
479 {
480 	dlmgmt_door_getname_t	getname;
481 	dlmgmt_getname_retval_t	retval;
482 	dladm_status_t		status;
483 
484 	if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) ||
485 	    (link == NULL && len != 0)) {
486 		return (DLADM_STATUS_BADARG);
487 	}
488 
489 	getname.ld_cmd = DLMGMT_CMD_GETNAME;
490 	getname.ld_linkid = linkid;
491 	if ((status = dladm_door_call(handle, &getname, sizeof (getname),
492 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
493 		return (status);
494 	}
495 
496 	if (len != 0 && (strlen(retval.lr_link) + 1 > len))
497 		return (DLADM_STATUS_TOOSMALL);
498 
499 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
500 	    retval.lr_flags & DLMGMT_ACTIVE) {
501 		/*
502 		 * An active physical link reported by the dlmgmtd daemon
503 		 * might not be active anymore. Check and set its real status.
504 		 */
505 		status = i_dladm_phys_status(handle, linkid, &retval.lr_flags);
506 		if (status != DLADM_STATUS_OK)
507 			return (status);
508 	}
509 
510 	if (link != NULL)
511 		(void) strlcpy(link, retval.lr_link, len);
512 	if (classp != NULL)
513 		*classp = retval.lr_class;
514 	if (mediap != NULL)
515 		*mediap = retval.lr_media;
516 	if (flagp != NULL) {
517 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ?
518 		    DLADM_OPT_ACTIVE : 0;
519 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
520 		    DLADM_OPT_PERSIST : 0;
521 	}
522 	return (DLADM_STATUS_OK);
523 }
524 
525 /*
526  * Set the given attr with the given attrval for the given link.
527  */
528 dladm_status_t
529 dladm_set_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr,
530     dladm_datatype_t type, const void *attrval)
531 {
532 	dlmgmt_door_setattr_t	setattr;
533 	dlmgmt_setattr_retval_t	retval;
534 	size_t			attrsz;
535 
536 	if (attr == NULL || attrval == NULL)
537 		return (DLADM_STATUS_BADARG);
538 
539 	if (type == DLADM_TYPE_STR)
540 		attrsz = strlen(attrval) + 1;
541 	else
542 		attrsz = dladm_datatype_size[type];
543 
544 	if (attrsz > MAXLINKATTRVALLEN)
545 		return (DLADM_STATUS_TOOSMALL);
546 
547 	setattr.ld_cmd = DLMGMT_CMD_SETATTR;
548 	setattr.ld_conf = conf;
549 	(void) strlcpy(setattr.ld_attr, attr, MAXLINKATTRLEN);
550 	setattr.ld_attrsz = attrsz;
551 	setattr.ld_type = type;
552 	bcopy(attrval, &setattr.ld_attrval, attrsz);
553 
554 	return (dladm_door_call(handle, &setattr, sizeof (setattr), &retval,
555 	    sizeof (retval)));
556 }
557 
558 /*
559  * Unset the given attr the given link.
560  */
561 dladm_status_t
562 dladm_unset_conf_field(dladm_handle_t handle, dladm_conf_t conf,
563     const char *attr)
564 {
565 	dlmgmt_door_unsetattr_t		unsetattr;
566 	dlmgmt_unsetattr_retval_t	retval;
567 
568 	if (attr == NULL)
569 		return (DLADM_STATUS_BADARG);
570 
571 	unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR;
572 	unsetattr.ld_conf = conf;
573 	(void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN);
574 
575 	return (dladm_door_call(handle, &unsetattr, sizeof (unsetattr), &retval,
576 	    sizeof (retval)));
577 }
578 
579 /*
580  * Remove the given link ID and its entry from the data link configuration
581  * repository.
582  */
583 dladm_status_t
584 dladm_remove_conf(dladm_handle_t handle, datalink_id_t linkid)
585 {
586 	dlmgmt_door_removeconf_t	removeconf;
587 	dlmgmt_removeconf_retval_t	retval;
588 
589 	removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF;
590 	removeconf.ld_linkid = linkid;
591 
592 	return (dladm_door_call(handle, &removeconf, sizeof (removeconf),
593 	    &retval, sizeof (retval)));
594 }
595 
596 /*
597  * Free the contents of the link structure.
598  */
599 void
600 dladm_destroy_conf(dladm_handle_t handle, dladm_conf_t conf)
601 {
602 	dlmgmt_door_destroyconf_t	destroyconf;
603 	dlmgmt_destroyconf_retval_t	retval;
604 
605 	if (conf == DLADM_INVALID_CONF)
606 		return;
607 
608 	destroyconf.ld_cmd = DLMGMT_CMD_DESTROYCONF;
609 	destroyconf.ld_conf = conf;
610 
611 	(void) dladm_door_call(handle, &destroyconf, sizeof (destroyconf),
612 	    &retval, sizeof (retval));
613 }
614 
615 dladm_status_t
616 dladm_zone_boot(dladm_handle_t handle, zoneid_t zoneid)
617 {
618 	dlmgmt_door_zoneboot_t		zoneboot;
619 	dlmgmt_zoneboot_retval_t	retval;
620 
621 	zoneboot.ld_cmd = DLMGMT_CMD_ZONEBOOT;
622 	zoneboot.ld_zoneid = zoneid;
623 	return (dladm_door_call(handle, &zoneboot, sizeof (zoneboot), &retval,
624 	    sizeof (retval)));
625 }
626 
627 dladm_status_t
628 dladm_zone_halt(dladm_handle_t handle, zoneid_t zoneid)
629 {
630 	dlmgmt_door_zonehalt_t		zonehalt;
631 	dlmgmt_zonehalt_retval_t	retval;
632 
633 	zonehalt.ld_cmd = DLMGMT_CMD_ZONEHALT;
634 	zonehalt.ld_zoneid = zoneid;
635 	return (dladm_door_call(handle, &zonehalt, sizeof (zonehalt), &retval,
636 	    sizeof (retval)));
637 }
638