1d62bc4baSyz /*
2d62bc4baSyz  * CDDL HEADER START
3d62bc4baSyz  *
4d62bc4baSyz  * The contents of this file are subject to the terms of the
5d62bc4baSyz  * Common Development and Distribution License (the "License").
6d62bc4baSyz  * You may not use this file except in compliance with the License.
7d62bc4baSyz  *
8d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10d62bc4baSyz  * See the License for the specific language governing permissions
11d62bc4baSyz  * and limitations under the License.
12d62bc4baSyz  *
13d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18d62bc4baSyz  *
19d62bc4baSyz  * CDDL HEADER END
20d62bc4baSyz  */
21d62bc4baSyz /*
22d62bc4baSyz  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23d62bc4baSyz  * Use is subject to license terms.
24d62bc4baSyz  */
25d62bc4baSyz 
26d62bc4baSyz #include <door.h>
27d62bc4baSyz #include <errno.h>
28d62bc4baSyz #include <assert.h>
29d62bc4baSyz #include <stdio.h>
30d62bc4baSyz #include <stdlib.h>
31d62bc4baSyz #include <unistd.h>
32d62bc4baSyz #include <string.h>
33d62bc4baSyz #include <strings.h>
34d62bc4baSyz #include <sys/types.h>
35d62bc4baSyz #include <sys/stat.h>
36d62bc4baSyz #include <sys/aggr.h>
37d62bc4baSyz #include <fcntl.h>
38d62bc4baSyz #include <libdladm.h>
39d62bc4baSyz #include <libdladm_impl.h>
40d62bc4baSyz #include <libdllink.h>
41d62bc4baSyz #include <libdlmgmt.h>
42d62bc4baSyz 
43d62bc4baSyz /*
44d62bc4baSyz  * Table of data type sizes indexed by dladm_datatype_t.
45d62bc4baSyz  */
46d62bc4baSyz static size_t dladm_datatype_size[] = {
47d62bc4baSyz 	0,				/* DLADM_TYPE_STR, use strnlen() */
48d62bc4baSyz 	sizeof (boolean_t),		/* DLADM_TYPE_BOOLEAN */
49d62bc4baSyz 	sizeof (uint64_t)		/* DLADM_TYPE_UINT64 */
50d62bc4baSyz };
51d62bc4baSyz 
52d62bc4baSyz static dladm_status_t
53024b0a25Sseb dladm_door_call(void *arg, size_t asize, void *rbuf, size_t rsize)
54d62bc4baSyz {
55d62bc4baSyz 	door_arg_t	darg;
56d62bc4baSyz 	int		fd;
57d62bc4baSyz 	dladm_status_t	status = DLADM_STATUS_OK;
58d62bc4baSyz 
59d62bc4baSyz 	if ((fd = open(DLMGMT_DOOR, O_RDONLY)) == -1)
60d62bc4baSyz 		return (dladm_errno2status(errno));
61d62bc4baSyz 
62d62bc4baSyz 	darg.data_ptr	= arg;
63d62bc4baSyz 	darg.data_size	= asize;
64d62bc4baSyz 	darg.desc_ptr	= NULL;
65d62bc4baSyz 	darg.desc_num	= 0;
66d62bc4baSyz 	darg.rbuf	= rbuf;
67024b0a25Sseb 	darg.rsize	= rsize;
68d62bc4baSyz 
69d62bc4baSyz 	if (door_call(fd, &darg) == -1)
70d62bc4baSyz 		status = dladm_errno2status(errno);
71d62bc4baSyz 	(void) close(fd);
72d62bc4baSyz 
73d62bc4baSyz 	if (status != DLADM_STATUS_OK)
74d62bc4baSyz 		return (status);
75d62bc4baSyz 
76d62bc4baSyz 	if (darg.rbuf != rbuf) {
77d62bc4baSyz 		/*
78d62bc4baSyz 		 * The size of the input rbuf is not big enough so that
79d62bc4baSyz 		 * the door allocate the rbuf itself. In this case, simply
80d62bc4baSyz 		 * think something wrong with the door call.
81d62bc4baSyz 		 */
82d62bc4baSyz 		(void) munmap(darg.rbuf, darg.rsize);
83d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
84d62bc4baSyz 	}
85024b0a25Sseb 	if (darg.rsize != rsize)
86d62bc4baSyz 		return (DLADM_STATUS_FAILED);
87d62bc4baSyz 
88024b0a25Sseb 	return (dladm_errno2status(((dlmgmt_retval_t *)rbuf)->lr_err));
89d62bc4baSyz }
90d62bc4baSyz 
91d62bc4baSyz /*
92d62bc4baSyz  * Allocate a new linkid with the given name. Return the new linkid.
93d62bc4baSyz  */
94d62bc4baSyz dladm_status_t
95d62bc4baSyz dladm_create_datalink_id(const char *link, datalink_class_t class,
96d62bc4baSyz     uint32_t media, uint32_t flags, datalink_id_t *linkidp)
97d62bc4baSyz {
98024b0a25Sseb 	dlmgmt_door_createid_t	createid;
99d62bc4baSyz 	dlmgmt_createid_retval_t retval;
100024b0a25Sseb 	uint32_t		dlmgmt_flags;
101024b0a25Sseb 	dladm_status_t		status;
102d62bc4baSyz 
103024b0a25Sseb 	if (link == NULL || class == DATALINK_CLASS_ALL ||
104d62bc4baSyz 	    !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
105d62bc4baSyz 	    linkidp == NULL) {
106d62bc4baSyz 		return (DLADM_STATUS_BADARG);
107d62bc4baSyz 	}
108d62bc4baSyz 
109d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
110d62bc4baSyz 	dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
111d62bc4baSyz 
112d62bc4baSyz 	(void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
113d62bc4baSyz 	createid.ld_class = class;
114d62bc4baSyz 	createid.ld_media = media;
115d62bc4baSyz 	createid.ld_flags = dlmgmt_flags;
116d62bc4baSyz 	createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
117d62bc4baSyz 	createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
118d62bc4baSyz 
119024b0a25Sseb 	if ((status = dladm_door_call(&createid, sizeof (createid), &retval,
120024b0a25Sseb 	    sizeof (retval))) == DLADM_STATUS_OK) {
121024b0a25Sseb 		*linkidp = retval.lr_linkid;
122024b0a25Sseb 	}
123024b0a25Sseb 	return (status);
124d62bc4baSyz }
125d62bc4baSyz 
126d62bc4baSyz /*
127d62bc4baSyz  * Destroy the given link ID.
128d62bc4baSyz  */
129d62bc4baSyz dladm_status_t
130d62bc4baSyz dladm_destroy_datalink_id(datalink_id_t linkid, uint32_t flags)
131d62bc4baSyz {
132d62bc4baSyz 	dlmgmt_door_destroyid_t		destroyid;
133d62bc4baSyz 	dlmgmt_destroyid_retval_t	retval;
134d62bc4baSyz 	uint32_t			dlmgmt_flags;
135d62bc4baSyz 
136d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
137d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
138d62bc4baSyz 
139d62bc4baSyz 	destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
140d62bc4baSyz 	destroyid.ld_linkid = linkid;
141d62bc4baSyz 	destroyid.ld_flags = dlmgmt_flags;
142d62bc4baSyz 
143024b0a25Sseb 	return (dladm_door_call(&destroyid, sizeof (destroyid),
144024b0a25Sseb 	    &retval, sizeof (retval)));
145d62bc4baSyz }
146d62bc4baSyz 
147d62bc4baSyz /*
148d62bc4baSyz  * Remap a given link ID to a new name.
149d62bc4baSyz  */
150d62bc4baSyz dladm_status_t
151d62bc4baSyz dladm_remap_datalink_id(datalink_id_t linkid, const char *link)
152d62bc4baSyz {
153d62bc4baSyz 	dlmgmt_door_remapid_t	remapid;
154d62bc4baSyz 	dlmgmt_remapid_retval_t	retval;
155d62bc4baSyz 
156d62bc4baSyz 	remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
157d62bc4baSyz 	remapid.ld_linkid = linkid;
158d62bc4baSyz 	(void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
159d62bc4baSyz 
160024b0a25Sseb 	return (dladm_door_call(&remapid, sizeof (remapid),
161024b0a25Sseb 	    &retval, sizeof (retval)));
162d62bc4baSyz }
163d62bc4baSyz 
164d62bc4baSyz /*
165d62bc4baSyz  * Make a given link ID active.
166d62bc4baSyz  */
167d62bc4baSyz dladm_status_t
168d62bc4baSyz dladm_up_datalink_id(datalink_id_t linkid)
169d62bc4baSyz {
170024b0a25Sseb 	dlmgmt_door_upid_t	upid;
171024b0a25Sseb 	dlmgmt_upid_retval_t	retval;
172d62bc4baSyz 
173d62bc4baSyz 	upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
174d62bc4baSyz 	upid.ld_linkid = linkid;
175d62bc4baSyz 
176024b0a25Sseb 	return (dladm_door_call(&upid, sizeof (upid),
177024b0a25Sseb 	    &retval, sizeof (retval)));
178d62bc4baSyz }
179d62bc4baSyz 
180d62bc4baSyz /*
181d62bc4baSyz  * Create a new link with the given name.  Return the new link's handle
182d62bc4baSyz  */
183d62bc4baSyz dladm_status_t
184d62bc4baSyz dladm_create_conf(const char *link, datalink_id_t linkid,
185d62bc4baSyz     datalink_class_t class, uint32_t media, dladm_conf_t *confp)
186d62bc4baSyz {
187024b0a25Sseb 	dlmgmt_door_createconf_t	createconf;
188024b0a25Sseb 	dlmgmt_createconf_retval_t	retval;
189024b0a25Sseb 	dladm_status_t			status;
190d62bc4baSyz 
191024b0a25Sseb 	if (link == NULL || confp == NULL)
192d62bc4baSyz 		return (DLADM_STATUS_BADARG);
193d62bc4baSyz 
194d62bc4baSyz 	(void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
195d62bc4baSyz 	createconf.ld_class = class;
196d62bc4baSyz 	createconf.ld_media = media;
197d62bc4baSyz 	createconf.ld_linkid = linkid;
198d62bc4baSyz 	createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
199d62bc4baSyz 
200024b0a25Sseb 	if ((status = dladm_door_call(&createconf, sizeof (createconf),
201024b0a25Sseb 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
202024b0a25Sseb 		*confp = retval.lr_conf;
203024b0a25Sseb 	}
204024b0a25Sseb 	return (status);
205d62bc4baSyz }
206d62bc4baSyz 
207d62bc4baSyz /*
208d62bc4baSyz  * An active physical link reported by the dlmgmtd daemon might not be active
209d62bc4baSyz  * anymore as this link might be removed during system shutdown. Check its
210d62bc4baSyz  * real status by calling dladm_phys_info().
211d62bc4baSyz  */
212d62bc4baSyz dladm_status_t
213d62bc4baSyz i_dladm_phys_status(datalink_id_t linkid, uint32_t *flagsp)
214d62bc4baSyz {
215d62bc4baSyz 	dladm_phys_attr_t	dpa;
216d62bc4baSyz 	dladm_status_t		status;
217d62bc4baSyz 
218d62bc4baSyz 	assert((*flagsp) & DLMGMT_ACTIVE);
219d62bc4baSyz 
220d62bc4baSyz 	status = dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE);
221d62bc4baSyz 	if (status == DLADM_STATUS_NOTFOUND) {
222d62bc4baSyz 		/*
223d62bc4baSyz 		 * No active status, this link was removed. Update its status
224d62bc4baSyz 		 * in the daemon and delete all active linkprops.
225*2d4eecfaSCathy Zhou 		 *
226*2d4eecfaSCathy Zhou 		 * Note that the operation could fail. If it does, return
227*2d4eecfaSCathy Zhou 		 * failure now since otherwise dladm_set_linkprop() might
228*2d4eecfaSCathy Zhou 		 * call back to i_dladm_phys_status() recursively.
229d62bc4baSyz 		 */
230*2d4eecfaSCathy Zhou 		status = dladm_destroy_datalink_id(linkid, DLADM_OPT_ACTIVE);
231*2d4eecfaSCathy Zhou 		if (status != DLADM_STATUS_OK)
232*2d4eecfaSCathy Zhou 			return (status);
233*2d4eecfaSCathy Zhou 
234d62bc4baSyz 		(void) dladm_set_linkprop(linkid, NULL, NULL, 0,
235d62bc4baSyz 		    DLADM_OPT_ACTIVE);
236d62bc4baSyz 
237d62bc4baSyz 		(*flagsp) &= ~DLMGMT_ACTIVE;
238d62bc4baSyz 		status = DLADM_STATUS_OK;
239d62bc4baSyz 	}
240d62bc4baSyz 	return (status);
241d62bc4baSyz }
242d62bc4baSyz 
243d62bc4baSyz /*
244d62bc4baSyz  * Walk each entry in the data link configuration repository and
245d62bc4baSyz  * call fn on the linkid and arg.
246d62bc4baSyz  */
247d62bc4baSyz dladm_status_t
248d62bc4baSyz dladm_walk_datalink_id(int (*fn)(datalink_id_t, void *), void *argp,
249d62bc4baSyz     datalink_class_t class, datalink_media_t dmedia, uint32_t flags)
250d62bc4baSyz {
251d62bc4baSyz 	dlmgmt_door_getnext_t	getnext;
252d62bc4baSyz 	dlmgmt_getnext_retval_t	retval;
253d62bc4baSyz 	uint32_t 		dlmgmt_flags;
254d62bc4baSyz 	datalink_id_t		linkid = DATALINK_INVALID_LINKID;
255d62bc4baSyz 	dladm_status_t		status = DLADM_STATUS_OK;
256d62bc4baSyz 
257d62bc4baSyz 	if (fn == NULL)
258d62bc4baSyz 		return (DLADM_STATUS_BADARG);
259d62bc4baSyz 
260d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
261d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
262d62bc4baSyz 
263d62bc4baSyz 	getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
264d62bc4baSyz 	getnext.ld_class = class;
265d62bc4baSyz 	getnext.ld_dmedia = dmedia;
266d62bc4baSyz 	getnext.ld_flags = dlmgmt_flags;
267d62bc4baSyz 
268d62bc4baSyz 	do {
269d62bc4baSyz 		getnext.ld_linkid = linkid;
270024b0a25Sseb 		if ((status = dladm_door_call(&getnext, sizeof (getnext),
271024b0a25Sseb 		    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
272d62bc4baSyz 			/*
273d62bc4baSyz 			 * done with walking
274d62bc4baSyz 			 */
275d62bc4baSyz 			break;
276d62bc4baSyz 		}
277d62bc4baSyz 
278d62bc4baSyz 		linkid = retval.lr_linkid;
279d62bc4baSyz 		if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
280d62bc4baSyz 		    (retval.lr_flags & DLMGMT_ACTIVE)) {
281d62bc4baSyz 			/*
282d62bc4baSyz 			 * An active physical link reported by the dlmgmtd
283d62bc4baSyz 			 * daemon might not be active anymore. Check its
284d62bc4baSyz 			 * real status.
285d62bc4baSyz 			 */
286d62bc4baSyz 			if (i_dladm_phys_status(linkid, &retval.lr_flags) !=
287d62bc4baSyz 			    DLADM_STATUS_OK) {
288d62bc4baSyz 				continue;
289d62bc4baSyz 			}
290d62bc4baSyz 
291d62bc4baSyz 			if (!(dlmgmt_flags & retval.lr_flags))
292d62bc4baSyz 				continue;
293d62bc4baSyz 		}
294d62bc4baSyz 
295d62bc4baSyz 		if (fn(linkid, argp) == DLADM_WALK_TERMINATE)
296d62bc4baSyz 			break;
297d62bc4baSyz 	} while (linkid != DATALINK_INVALID_LINKID);
298d62bc4baSyz 
299d62bc4baSyz 	return (status);
300d62bc4baSyz }
301d62bc4baSyz 
302d62bc4baSyz /*
303d62bc4baSyz  * Get the link properties structure for the given link.
304d62bc4baSyz  */
305d62bc4baSyz dladm_status_t
306d62bc4baSyz dladm_read_conf(datalink_id_t linkid, dladm_conf_t *confp)
307d62bc4baSyz {
308024b0a25Sseb 	dlmgmt_door_readconf_t		readconf;
309d62bc4baSyz 	dlmgmt_readconf_retval_t	retval;
310d62bc4baSyz 	dladm_status_t			status;
311d62bc4baSyz 
312d62bc4baSyz 	if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
313d62bc4baSyz 		return (DLADM_STATUS_BADARG);
314d62bc4baSyz 
315d62bc4baSyz 	readconf.ld_linkid = linkid;
316d62bc4baSyz 	readconf.ld_cmd = DLMGMT_CMD_READCONF;
317d62bc4baSyz 
318024b0a25Sseb 	if ((status = dladm_door_call(&readconf, sizeof (readconf),
319024b0a25Sseb 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
320024b0a25Sseb 		*confp = retval.lr_conf;
321024b0a25Sseb 	}
322024b0a25Sseb 	return (status);
323d62bc4baSyz }
324d62bc4baSyz 
325d62bc4baSyz /*
326d62bc4baSyz  * Commit the given link to the data link configuration repository so
327d62bc4baSyz  * that it will persist across reboots.
328d62bc4baSyz  */
329d62bc4baSyz dladm_status_t
330d62bc4baSyz dladm_write_conf(dladm_conf_t conf)
331d62bc4baSyz {
332d62bc4baSyz 	dlmgmt_door_writeconf_t		writeconf;
333d62bc4baSyz 	dlmgmt_writeconf_retval_t	retval;
334d62bc4baSyz 
335d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
336d62bc4baSyz 		return (DLADM_STATUS_BADARG);
337d62bc4baSyz 
338d62bc4baSyz 	writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
339d62bc4baSyz 	writeconf.ld_conf = conf;
340d62bc4baSyz 
341024b0a25Sseb 	return (dladm_door_call(&writeconf, sizeof (writeconf),
342024b0a25Sseb 	    &retval, sizeof (retval)));
343d62bc4baSyz }
344d62bc4baSyz 
345d62bc4baSyz /*
346d62bc4baSyz  * Given a link ID and a key, get the matching information from
347d62bc4baSyz  * data link configuration repository.
348d62bc4baSyz  */
349d62bc4baSyz dladm_status_t
350d62bc4baSyz dladm_get_conf_field(dladm_conf_t conf, const char *attr, void *attrval,
351d62bc4baSyz     size_t attrsz)
352d62bc4baSyz {
353024b0a25Sseb 	dlmgmt_door_getattr_t	getattr;
354024b0a25Sseb 	dlmgmt_getattr_retval_t	retval;
355024b0a25Sseb 	dladm_status_t		status;
356d62bc4baSyz 
357d62bc4baSyz 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
358024b0a25Sseb 	    attrsz == 0 || attr == NULL) {
359d62bc4baSyz 		return (DLADM_STATUS_BADARG);
360d62bc4baSyz 	}
361d62bc4baSyz 
362d62bc4baSyz 	getattr.ld_cmd = DLMGMT_CMD_GETATTR;
363d62bc4baSyz 	getattr.ld_conf = conf;
364d62bc4baSyz 	(void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
365d62bc4baSyz 
366024b0a25Sseb 	if ((status = dladm_door_call(&getattr, sizeof (getattr), &retval,
367024b0a25Sseb 	    sizeof (retval))) != DLADM_STATUS_OK) {
368024b0a25Sseb 		return (status);
369024b0a25Sseb 	}
370d62bc4baSyz 
371024b0a25Sseb 	if (retval.lr_attrsz > attrsz)
372024b0a25Sseb 		return (DLADM_STATUS_TOOSMALL);
373d62bc4baSyz 
374024b0a25Sseb 	bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
375024b0a25Sseb 	return (DLADM_STATUS_OK);
376d62bc4baSyz }
377d62bc4baSyz 
378d62bc4baSyz /*
379d62bc4baSyz  * Get the link ID that is associated with the given name.
380d62bc4baSyz  */
381d62bc4baSyz dladm_status_t
382d62bc4baSyz dladm_name2info(const char *link, datalink_id_t *linkidp, uint32_t *flagp,
383d62bc4baSyz     datalink_class_t *classp, uint32_t *mediap)
384d62bc4baSyz {
385d62bc4baSyz 	dlmgmt_door_getlinkid_t		getlinkid;
386d62bc4baSyz 	dlmgmt_getlinkid_retval_t	retval;
387d62bc4baSyz 	datalink_id_t			linkid;
388d62bc4baSyz 	dladm_status_t			status;
389d62bc4baSyz 
390d62bc4baSyz 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
391d62bc4baSyz 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
392d62bc4baSyz 
393024b0a25Sseb 	if ((status = dladm_door_call(&getlinkid, sizeof (getlinkid),
394024b0a25Sseb 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
395d62bc4baSyz 		return (status);
396024b0a25Sseb 	}
397d62bc4baSyz 
398d62bc4baSyz 	linkid = retval.lr_linkid;
399d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
400d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
401d62bc4baSyz 		/*
402d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
403d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
404d62bc4baSyz 		 */
405d62bc4baSyz 		status = i_dladm_phys_status(linkid, &retval.lr_flags);
406d62bc4baSyz 		if (status != DLADM_STATUS_OK)
407d62bc4baSyz 			return (status);
408d62bc4baSyz 	}
409d62bc4baSyz 
410d62bc4baSyz 	if (linkidp != NULL)
411d62bc4baSyz 		*linkidp = linkid;
412d62bc4baSyz 	if (flagp != NULL) {
413d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
414d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
415d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
416d62bc4baSyz 	}
417d62bc4baSyz 	if (classp != NULL)
418d62bc4baSyz 		*classp = retval.lr_class;
419d62bc4baSyz 	if (mediap != NULL)
420d62bc4baSyz 		*mediap = retval.lr_media;
421d62bc4baSyz 
422d62bc4baSyz 	return (DLADM_STATUS_OK);
423d62bc4baSyz }
424d62bc4baSyz 
425d62bc4baSyz /*
426d62bc4baSyz  * Get the link name that is associated with the given id.
427d62bc4baSyz  */
428d62bc4baSyz dladm_status_t
429d62bc4baSyz dladm_datalink_id2info(datalink_id_t linkid, uint32_t *flagp,
430d62bc4baSyz     datalink_class_t *classp, uint32_t *mediap, char *link, size_t len)
431d62bc4baSyz {
432024b0a25Sseb 	dlmgmt_door_getname_t	getname;
433024b0a25Sseb 	dlmgmt_getname_retval_t	retval;
434024b0a25Sseb 	dladm_status_t		status;
435d62bc4baSyz 
436d62bc4baSyz 	if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) ||
437d62bc4baSyz 	    (link == NULL && len != 0)) {
438d62bc4baSyz 		return (DLADM_STATUS_BADARG);
439d62bc4baSyz 	}
440d62bc4baSyz 
441d62bc4baSyz 	getname.ld_cmd = DLMGMT_CMD_GETNAME;
442d62bc4baSyz 	getname.ld_linkid = linkid;
443024b0a25Sseb 	if ((status = dladm_door_call(&getname, sizeof (getname), &retval,
444024b0a25Sseb 	    sizeof (retval))) != DLADM_STATUS_OK) {
445d62bc4baSyz 		return (status);
446024b0a25Sseb 	}
447d62bc4baSyz 
448024b0a25Sseb 	if (len != 0 && (strlen(retval.lr_link) + 1 > len))
449d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
450d62bc4baSyz 
451d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
452d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
453d62bc4baSyz 		/*
454d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
455d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
456d62bc4baSyz 		 */
457d62bc4baSyz 		status = i_dladm_phys_status(linkid, &retval.lr_flags);
458d62bc4baSyz 		if (status != DLADM_STATUS_OK)
459d62bc4baSyz 			return (status);
460d62bc4baSyz 	}
461d62bc4baSyz 
462d62bc4baSyz 	if (link != NULL)
463d62bc4baSyz 		(void) strlcpy(link, retval.lr_link, len);
464d62bc4baSyz 	if (classp != NULL)
465d62bc4baSyz 		*classp = retval.lr_class;
466d62bc4baSyz 	if (mediap != NULL)
467d62bc4baSyz 		*mediap = retval.lr_media;
468d62bc4baSyz 	if (flagp != NULL) {
469d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ?
470d62bc4baSyz 		    DLADM_OPT_ACTIVE : 0;
471d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
472d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
473d62bc4baSyz 	}
474d62bc4baSyz 	return (DLADM_STATUS_OK);
475d62bc4baSyz }
476d62bc4baSyz 
477d62bc4baSyz /*
478d62bc4baSyz  * Set the given attr with the given attrval for the given link.
479d62bc4baSyz  */
480d62bc4baSyz dladm_status_t
481d62bc4baSyz dladm_set_conf_field(dladm_conf_t conf, const char *attr,
482d62bc4baSyz     dladm_datatype_t type, const void *attrval)
483d62bc4baSyz {
484024b0a25Sseb 	dlmgmt_door_setattr_t	setattr;
485024b0a25Sseb 	dlmgmt_setattr_retval_t	retval;
486024b0a25Sseb 	size_t			attrsz;
487d62bc4baSyz 
488024b0a25Sseb 	if (attr == NULL || attrval == NULL)
489d62bc4baSyz 		return (DLADM_STATUS_BADARG);
490d62bc4baSyz 
491d62bc4baSyz 	if (type == DLADM_TYPE_STR)
492d62bc4baSyz 		attrsz = strlen(attrval) + 1;
493d62bc4baSyz 	else
494d62bc4baSyz 		attrsz = dladm_datatype_size[type];
495d62bc4baSyz 
496024b0a25Sseb 	if (attrsz > MAXLINKATTRVALLEN)
497024b0a25Sseb 		return (DLADM_STATUS_TOOSMALL);
498d62bc4baSyz 
499024b0a25Sseb 	setattr.ld_cmd = DLMGMT_CMD_SETATTR;
500024b0a25Sseb 	setattr.ld_conf = conf;
501024b0a25Sseb 	(void) strlcpy(setattr.ld_attr, attr, MAXLINKATTRLEN);
502024b0a25Sseb 	setattr.ld_attrsz = attrsz;
503024b0a25Sseb 	setattr.ld_type = type;
504024b0a25Sseb 	bcopy(attrval, &setattr.ld_attrval, attrsz);
505d62bc4baSyz 
506024b0a25Sseb 	return (dladm_door_call(&setattr, sizeof (setattr),
507024b0a25Sseb 	    &retval, sizeof (retval)));
508d62bc4baSyz }
509d62bc4baSyz 
510d62bc4baSyz /*
511d62bc4baSyz  * Unset the given attr the given link.
512d62bc4baSyz  */
513d62bc4baSyz dladm_status_t
514d62bc4baSyz dladm_unset_conf_field(dladm_conf_t conf, const char *attr)
515d62bc4baSyz {
516d62bc4baSyz 	dlmgmt_door_unsetattr_t		unsetattr;
517d62bc4baSyz 	dlmgmt_unsetattr_retval_t	retval;
518d62bc4baSyz 
519024b0a25Sseb 	if (attr == NULL)
520d62bc4baSyz 		return (DLADM_STATUS_BADARG);
521d62bc4baSyz 
522d62bc4baSyz 	unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR;
523d62bc4baSyz 	unsetattr.ld_conf = conf;
524d62bc4baSyz 	(void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN);
525d62bc4baSyz 
526024b0a25Sseb 	return (dladm_door_call(&unsetattr, sizeof (unsetattr),
527024b0a25Sseb 	    &retval, sizeof (retval)));
528d62bc4baSyz }
529d62bc4baSyz 
530d62bc4baSyz /*
531d62bc4baSyz  * Remove the given link ID and its entry from the data link configuration
532d62bc4baSyz  * repository.
533d62bc4baSyz  */
534d62bc4baSyz dladm_status_t
535d62bc4baSyz dladm_remove_conf(datalink_id_t linkid)
536d62bc4baSyz {
537d62bc4baSyz 	dlmgmt_door_removeconf_t	removeconf;
538d62bc4baSyz 	dlmgmt_removeconf_retval_t	retval;
539d62bc4baSyz 
540d62bc4baSyz 	removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF;
541d62bc4baSyz 	removeconf.ld_linkid = linkid;
542d62bc4baSyz 
543024b0a25Sseb 	return (dladm_door_call(&removeconf, sizeof (removeconf),
544024b0a25Sseb 	    &retval, sizeof (retval)));
545d62bc4baSyz }
546d62bc4baSyz 
547d62bc4baSyz /*
548d62bc4baSyz  * Free the contents of the link structure.
549d62bc4baSyz  */
550d62bc4baSyz void
551d62bc4baSyz dladm_destroy_conf(dladm_conf_t conf)
552d62bc4baSyz {
553d62bc4baSyz 	dlmgmt_door_destroyconf_t	destroyconf;
554d62bc4baSyz 	dlmgmt_destroyconf_retval_t	retval;
555d62bc4baSyz 
556d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
557d62bc4baSyz 		return;
558d62bc4baSyz 
559d62bc4baSyz 	destroyconf.ld_cmd = DLMGMT_CMD_DESTROYCONF;
560d62bc4baSyz 	destroyconf.ld_conf = conf;
561d62bc4baSyz 
562024b0a25Sseb 	(void) dladm_door_call(&destroyconf, sizeof (destroyconf),
563024b0a25Sseb 	    &retval, sizeof (retval));
564d62bc4baSyz }
565