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