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 /*
22*82a2fc47SJames Carlson  * Copyright 2009 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>
37*82a2fc47SJames Carlson #include <sys/mman.h>
38d62bc4baSyz #include <fcntl.h>
39d62bc4baSyz #include <libdladm.h>
40d62bc4baSyz #include <libdladm_impl.h>
41d62bc4baSyz #include <libdllink.h>
42d62bc4baSyz #include <libdlmgmt.h>
43d62bc4baSyz 
44d62bc4baSyz /*
45d62bc4baSyz  * Table of data type sizes indexed by dladm_datatype_t.
46d62bc4baSyz  */
47d62bc4baSyz static size_t dladm_datatype_size[] = {
48d62bc4baSyz 	0,				/* DLADM_TYPE_STR, use strnlen() */
49d62bc4baSyz 	sizeof (boolean_t),		/* DLADM_TYPE_BOOLEAN */
50d62bc4baSyz 	sizeof (uint64_t)		/* DLADM_TYPE_UINT64 */
51d62bc4baSyz };
52d62bc4baSyz 
53d62bc4baSyz static dladm_status_t
544ac67f02SAnurag S. Maskey dladm_door_call(dladm_handle_t handle, void *arg, size_t asize, void *rbuf,
554ac67f02SAnurag S. Maskey     size_t rsize)
56d62bc4baSyz {
57d62bc4baSyz 	door_arg_t	darg;
584ac67f02SAnurag S. Maskey 	int		door_fd;
59d62bc4baSyz 	dladm_status_t	status = DLADM_STATUS_OK;
60d62bc4baSyz 
61d62bc4baSyz 	darg.data_ptr	= arg;
62d62bc4baSyz 	darg.data_size	= asize;
63d62bc4baSyz 	darg.desc_ptr	= NULL;
64d62bc4baSyz 	darg.desc_num	= 0;
65d62bc4baSyz 	darg.rbuf	= rbuf;
66024b0a25Sseb 	darg.rsize	= rsize;
67d62bc4baSyz 
684ac67f02SAnurag S. Maskey 	/* The door descriptor is opened if it isn't already */
694ac67f02SAnurag S. Maskey 	if ((status = dladm_door_fd(handle, &door_fd)) != DLADM_STATUS_OK)
704ac67f02SAnurag S. Maskey 		return (status);
714ac67f02SAnurag S. Maskey 	if (door_call(door_fd, &darg) == -1)
72d62bc4baSyz 		status = dladm_errno2status(errno);
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
954ac67f02SAnurag S. Maskey dladm_create_datalink_id(dladm_handle_t handle, const char *link,
964ac67f02SAnurag S. Maskey     datalink_class_t class, uint32_t media, uint32_t flags,
974ac67f02SAnurag S. Maskey     datalink_id_t *linkidp)
98d62bc4baSyz {
99024b0a25Sseb 	dlmgmt_door_createid_t	createid;
100d62bc4baSyz 	dlmgmt_createid_retval_t retval;
101024b0a25Sseb 	uint32_t		dlmgmt_flags;
102024b0a25Sseb 	dladm_status_t		status;
103d62bc4baSyz 
104024b0a25Sseb 	if (link == NULL || class == DATALINK_CLASS_ALL ||
105d62bc4baSyz 	    !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
106d62bc4baSyz 	    linkidp == NULL) {
107d62bc4baSyz 		return (DLADM_STATUS_BADARG);
108d62bc4baSyz 	}
109d62bc4baSyz 
110d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
111d62bc4baSyz 	dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
112d62bc4baSyz 
113d62bc4baSyz 	(void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
114d62bc4baSyz 	createid.ld_class = class;
115d62bc4baSyz 	createid.ld_media = media;
116d62bc4baSyz 	createid.ld_flags = dlmgmt_flags;
117d62bc4baSyz 	createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
118d62bc4baSyz 	createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
119d62bc4baSyz 
1204ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &createid, sizeof (createid),
1214ac67f02SAnurag S. Maskey 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
122024b0a25Sseb 		*linkidp = retval.lr_linkid;
123024b0a25Sseb 	}
124024b0a25Sseb 	return (status);
125d62bc4baSyz }
126d62bc4baSyz 
127d62bc4baSyz /*
128d62bc4baSyz  * Destroy the given link ID.
129d62bc4baSyz  */
130d62bc4baSyz dladm_status_t
1314ac67f02SAnurag S. Maskey dladm_destroy_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
1324ac67f02SAnurag S. Maskey     uint32_t flags)
133d62bc4baSyz {
134d62bc4baSyz 	dlmgmt_door_destroyid_t		destroyid;
135d62bc4baSyz 	dlmgmt_destroyid_retval_t	retval;
136d62bc4baSyz 	uint32_t			dlmgmt_flags;
137d62bc4baSyz 
138d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
139d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
140d62bc4baSyz 
141d62bc4baSyz 	destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
142d62bc4baSyz 	destroyid.ld_linkid = linkid;
143d62bc4baSyz 	destroyid.ld_flags = dlmgmt_flags;
144d62bc4baSyz 
1454ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &destroyid, sizeof (destroyid), &retval,
1464ac67f02SAnurag S. Maskey 	    sizeof (retval)));
147d62bc4baSyz }
148d62bc4baSyz 
149d62bc4baSyz /*
150d62bc4baSyz  * Remap a given link ID to a new name.
151d62bc4baSyz  */
152d62bc4baSyz dladm_status_t
1534ac67f02SAnurag S. Maskey dladm_remap_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
1544ac67f02SAnurag S. Maskey     const char *link)
155d62bc4baSyz {
156d62bc4baSyz 	dlmgmt_door_remapid_t	remapid;
157d62bc4baSyz 	dlmgmt_remapid_retval_t	retval;
158d62bc4baSyz 
159d62bc4baSyz 	remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
160d62bc4baSyz 	remapid.ld_linkid = linkid;
161d62bc4baSyz 	(void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
162d62bc4baSyz 
1634ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &remapid, sizeof (remapid), &retval,
1644ac67f02SAnurag S. Maskey 	    sizeof (retval)));
165d62bc4baSyz }
166d62bc4baSyz 
167d62bc4baSyz /*
168d62bc4baSyz  * Make a given link ID active.
169d62bc4baSyz  */
170d62bc4baSyz dladm_status_t
1714ac67f02SAnurag S. Maskey dladm_up_datalink_id(dladm_handle_t handle, datalink_id_t linkid)
172d62bc4baSyz {
173024b0a25Sseb 	dlmgmt_door_upid_t	upid;
174024b0a25Sseb 	dlmgmt_upid_retval_t	retval;
175d62bc4baSyz 
176d62bc4baSyz 	upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
177d62bc4baSyz 	upid.ld_linkid = linkid;
178d62bc4baSyz 
1794ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &upid, sizeof (upid), &retval,
1804ac67f02SAnurag S. Maskey 	    sizeof (retval)));
181d62bc4baSyz }
182d62bc4baSyz 
183d62bc4baSyz /*
184d62bc4baSyz  * Create a new link with the given name.  Return the new link's handle
185d62bc4baSyz  */
186d62bc4baSyz dladm_status_t
1874ac67f02SAnurag S. Maskey dladm_create_conf(dladm_handle_t handle, const char *link, datalink_id_t linkid,
188d62bc4baSyz     datalink_class_t class, uint32_t media, dladm_conf_t *confp)
189d62bc4baSyz {
190024b0a25Sseb 	dlmgmt_door_createconf_t	createconf;
191024b0a25Sseb 	dlmgmt_createconf_retval_t	retval;
192024b0a25Sseb 	dladm_status_t			status;
193d62bc4baSyz 
194024b0a25Sseb 	if (link == NULL || confp == NULL)
195d62bc4baSyz 		return (DLADM_STATUS_BADARG);
196d62bc4baSyz 
197d62bc4baSyz 	(void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
198d62bc4baSyz 	createconf.ld_class = class;
199d62bc4baSyz 	createconf.ld_media = media;
200d62bc4baSyz 	createconf.ld_linkid = linkid;
201d62bc4baSyz 	createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
202d62bc4baSyz 
2034ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &createconf, sizeof (createconf),
204024b0a25Sseb 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
205024b0a25Sseb 		*confp = retval.lr_conf;
206024b0a25Sseb 	}
207024b0a25Sseb 	return (status);
208d62bc4baSyz }
209d62bc4baSyz 
210d62bc4baSyz /*
211d62bc4baSyz  * An active physical link reported by the dlmgmtd daemon might not be active
212d62bc4baSyz  * anymore as this link might be removed during system shutdown. Check its
213d62bc4baSyz  * real status by calling dladm_phys_info().
214d62bc4baSyz  */
215d62bc4baSyz dladm_status_t
2164ac67f02SAnurag S. Maskey i_dladm_phys_status(dladm_handle_t handle, datalink_id_t linkid,
2174ac67f02SAnurag S. Maskey     uint32_t *flagsp)
218d62bc4baSyz {
219d62bc4baSyz 	dladm_phys_attr_t	dpa;
220d62bc4baSyz 	dladm_status_t		status;
221d62bc4baSyz 
222d62bc4baSyz 	assert((*flagsp) & DLMGMT_ACTIVE);
223d62bc4baSyz 
2244ac67f02SAnurag S. Maskey 	status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE);
225d62bc4baSyz 	if (status == DLADM_STATUS_NOTFOUND) {
226d62bc4baSyz 		/*
227d62bc4baSyz 		 * No active status, this link was removed. Update its status
228d62bc4baSyz 		 * in the daemon and delete all active linkprops.
2292d4eecfaSCathy Zhou 		 *
2302d4eecfaSCathy Zhou 		 * Note that the operation could fail. If it does, return
2312d4eecfaSCathy Zhou 		 * failure now since otherwise dladm_set_linkprop() might
2322d4eecfaSCathy Zhou 		 * call back to i_dladm_phys_status() recursively.
233d62bc4baSyz 		 */
2344ac67f02SAnurag S. Maskey 		if ((status = dladm_destroy_datalink_id(handle, linkid,
2354ac67f02SAnurag S. Maskey 		    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
2362d4eecfaSCathy Zhou 			return (status);
2372d4eecfaSCathy Zhou 
2384ac67f02SAnurag S. Maskey 		(void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
239d62bc4baSyz 		    DLADM_OPT_ACTIVE);
240d62bc4baSyz 
241d62bc4baSyz 		(*flagsp) &= ~DLMGMT_ACTIVE;
242d62bc4baSyz 		status = DLADM_STATUS_OK;
243d62bc4baSyz 	}
244d62bc4baSyz 	return (status);
245d62bc4baSyz }
246d62bc4baSyz 
247d62bc4baSyz /*
248d62bc4baSyz  * Walk each entry in the data link configuration repository and
249d62bc4baSyz  * call fn on the linkid and arg.
250d62bc4baSyz  */
251d62bc4baSyz dladm_status_t
2524ac67f02SAnurag S. Maskey dladm_walk_datalink_id(int (*fn)(dladm_handle_t, datalink_id_t, void *),
2534ac67f02SAnurag S. Maskey     dladm_handle_t handle, void *argp, datalink_class_t class,
2544ac67f02SAnurag S. Maskey     datalink_media_t dmedia, uint32_t flags)
255d62bc4baSyz {
256d62bc4baSyz 	dlmgmt_door_getnext_t	getnext;
257d62bc4baSyz 	dlmgmt_getnext_retval_t	retval;
258d62bc4baSyz 	uint32_t 		dlmgmt_flags;
259d62bc4baSyz 	datalink_id_t		linkid = DATALINK_INVALID_LINKID;
260d62bc4baSyz 	dladm_status_t		status = DLADM_STATUS_OK;
261d62bc4baSyz 
262d62bc4baSyz 	if (fn == NULL)
263d62bc4baSyz 		return (DLADM_STATUS_BADARG);
264d62bc4baSyz 
265d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
266d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
267d62bc4baSyz 
268d62bc4baSyz 	getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
269d62bc4baSyz 	getnext.ld_class = class;
270d62bc4baSyz 	getnext.ld_dmedia = dmedia;
271d62bc4baSyz 	getnext.ld_flags = dlmgmt_flags;
272d62bc4baSyz 
273d62bc4baSyz 	do {
274d62bc4baSyz 		getnext.ld_linkid = linkid;
2754ac67f02SAnurag S. Maskey 		if ((status = dladm_door_call(handle, &getnext,
2764ac67f02SAnurag S. Maskey 		    sizeof (getnext), &retval, sizeof (retval))) !=
2774ac67f02SAnurag S. Maskey 		    DLADM_STATUS_OK) {
278d62bc4baSyz 			/*
279d62bc4baSyz 			 * done with walking
280d62bc4baSyz 			 */
281d62bc4baSyz 			break;
282d62bc4baSyz 		}
283d62bc4baSyz 
284d62bc4baSyz 		linkid = retval.lr_linkid;
285d62bc4baSyz 		if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
286d62bc4baSyz 		    (retval.lr_flags & DLMGMT_ACTIVE)) {
287d62bc4baSyz 			/*
288d62bc4baSyz 			 * An active physical link reported by the dlmgmtd
289d62bc4baSyz 			 * daemon might not be active anymore. Check its
290d62bc4baSyz 			 * real status.
291d62bc4baSyz 			 */
2924ac67f02SAnurag S. Maskey 			if (i_dladm_phys_status(handle, linkid,
2934ac67f02SAnurag S. Maskey 			    &retval.lr_flags) != DLADM_STATUS_OK) {
294d62bc4baSyz 				continue;
295d62bc4baSyz 			}
296d62bc4baSyz 
297d62bc4baSyz 			if (!(dlmgmt_flags & retval.lr_flags))
298d62bc4baSyz 				continue;
299d62bc4baSyz 		}
300d62bc4baSyz 
3014ac67f02SAnurag S. Maskey 		if (fn(handle, linkid, argp) == DLADM_WALK_TERMINATE)
302d62bc4baSyz 			break;
303d62bc4baSyz 	} while (linkid != DATALINK_INVALID_LINKID);
304d62bc4baSyz 
305d62bc4baSyz 	return (status);
306d62bc4baSyz }
307d62bc4baSyz 
308d62bc4baSyz /*
309d62bc4baSyz  * Get the link properties structure for the given link.
310d62bc4baSyz  */
311d62bc4baSyz dladm_status_t
3124ac67f02SAnurag S. Maskey dladm_read_conf(dladm_handle_t handle, datalink_id_t linkid,
3134ac67f02SAnurag S. Maskey     dladm_conf_t *confp)
314d62bc4baSyz {
315024b0a25Sseb 	dlmgmt_door_readconf_t		readconf;
316d62bc4baSyz 	dlmgmt_readconf_retval_t	retval;
317d62bc4baSyz 	dladm_status_t			status;
318d62bc4baSyz 
319d62bc4baSyz 	if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
320d62bc4baSyz 		return (DLADM_STATUS_BADARG);
321d62bc4baSyz 
322d62bc4baSyz 	readconf.ld_linkid = linkid;
323d62bc4baSyz 	readconf.ld_cmd = DLMGMT_CMD_READCONF;
324d62bc4baSyz 
3254ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &readconf, sizeof (readconf),
326024b0a25Sseb 	    &retval, sizeof (retval))) == DLADM_STATUS_OK) {
327024b0a25Sseb 		*confp = retval.lr_conf;
328024b0a25Sseb 	}
329024b0a25Sseb 	return (status);
330d62bc4baSyz }
331d62bc4baSyz 
332d62bc4baSyz /*
333d62bc4baSyz  * Commit the given link to the data link configuration repository so
334d62bc4baSyz  * that it will persist across reboots.
335d62bc4baSyz  */
336d62bc4baSyz dladm_status_t
3374ac67f02SAnurag S. Maskey dladm_write_conf(dladm_handle_t handle, dladm_conf_t conf)
338d62bc4baSyz {
339d62bc4baSyz 	dlmgmt_door_writeconf_t		writeconf;
340d62bc4baSyz 	dlmgmt_writeconf_retval_t	retval;
341d62bc4baSyz 
342d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
343d62bc4baSyz 		return (DLADM_STATUS_BADARG);
344d62bc4baSyz 
345d62bc4baSyz 	writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
346d62bc4baSyz 	writeconf.ld_conf = conf;
347d62bc4baSyz 
3484ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &writeconf, sizeof (writeconf), &retval,
3494ac67f02SAnurag S. Maskey 	    sizeof (retval)));
350d62bc4baSyz }
351d62bc4baSyz 
352d62bc4baSyz /*
353d62bc4baSyz  * Given a link ID and a key, get the matching information from
354d62bc4baSyz  * data link configuration repository.
355d62bc4baSyz  */
356d62bc4baSyz dladm_status_t
3574ac67f02SAnurag S. Maskey dladm_get_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr,
3584ac67f02SAnurag S. Maskey     void *attrval, size_t attrsz)
359d62bc4baSyz {
360024b0a25Sseb 	dlmgmt_door_getattr_t	getattr;
361024b0a25Sseb 	dlmgmt_getattr_retval_t	retval;
362024b0a25Sseb 	dladm_status_t		status;
363d62bc4baSyz 
364d62bc4baSyz 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
365024b0a25Sseb 	    attrsz == 0 || attr == NULL) {
366d62bc4baSyz 		return (DLADM_STATUS_BADARG);
367d62bc4baSyz 	}
368d62bc4baSyz 
369d62bc4baSyz 	getattr.ld_cmd = DLMGMT_CMD_GETATTR;
370d62bc4baSyz 	getattr.ld_conf = conf;
371d62bc4baSyz 	(void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
372d62bc4baSyz 
3734ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &getattr, sizeof (getattr),
3744ac67f02SAnurag S. Maskey 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
375024b0a25Sseb 		return (status);
376024b0a25Sseb 	}
377d62bc4baSyz 
378024b0a25Sseb 	if (retval.lr_attrsz > attrsz)
379024b0a25Sseb 		return (DLADM_STATUS_TOOSMALL);
380d62bc4baSyz 
38162ee1d25SArtem Kachitchkine 	bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
38262ee1d25SArtem Kachitchkine 	return (DLADM_STATUS_OK);
38362ee1d25SArtem Kachitchkine }
38462ee1d25SArtem Kachitchkine 
38562ee1d25SArtem Kachitchkine /*
38662ee1d25SArtem Kachitchkine  * Get next property attribute from data link configuration repository.
38762ee1d25SArtem Kachitchkine  */
38862ee1d25SArtem Kachitchkine dladm_status_t
38962ee1d25SArtem Kachitchkine dladm_getnext_conf_linkprop(dladm_handle_t handle, dladm_conf_t conf,
39062ee1d25SArtem Kachitchkine     const char *last_attr, char *attr, void *attrval, size_t attrsz,
39162ee1d25SArtem Kachitchkine     size_t *attrszp)
39262ee1d25SArtem Kachitchkine {
39362ee1d25SArtem Kachitchkine 	dlmgmt_door_linkprop_getnext_t		getnext;
39462ee1d25SArtem Kachitchkine 	dlmgmt_linkprop_getnext_retval_t	retval;
39562ee1d25SArtem Kachitchkine 	dladm_status_t				status;
39662ee1d25SArtem Kachitchkine 
39762ee1d25SArtem Kachitchkine 	if (conf == DLADM_INVALID_CONF || attrval == NULL ||
39862ee1d25SArtem Kachitchkine 	    attrsz == 0 || attr == NULL) {
39962ee1d25SArtem Kachitchkine 		return (DLADM_STATUS_BADARG);
40062ee1d25SArtem Kachitchkine 	}
40162ee1d25SArtem Kachitchkine 
40262ee1d25SArtem Kachitchkine 	getnext.ld_cmd = DLMGMT_CMD_LINKPROP_GETNEXT;
40362ee1d25SArtem Kachitchkine 	getnext.ld_conf = conf;
40462ee1d25SArtem Kachitchkine 	(void) strlcpy(getnext.ld_last_attr, last_attr, MAXLINKATTRLEN);
40562ee1d25SArtem Kachitchkine 
40662ee1d25SArtem Kachitchkine 	if ((status = dladm_door_call(handle, &getnext, sizeof (getnext),
40762ee1d25SArtem Kachitchkine 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
40862ee1d25SArtem Kachitchkine 		return (status);
40962ee1d25SArtem Kachitchkine 	}
41062ee1d25SArtem Kachitchkine 
41162ee1d25SArtem Kachitchkine 	*attrszp = retval.lr_attrsz;
41262ee1d25SArtem Kachitchkine 	if (retval.lr_attrsz > attrsz) {
41362ee1d25SArtem Kachitchkine 		return (DLADM_STATUS_TOOSMALL);
41462ee1d25SArtem Kachitchkine 	}
41562ee1d25SArtem Kachitchkine 
41662ee1d25SArtem Kachitchkine 	(void) strlcpy(attr, retval.lr_attr, MAXLINKATTRLEN);
417024b0a25Sseb 	bcopy(retval.lr_attrval, attrval, retval.lr_attrsz);
418024b0a25Sseb 	return (DLADM_STATUS_OK);
419d62bc4baSyz }
420d62bc4baSyz 
421d62bc4baSyz /*
422d62bc4baSyz  * Get the link ID that is associated with the given name.
423d62bc4baSyz  */
424d62bc4baSyz dladm_status_t
4254ac67f02SAnurag S. Maskey dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp,
4264ac67f02SAnurag S. Maskey     uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap)
427d62bc4baSyz {
428d62bc4baSyz 	dlmgmt_door_getlinkid_t		getlinkid;
429d62bc4baSyz 	dlmgmt_getlinkid_retval_t	retval;
430d62bc4baSyz 	datalink_id_t			linkid;
431d62bc4baSyz 	dladm_status_t			status;
432d62bc4baSyz 
433d62bc4baSyz 	getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
434d62bc4baSyz 	(void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
435d62bc4baSyz 
4364ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid),
437024b0a25Sseb 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
438d62bc4baSyz 		return (status);
439024b0a25Sseb 	}
440d62bc4baSyz 
441d62bc4baSyz 	linkid = retval.lr_linkid;
442d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
443d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
444d62bc4baSyz 		/*
445d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
446d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
447d62bc4baSyz 		 */
4484ac67f02SAnurag S. Maskey 		status = i_dladm_phys_status(handle, linkid, &retval.lr_flags);
449d62bc4baSyz 		if (status != DLADM_STATUS_OK)
450d62bc4baSyz 			return (status);
451d62bc4baSyz 	}
452d62bc4baSyz 
453d62bc4baSyz 	if (linkidp != NULL)
454d62bc4baSyz 		*linkidp = linkid;
455d62bc4baSyz 	if (flagp != NULL) {
456d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
457d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
458d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
459d62bc4baSyz 	}
460d62bc4baSyz 	if (classp != NULL)
461d62bc4baSyz 		*classp = retval.lr_class;
462d62bc4baSyz 	if (mediap != NULL)
463d62bc4baSyz 		*mediap = retval.lr_media;
464d62bc4baSyz 
465d62bc4baSyz 	return (DLADM_STATUS_OK);
466d62bc4baSyz }
467d62bc4baSyz 
468d62bc4baSyz /*
469d62bc4baSyz  * Get the link name that is associated with the given id.
470d62bc4baSyz  */
471d62bc4baSyz dladm_status_t
4724ac67f02SAnurag S. Maskey dladm_datalink_id2info(dladm_handle_t handle, datalink_id_t linkid,
4734ac67f02SAnurag S. Maskey     uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap, char *link,
4744ac67f02SAnurag S. Maskey     size_t len)
475d62bc4baSyz {
476024b0a25Sseb 	dlmgmt_door_getname_t	getname;
477024b0a25Sseb 	dlmgmt_getname_retval_t	retval;
478024b0a25Sseb 	dladm_status_t		status;
479d62bc4baSyz 
480d62bc4baSyz 	if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) ||
481d62bc4baSyz 	    (link == NULL && len != 0)) {
482d62bc4baSyz 		return (DLADM_STATUS_BADARG);
483d62bc4baSyz 	}
484d62bc4baSyz 
485d62bc4baSyz 	getname.ld_cmd = DLMGMT_CMD_GETNAME;
486d62bc4baSyz 	getname.ld_linkid = linkid;
4874ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &getname, sizeof (getname),
4884ac67f02SAnurag S. Maskey 	    &retval, sizeof (retval))) != DLADM_STATUS_OK) {
489d62bc4baSyz 		return (status);
490024b0a25Sseb 	}
491d62bc4baSyz 
492024b0a25Sseb 	if (len != 0 && (strlen(retval.lr_link) + 1 > len))
493d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
494d62bc4baSyz 
495d62bc4baSyz 	if (retval.lr_class == DATALINK_CLASS_PHYS &&
496d62bc4baSyz 	    retval.lr_flags & DLMGMT_ACTIVE) {
497d62bc4baSyz 		/*
498d62bc4baSyz 		 * An active physical link reported by the dlmgmtd daemon
499d62bc4baSyz 		 * might not be active anymore. Check and set its real status.
500d62bc4baSyz 		 */
5014ac67f02SAnurag S. Maskey 		status = i_dladm_phys_status(handle, linkid, &retval.lr_flags);
502d62bc4baSyz 		if (status != DLADM_STATUS_OK)
503d62bc4baSyz 			return (status);
504d62bc4baSyz 	}
505d62bc4baSyz 
506d62bc4baSyz 	if (link != NULL)
507d62bc4baSyz 		(void) strlcpy(link, retval.lr_link, len);
508d62bc4baSyz 	if (classp != NULL)
509d62bc4baSyz 		*classp = retval.lr_class;
510d62bc4baSyz 	if (mediap != NULL)
511d62bc4baSyz 		*mediap = retval.lr_media;
512d62bc4baSyz 	if (flagp != NULL) {
513d62bc4baSyz 		*flagp = retval.lr_flags & DLMGMT_ACTIVE ?
514d62bc4baSyz 		    DLADM_OPT_ACTIVE : 0;
515d62bc4baSyz 		*flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
516d62bc4baSyz 		    DLADM_OPT_PERSIST : 0;
517d62bc4baSyz 	}
518d62bc4baSyz 	return (DLADM_STATUS_OK);
519d62bc4baSyz }
520d62bc4baSyz 
521d62bc4baSyz /*
522d62bc4baSyz  * Set the given attr with the given attrval for the given link.
523d62bc4baSyz  */
524d62bc4baSyz dladm_status_t
5254ac67f02SAnurag S. Maskey dladm_set_conf_field(dladm_handle_t handle, dladm_conf_t conf, const char *attr,
526d62bc4baSyz     dladm_datatype_t type, const void *attrval)
527d62bc4baSyz {
528024b0a25Sseb 	dlmgmt_door_setattr_t	setattr;
529024b0a25Sseb 	dlmgmt_setattr_retval_t	retval;
530024b0a25Sseb 	size_t			attrsz;
531d62bc4baSyz 
532024b0a25Sseb 	if (attr == NULL || attrval == NULL)
533d62bc4baSyz 		return (DLADM_STATUS_BADARG);
534d62bc4baSyz 
535d62bc4baSyz 	if (type == DLADM_TYPE_STR)
536d62bc4baSyz 		attrsz = strlen(attrval) + 1;
537d62bc4baSyz 	else
538d62bc4baSyz 		attrsz = dladm_datatype_size[type];
539d62bc4baSyz 
540024b0a25Sseb 	if (attrsz > MAXLINKATTRVALLEN)
541024b0a25Sseb 		return (DLADM_STATUS_TOOSMALL);
542d62bc4baSyz 
543024b0a25Sseb 	setattr.ld_cmd = DLMGMT_CMD_SETATTR;
544024b0a25Sseb 	setattr.ld_conf = conf;
545024b0a25Sseb 	(void) strlcpy(setattr.ld_attr, attr, MAXLINKATTRLEN);
546024b0a25Sseb 	setattr.ld_attrsz = attrsz;
547024b0a25Sseb 	setattr.ld_type = type;
548024b0a25Sseb 	bcopy(attrval, &setattr.ld_attrval, attrsz);
549d62bc4baSyz 
5504ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &setattr, sizeof (setattr), &retval,
5514ac67f02SAnurag S. Maskey 	    sizeof (retval)));
552d62bc4baSyz }
553d62bc4baSyz 
554d62bc4baSyz /*
555d62bc4baSyz  * Unset the given attr the given link.
556d62bc4baSyz  */
557d62bc4baSyz dladm_status_t
5584ac67f02SAnurag S. Maskey dladm_unset_conf_field(dladm_handle_t handle, dladm_conf_t conf,
5594ac67f02SAnurag S. Maskey     const char *attr)
560d62bc4baSyz {
561d62bc4baSyz 	dlmgmt_door_unsetattr_t		unsetattr;
562d62bc4baSyz 	dlmgmt_unsetattr_retval_t	retval;
563d62bc4baSyz 
564024b0a25Sseb 	if (attr == NULL)
565d62bc4baSyz 		return (DLADM_STATUS_BADARG);
566d62bc4baSyz 
567d62bc4baSyz 	unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR;
568d62bc4baSyz 	unsetattr.ld_conf = conf;
569d62bc4baSyz 	(void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN);
570d62bc4baSyz 
5714ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &unsetattr, sizeof (unsetattr), &retval,
5724ac67f02SAnurag S. Maskey 	    sizeof (retval)));
573d62bc4baSyz }
574d62bc4baSyz 
575d62bc4baSyz /*
576d62bc4baSyz  * Remove the given link ID and its entry from the data link configuration
577d62bc4baSyz  * repository.
578d62bc4baSyz  */
579d62bc4baSyz dladm_status_t
5804ac67f02SAnurag S. Maskey dladm_remove_conf(dladm_handle_t handle, datalink_id_t linkid)
581d62bc4baSyz {
582d62bc4baSyz 	dlmgmt_door_removeconf_t	removeconf;
583d62bc4baSyz 	dlmgmt_removeconf_retval_t	retval;
584d62bc4baSyz 
585d62bc4baSyz 	removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF;
586d62bc4baSyz 	removeconf.ld_linkid = linkid;
587d62bc4baSyz 
5884ac67f02SAnurag S. Maskey 	return (dladm_door_call(handle, &removeconf, sizeof (removeconf),
589024b0a25Sseb 	    &retval, sizeof (retval)));
590d62bc4baSyz }
591d62bc4baSyz 
592d62bc4baSyz /*
593d62bc4baSyz  * Free the contents of the link structure.
594d62bc4baSyz  */
595d62bc4baSyz void
5964ac67f02SAnurag S. Maskey dladm_destroy_conf(dladm_handle_t handle, dladm_conf_t conf)
597d62bc4baSyz {
598d62bc4baSyz 	dlmgmt_door_destroyconf_t	destroyconf;
599d62bc4baSyz 	dlmgmt_destroyconf_retval_t	retval;
600d62bc4baSyz 
601d62bc4baSyz 	if (conf == DLADM_INVALID_CONF)
602d62bc4baSyz 		return;
603d62bc4baSyz 
604d62bc4baSyz 	destroyconf.ld_cmd = DLMGMT_CMD_DESTROYCONF;
605d62bc4baSyz 	destroyconf.ld_conf = conf;
606d62bc4baSyz 
6074ac67f02SAnurag S. Maskey 	(void) dladm_door_call(handle, &destroyconf, sizeof (destroyconf),
608024b0a25Sseb 	    &retval, sizeof (retval));
609d62bc4baSyz }
610