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 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent Inc. All rights reserved.
25 */
26
27 /*
28 * Main door handler functions used by dlmgmtd to process the different door
29 * call requests. Door call requests can come from the user-land applications,
30 * or from the kernel.
31 *
32 * Note on zones handling:
33 *
34 * There are two zoneid's associated with a link. One is the zoneid of the
35 * zone in which the link was created (ll_zoneid in the dlmgmt_link_t), and
36 * the other is the zoneid of the zone where the link is currently assigned
37 * (the "zone" link property). The two can be different if a datalink is
38 * created in the global zone and subsequently assigned to a non-global zone
39 * via zonecfg or via explicitly setting the "zone" link property.
40 *
41 * Door clients can see links that were created in their zone, and links that
42 * are currently assigned to their zone. Door clients in a zone can only
43 * modify links that were created in their zone.
44 *
48 */
49
50 #include <assert.h>
51 #include <alloca.h>
52 #include <errno.h>
53 #include <priv_utils.h>
54 #include <stdlib.h>
55 #include <strings.h>
56 #include <syslog.h>
57 #include <sys/sysevent/eventdefs.h>
58 #include <zone.h>
59 #include <libsysevent.h>
60 #include <libdlmgmt.h>
61 #include <librcm.h>
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <fcntl.h>
65 #include <unistd.h>
66 #include "dlmgmt_impl.h"
67
68 typedef void dlmgmt_door_handler_t(void *, void *, size_t *, zoneid_t,
69 ucred_t *);
70
71 typedef struct dlmgmt_door_info_s {
72 uint_t di_cmd;
73 size_t di_reqsz;
74 size_t di_acksz;
75 dlmgmt_door_handler_t *di_handler;
76 } dlmgmt_door_info_t;
77
78 /*
79 * Check if the caller has the required privileges to operate on a link of the
80 * given class.
81 */
82 static int
83 dlmgmt_checkprivs(datalink_class_t class, ucred_t *cred)
84 {
85 const priv_set_t *eset;
86
87 eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
432 } else {
433 retvalp->lr_flags = linkp->ll_flags;
434 retvalp->lr_class = linkp->ll_class;
435 retvalp->lr_media = linkp->ll_media;
436 }
437
438 dlmgmt_table_unlock();
439 retvalp->lr_err = err;
440 }
441
442 /* ARGSUSED */
443 static void
444 dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
445 ucred_t *cred)
446 {
447 dlmgmt_door_getlinkid_t *getlinkid = argp;
448 dlmgmt_getlinkid_retval_t *retvalp = retp;
449 dlmgmt_link_t *linkp;
450 int err = 0;
451
452 /* Enable the global zone to lookup links it has given away. */
453 if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1)
454 zoneid = getlinkid->ld_zoneid;
455
456 /*
457 * Hold the reader lock to access the link
458 */
459 dlmgmt_table_lock(B_FALSE);
460
461 if ((linkp = link_by_name(getlinkid->ld_link, zoneid)) == NULL) {
462 /*
463 * The link does not exist in this zone.
464 */
465 err = ENOENT;
466 goto done;
467 }
468
469 retvalp->lr_linkid = linkp->ll_linkid;
470 retvalp->lr_flags = linkp->ll_flags;
471 retvalp->lr_class = linkp->ll_class;
472 retvalp->lr_media = linkp->ll_media;
473
474 done:
475 dlmgmt_table_unlock();
1258 if (oldzoneid == newzoneid)
1259 goto done;
1260
1261 /*
1262 * Before we remove the link from its current zone, make sure that
1263 * there isn't a link with the same name in the destination zone.
1264 */
1265 if (zoneid != GLOBAL_ZONEID &&
1266 link_by_name(linkp->ll_link, newzoneid) != NULL) {
1267 err = EEXIST;
1268 goto done;
1269 }
1270
1271 if (oldzoneid != GLOBAL_ZONEID) {
1272 if (zone_remove_datalink(oldzoneid, linkid) != 0) {
1273 err = errno;
1274 dlmgmt_log(LOG_WARNING, "unable to remove link %d from "
1275 "zone %d: %s", linkid, oldzoneid, strerror(err));
1276 goto done;
1277 }
1278
1279 if (newzoneid == GLOBAL_ZONEID && linkp->ll_onloan) {
1280 /*
1281 * We can only reassign a loaned VNIC back to the
1282 * global zone when the zone is shutting down, since
1283 * otherwise the VNIC is in use by the zone and will be
1284 * busy. Leave the VNIC assigned to the zone so we can
1285 * still see it and delete it when dlmgmt_zonehalt()
1286 * runs.
1287 */
1288 goto done;
1289 }
1290
1291 linkp->ll_onloan = B_FALSE;
1292 }
1293 if (newzoneid != GLOBAL_ZONEID) {
1294 if (zone_add_datalink(newzoneid, linkid) != 0) {
1295 err = errno;
1296 dlmgmt_log(LOG_WARNING, "unable to add link %d to zone "
1297 "%d: %s", linkid, newzoneid, strerror(err));
1298 (void) zone_add_datalink(oldzoneid, linkid);
1299 goto done;
1300 }
1301 linkp->ll_onloan = B_TRUE;
1302 }
1303
1304 avl_remove(&dlmgmt_name_avl, linkp);
1305 linkp->ll_zoneid = newzoneid;
1306 avl_add(&dlmgmt_name_avl, linkp);
1307
1308 done:
1309 dlmgmt_table_unlock();
1310 retvalp->lr_err = err;
1311 }
1312
1313 /* ARGSUSED */
1314 static void
1315 dlmgmt_zoneboot(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
1316 ucred_t *cred)
1317 {
1318 int err;
1319 dlmgmt_door_zoneboot_t *zoneboot = argp;
1320 dlmgmt_zoneboot_retval_t *retvalp = retp;
|
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 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Main door handler functions used by dlmgmtd to process the different door
28 * call requests. Door call requests can come from the user-land applications,
29 * or from the kernel.
30 *
31 * Note on zones handling:
32 *
33 * There are two zoneid's associated with a link. One is the zoneid of the
34 * zone in which the link was created (ll_zoneid in the dlmgmt_link_t), and
35 * the other is the zoneid of the zone where the link is currently assigned
36 * (the "zone" link property). The two can be different if a datalink is
37 * created in the global zone and subsequently assigned to a non-global zone
38 * via zonecfg or via explicitly setting the "zone" link property.
39 *
40 * Door clients can see links that were created in their zone, and links that
41 * are currently assigned to their zone. Door clients in a zone can only
42 * modify links that were created in their zone.
43 *
47 */
48
49 #include <assert.h>
50 #include <alloca.h>
51 #include <errno.h>
52 #include <priv_utils.h>
53 #include <stdlib.h>
54 #include <strings.h>
55 #include <syslog.h>
56 #include <sys/sysevent/eventdefs.h>
57 #include <zone.h>
58 #include <libsysevent.h>
59 #include <libdlmgmt.h>
60 #include <librcm.h>
61 #include <sys/types.h>
62 #include <sys/stat.h>
63 #include <fcntl.h>
64 #include <unistd.h>
65 #include "dlmgmt_impl.h"
66
67
68 typedef void dlmgmt_door_handler_t(void *, void *, size_t *, zoneid_t,
69 ucred_t *);
70
71 typedef struct dlmgmt_door_info_s {
72 uint_t di_cmd;
73 size_t di_reqsz;
74 size_t di_acksz;
75 dlmgmt_door_handler_t *di_handler;
76 } dlmgmt_door_info_t;
77
78 /*
79 * Check if the caller has the required privileges to operate on a link of the
80 * given class.
81 */
82 static int
83 dlmgmt_checkprivs(datalink_class_t class, ucred_t *cred)
84 {
85 const priv_set_t *eset;
86
87 eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
432 } else {
433 retvalp->lr_flags = linkp->ll_flags;
434 retvalp->lr_class = linkp->ll_class;
435 retvalp->lr_media = linkp->ll_media;
436 }
437
438 dlmgmt_table_unlock();
439 retvalp->lr_err = err;
440 }
441
442 /* ARGSUSED */
443 static void
444 dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
445 ucred_t *cred)
446 {
447 dlmgmt_door_getlinkid_t *getlinkid = argp;
448 dlmgmt_getlinkid_retval_t *retvalp = retp;
449 dlmgmt_link_t *linkp;
450 int err = 0;
451
452 /*
453 * Hold the reader lock to access the link
454 */
455 dlmgmt_table_lock(B_FALSE);
456
457 if ((linkp = link_by_name(getlinkid->ld_link, zoneid)) == NULL) {
458 /*
459 * The link does not exist in this zone.
460 */
461 err = ENOENT;
462 goto done;
463 }
464
465 retvalp->lr_linkid = linkp->ll_linkid;
466 retvalp->lr_flags = linkp->ll_flags;
467 retvalp->lr_class = linkp->ll_class;
468 retvalp->lr_media = linkp->ll_media;
469
470 done:
471 dlmgmt_table_unlock();
1254 if (oldzoneid == newzoneid)
1255 goto done;
1256
1257 /*
1258 * Before we remove the link from its current zone, make sure that
1259 * there isn't a link with the same name in the destination zone.
1260 */
1261 if (zoneid != GLOBAL_ZONEID &&
1262 link_by_name(linkp->ll_link, newzoneid) != NULL) {
1263 err = EEXIST;
1264 goto done;
1265 }
1266
1267 if (oldzoneid != GLOBAL_ZONEID) {
1268 if (zone_remove_datalink(oldzoneid, linkid) != 0) {
1269 err = errno;
1270 dlmgmt_log(LOG_WARNING, "unable to remove link %d from "
1271 "zone %d: %s", linkid, oldzoneid, strerror(err));
1272 goto done;
1273 }
1274 avl_remove(&dlmgmt_loan_avl, linkp);
1275 linkp->ll_onloan = B_FALSE;
1276 }
1277 if (newzoneid != GLOBAL_ZONEID) {
1278 if (zone_add_datalink(newzoneid, linkid) != 0) {
1279 err = errno;
1280 dlmgmt_log(LOG_WARNING, "unable to add link %d to zone "
1281 "%d: %s", linkid, newzoneid, strerror(err));
1282 (void) zone_add_datalink(oldzoneid, linkid);
1283 goto done;
1284 }
1285 avl_add(&dlmgmt_loan_avl, linkp);
1286 linkp->ll_onloan = B_TRUE;
1287 }
1288
1289 avl_remove(&dlmgmt_name_avl, linkp);
1290 linkp->ll_zoneid = newzoneid;
1291 avl_add(&dlmgmt_name_avl, linkp);
1292
1293 done:
1294 dlmgmt_table_unlock();
1295 retvalp->lr_err = err;
1296 }
1297
1298 /* ARGSUSED */
1299 static void
1300 dlmgmt_zoneboot(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
1301 ucred_t *cred)
1302 {
1303 int err;
1304 dlmgmt_door_zoneboot_t *zoneboot = argp;
1305 dlmgmt_zoneboot_retval_t *retvalp = retp;
|