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 /*
2232715170SCathy Zhou  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23d62bc4baSyz  */
25d62bc4baSyz #include <door.h>
26d62bc4baSyz #include <errno.h>
27d62bc4baSyz #include <assert.h>
28d62bc4baSyz #include <stdio.h>
29d62bc4baSyz #include <stdlib.h>
30d62bc4baSyz #include <unistd.h>
31d62bc4baSyz #include <string.h>
32d62bc4baSyz #include <strings.h>
332b24ab6bSSebastien Roy #include <zone.h>
34d62bc4baSyz #include <sys/types.h>
35d62bc4baSyz #include <sys/stat.h>
36d62bc4baSyz #include <sys/aggr.h>
3782a2fc47SJames 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>
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 };
53d62bc4baSyz static dladm_status_t
dladm_door_call(dladm_handle_t handle,void * arg,size_t asize,void * rbuf,size_t * rsizep)544ac67f02SAnurag S. Maskey dladm_door_call(dladm_handle_t handle, void *arg, size_t asize, void *rbuf,
5532715170SCathy Zhou     size_t *rsizep)
56d62bc4baSyz {
57d62bc4baSyz 	door_arg_t	darg;
584ac67f02SAnurag S. Maskey 	int		door_fd;
59f689bed1SRishi Srivatsavai 	dladm_status_t	status;
60f689bed1SRishi Srivatsavai 	boolean_t	reopen = B_FALSE;
62d62bc4baSyz 	darg.data_ptr	= arg;
63d62bc4baSyz 	darg.data_size	= asize;
64d62bc4baSyz 	darg.desc_ptr	= NULL;
65d62bc4baSyz 	darg.desc_num	= 0;
66d62bc4baSyz 	darg.rbuf	= rbuf;
6732715170SCathy Zhou 	darg.rsize	= *rsizep;
69f689bed1SRishi Srivatsavai reopen:
704ac67f02SAnurag S. Maskey 	/* The door descriptor is opened if it isn't already */
714ac67f02SAnurag S. Maskey 	if ((status = dladm_door_fd(handle, &door_fd)) != DLADM_STATUS_OK)
724ac67f02SAnurag S. Maskey 		return (status);
73f689bed1SRishi Srivatsavai 	if (door_call(door_fd, &darg) == -1) {
74f689bed1SRishi Srivatsavai 		/*
75f689bed1SRishi Srivatsavai 		 * Stale door descriptor is possible if dlmgmtd was re-started
76f689bed1SRishi Srivatsavai 		 * since last door_fd open so try re-opening door file.
77f689bed1SRishi Srivatsavai 		 */
78f689bed1SRishi Srivatsavai 		if (!reopen && errno == EBADF) {
79f689bed1SRishi Srivatsavai 			(void) close(handle->door_fd);
80f689bed1SRishi Srivatsavai 			handle->door_fd = -1;
81f689bed1SRishi Srivatsavai 			reopen = B_TRUE;
82f689bed1SRishi Srivatsavai 			goto reopen;
83f689bed1SRishi Srivatsavai 		}
84d62bc4baSyz 		status = dladm_errno2status(errno);
85f689bed1SRishi Srivatsavai 	}
86d62bc4baSyz 	if (status != DLADM_STATUS_OK)
87d62bc4baSyz 		return (status);
89d62bc4baSyz 	if (darg.rbuf != rbuf) {
90d62bc4baSyz 		/*
91d62bc4baSyz 		 * The size of the input rbuf is not big enough so that
9232715170SCathy Zhou 		 * the door allocate the rbuf itself. In this case, return
9332715170SCathy Zhou 		 * the required size to the caller.
94d62bc4baSyz 		 */
95d62bc4baSyz 		(void) munmap(darg.rbuf, darg.rsize);
9632715170SCathy Zhou 		*rsizep = darg.rsize;
97d62bc4baSyz 		return (DLADM_STATUS_TOOSMALL);
9832715170SCathy Zhou 	} else if (darg.rsize != *rsizep) {
99d62bc4baSyz 		return (DLADM_STATUS_FAILED);
10032715170SCathy Zhou 	}
102024b0a25Sseb 	return (dladm_errno2status(((dlmgmt_retval_t *)rbuf)->lr_err));
103d62bc4baSyz }
105d62bc4baSyz /*
106d62bc4baSyz  * Allocate a new linkid with the given name. Return the new linkid.
107d62bc4baSyz  */
108d62bc4baSyz dladm_status_t
dladm_create_datalink_id(dladm_handle_t handle,const char * link,datalink_class_t class,uint32_t media,uint32_t flags,datalink_id_t * linkidp)1094ac67f02SAnurag S. Maskey dladm_create_datalink_id(dladm_handle_t handle, const char *link,
1104ac67f02SAnurag S. Maskey     datalink_class_t class, uint32_t media, uint32_t flags,
1114ac67f02SAnurag S. Maskey     datalink_id_t *linkidp)
112d62bc4baSyz {
113024b0a25Sseb 	dlmgmt_door_createid_t	createid;
114d62bc4baSyz 	dlmgmt_createid_retval_t retval;
115024b0a25Sseb 	uint32_t		dlmgmt_flags;
116024b0a25Sseb 	dladm_status_t		status;
11732715170SCathy Zhou 	size_t			sz = sizeof (retval);
119024b0a25Sseb 	if (link == NULL || class == DATALINK_CLASS_ALL ||
120d62bc4baSyz 	    !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
121d62bc4baSyz 	    linkidp == NULL) {
122d62bc4baSyz 		return (DLADM_STATUS_BADARG);
123d62bc4baSyz 	}
125d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
126d62bc4baSyz 	dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
128d62bc4baSyz 	(void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
129d62bc4baSyz 	createid.ld_class = class;
130d62bc4baSyz 	createid.ld_media = media;
131d62bc4baSyz 	createid.ld_flags = dlmgmt_flags;
132d62bc4baSyz 	createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
133d62bc4baSyz 	createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
1354ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &createid, sizeof (createid),
13632715170SCathy Zhou 	    &retval, &sz)) == DLADM_STATUS_OK) {
137024b0a25Sseb 		*linkidp = retval.lr_linkid;
138024b0a25Sseb 	}
139024b0a25Sseb 	return (status);
140d62bc4baSyz }
142d62bc4baSyz /*
143d62bc4baSyz  * Destroy the given link ID.
144d62bc4baSyz  */
145d62bc4baSyz dladm_status_t
dladm_destroy_datalink_id(dladm_handle_t handle,datalink_id_t linkid,uint32_t flags)1464ac67f02SAnurag S. Maskey dladm_destroy_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
1474ac67f02SAnurag S. Maskey     uint32_t flags)
148d62bc4baSyz {
149d62bc4baSyz 	dlmgmt_door_destroyid_t		destroyid;
150d62bc4baSyz 	dlmgmt_destroyid_retval_t	retval;
151d62bc4baSyz 	uint32_t			dlmgmt_flags;
15232715170SCathy Zhou 	size_t				sz = sizeof (retval);
154d62bc4baSyz 	dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
155d62bc4baSyz 	dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
157d62bc4baSyz 	destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
158d62bc4baSyz 	destroyid.ld_linkid = linkid;
159d62bc4baSyz 	destroyid.ld_flags = dlmgmt_flags;
16132715170SCathy Zhou 	return (dladm_door_call(handle, &destroyid, sizeof (destroyid),
16232715170SCathy Zhou 	    &retval, &sz));
163d62bc4baSyz }
165d62bc4baSyz /*
166d62bc4baSyz  * Remap a given link ID to a new name.
167d62bc4baSyz  */
168d62bc4baSyz dladm_status_t
dladm_remap_datalink_id(dladm_handle_t handle,datalink_id_t linkid,const char * link)1694ac67f02SAnurag S. Maskey dladm_remap_datalink_id(dladm_handle_t handle, datalink_id_t linkid,
1704ac67f02SAnurag S. Maskey     const char *link)
171d62bc4baSyz {
172d62bc4baSyz 	dlmgmt_door_remapid_t	remapid;
173d62bc4baSyz 	dlmgmt_remapid_retval_t	retval;
17432715170SCathy Zhou 	size_t			sz = sizeof (retval);
176d62bc4baSyz 	remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
177d62bc4baSyz 	remapid.ld_linkid = linkid;
178d62bc4baSyz 	(void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
18032715170SCathy Zhou 	return (dladm_door_call(handle, &remapid, sizeof (remapid),
18132715170SCathy Zhou 	    &retval, &sz));
182d62bc4baSyz }
184d62bc4baSyz /*
185d62bc4baSyz  * Make a given link ID active.
186d62bc4baSyz  */
187d62bc4baSyz dladm_status_t
dladm_up_datalink_id(dladm_handle_t handle,datalink_id_t linkid)1884ac67f02SAnurag S. Maskey dladm_up_datalink_id(dladm_handle_t handle, datalink_id_t linkid)
189d62bc4baSyz {
190024b0a25Sseb 	dlmgmt_door_upid_t	upid;
191024b0a25Sseb 	dlmgmt_upid_retval_t	retval;
19232715170SCathy Zhou 	size_t			sz = sizeof (retval);
194d62bc4baSyz 	upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
195d62bc4baSyz 	upid.ld_linkid = linkid;
19732715170SCathy Zhou 	return (dladm_door_call(handle, &upid, sizeof (upid), &retval, &sz));
198d62bc4baSyz }
200d62bc4baSyz /*
201d62bc4baSyz  * Create a new link with the given name.  Return the new link's handle
202d62bc4baSyz  */
203d62bc4baSyz dladm_status_t
dladm_create_conf(dladm_handle_t handle,const char * link,datalink_id_t linkid,datalink_class_t class,uint32_t media,dladm_conf_t * confp)2044ac67f02SAnurag S. Maskey dladm_create_conf(dladm_handle_t handle, const char *link, datalink_id_t linkid,
205d62bc4baSyz     datalink_class_t class, uint32_t media, dladm_conf_t *confp)
206d62bc4baSyz {
207024b0a25Sseb 	dlmgmt_door_createconf_t	createconf;
208024b0a25Sseb 	dlmgmt_createconf_retval_t	retval;
209024b0a25Sseb 	dladm_status_t			status;
21032715170SCathy Zhou 	size_t				sz = sizeof (retval);
212024b0a25Sseb 	if (link == NULL || confp == NULL)
213d62bc4baSyz 		return (DLADM_STATUS_BADARG);
215d62bc4baSyz 	(void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
216d62bc4baSyz 	createconf.ld_class = class;
217d62bc4baSyz 	createconf.ld_media = media;
218d62bc4baSyz 	createconf.ld_linkid = linkid;
219d62bc4baSyz 	createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
22032715170SCathy Zhou 	confp->ds_confid = DLADM_INVALID_CONF;
2224ac67f02SAnurag S. Maskey 	if ((status = dladm_door_call(handle, &createconf, sizeof (createconf),
22332715170SCathy Zhou 	    &retval, &sz)) == DLADM_STATUS_OK) {
22432715170SCathy Zhou 		confp->ds_readonly = B_FALSE;
22532715170SCathy Zhou 		confp->ds_confid = retval.lr_confid;
226024b0a25Sseb 	}
227024b0a25Sseb 	return (status);
228d62bc4baSyz }
230d62bc4baSyz /*
231d62bc4baSyz  * An active physical link reported by the dlmgmtd daemon might not be active
232d62bc4baSyz  * anymore as this link might be removed during system shutdown. Check its
233d62bc4baSyz  * real status by calling dladm_phys_info().
234d62bc4baSyz  */
235d62bc4baSyz dladm_status_t
i_dladm_phys_status(dladm_handle_t handle,datalink_id_t linkid,uint32_t * flagsp)2364ac67f02SAnurag S. Maskey i_dladm_phys_status(dladm_handle_t handle, datalink_id_t linkid,
2374ac67f02SAnurag S. Maskey     uint32_t *flagsp)
238d62bc4baSyz {
239d62bc4baSyz 	dladm_phys_attr_t	dpa;
240d62bc4baSyz 	dladm_status_t		status;
242d62bc4baSyz 	assert((*flagsp) & DLMGMT_ACTIVE);
2444ac67f02SAnurag S. Maskey 	status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE);
245d62bc4baSyz 	if (status == DLADM_STATUS_NOTFOUND) {
246d62bc4baSyz 		/*
247d62bc4baSyz 		 * No active status, this link was removed. Update its status
248d62bc4baSyz 		 * in the daemon and delete all active linkprops.
2492d4eecfaSCathy Zhou 		 *
2502d4eecfaSCathy Zhou 		 * Note that the operation could fail. If it does, return
2512d4eecfaSCathy Zhou 		 * failure now since otherwise dladm_set_linkprop() might
2522d4eecfaSCathy Zhou 		 * call back to i_dladm_phys_status() recursively.
253d62bc4baSyz 		 */
2544ac67f02SAnurag S. Maskey 		if ((status = dladm_destroy_datalink_id(handle, linkid,
2554ac67f02SAnurag S. Maskey 		    DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK)
2562d4eecfaSCathy Zhou 			return (status);
2572d4eecfaSCathy Zhou 
2584ac67f02SAnurag S. Maskey 		(void) dladm_set_linkprop(handle, linkid, NULL, NULL, 0,
259d62bc4baSyz 		    DLADM_OPT_ACTIVE);
261d62bc4baSyz 		(*flagsp) &= ~DLMGMT_ACTIVE;
262d62bc4baSyz 		status = DLADM_STATUS_OK;