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 2019 Joyent, Inc.
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 *
408 ucred_t *cred)
409 {
410 dlmgmt_door_getname_t *getname = argp;
411 dlmgmt_getname_retval_t *retvalp = retp;
412 dlmgmt_link_t *linkp;
413 int err = 0;
414
415 /*
416 * Hold the reader lock to access the link
417 */
418 dlmgmt_table_lock(B_FALSE);
419 if ((linkp = link_by_id(getname->ld_linkid, zoneid)) == NULL) {
420 err = ENOENT;
421 } else if (strlcpy(retvalp->lr_link, linkp->ll_link, MAXLINKNAMELEN) >=
422 MAXLINKNAMELEN) {
423 err = ENOSPC;
424 } else {
425 retvalp->lr_flags = linkp->ll_flags;
426 retvalp->lr_class = linkp->ll_class;
427 retvalp->lr_media = linkp->ll_media;
428 retvalp->lr_flags |= (linkp->ll_trans == B_TRUE) ?
429 DLMGMT_TRANSIENT : 0;
430 }
431
432
433 dlmgmt_table_unlock();
434 retvalp->lr_err = err;
435 }
436
437 /* ARGSUSED */
438 static void
439 dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
440 ucred_t *cred)
441 {
442 dlmgmt_door_getlinkid_t *getlinkid = argp;
443 dlmgmt_getlinkid_retval_t *retvalp = retp;
444 dlmgmt_link_t *linkp;
445 int err = 0;
446
447 /* Enable the global zone to lookup links it has given away. */
448 if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1)
449 zoneid = getlinkid->ld_zoneid;
450
451 /*
452 * Hold the reader lock to access the link
453 */
454 dlmgmt_table_lock(B_FALSE);
455
456 if ((linkp = link_by_name(getlinkid->ld_link, zoneid)) == NULL) {
457 /*
458 * The link does not exist in this zone.
459 */
460 err = ENOENT;
461 goto done;
462 }
463
464 retvalp->lr_linkid = linkp->ll_linkid;
465 retvalp->lr_flags = linkp->ll_flags;
466 retvalp->lr_class = linkp->ll_class;
467 retvalp->lr_media = linkp->ll_media;
468
469 done:
470 dlmgmt_table_unlock();
471 retvalp->lr_err = err;
472 }
473
474 /* ARGSUSED */
475 static void
476 dlmgmt_getnext(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
477 ucred_t *cred)
478 {
479 dlmgmt_door_getnext_t *getnext = argp;
480 dlmgmt_getnext_retval_t *retvalp = retp;
481 dlmgmt_link_t link, *linkp;
482 avl_index_t where;
483 int err = 0;
484
485 /*
486 * Hold the reader lock to access the link
487 */
491 if ((linkp = avl_find(&dlmgmt_id_avl, &link, &where)) == NULL)
492 linkp = avl_nearest(&dlmgmt_id_avl, where, AVL_AFTER);
493
494 for (; linkp != NULL; linkp = AVL_NEXT(&dlmgmt_id_avl, linkp)) {
495 if (!link_is_visible(linkp, zoneid))
496 continue;
497 if ((linkp->ll_class & getnext->ld_class) &&
498 (linkp->ll_flags & getnext->ld_flags) &&
499 DATALINK_MEDIA_ACCEPTED(getnext->ld_dmedia,
500 linkp->ll_media))
501 break;
502 }
503
504 if (linkp == NULL) {
505 err = ENOENT;
506 } else {
507 retvalp->lr_linkid = linkp->ll_linkid;
508 retvalp->lr_class = linkp->ll_class;
509 retvalp->lr_media = linkp->ll_media;
510 retvalp->lr_flags = linkp->ll_flags;
511 }
512
513 dlmgmt_table_unlock();
514 retvalp->lr_err = err;
515 }
516
517 /* ARGSUSED */
518 static void
519 dlmgmt_upcall_getattr(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
520 ucred_t *cred)
521 {
522 dlmgmt_upcall_arg_getattr_t *getattr = argp;
523 dlmgmt_getattr_retval_t *retvalp = retp;
524 dlmgmt_link_t *linkp;
525
526 /*
527 * Hold the reader lock to access the link
528 */
529 dlmgmt_table_lock(B_FALSE);
530 if ((linkp = link_by_id(getattr->ld_linkid, zoneid)) == NULL) {
1237
1238 if (oldzoneid == newzoneid)
1239 goto done;
1240
1241 /*
1242 * Before we remove the link from its current zone, make sure that
1243 * there isn't a link with the same name in the destination zone.
1244 */
1245 if (link_by_name(linkp->ll_link, newzoneid) != NULL) {
1246 err = EEXIST;
1247 goto done;
1248 }
1249
1250 if (oldzoneid != GLOBAL_ZONEID) {
1251 if (zone_remove_datalink(oldzoneid, linkid) != 0) {
1252 err = errno;
1253 dlmgmt_log(LOG_WARNING, "unable to remove link %d from "
1254 "zone %d: %s", linkid, oldzoneid, strerror(err));
1255 goto done;
1256 }
1257
1258 linkp->ll_onloan = B_FALSE;
1259 }
1260
1261 if (newzoneid != GLOBAL_ZONEID) {
1262 if (zone_add_datalink(newzoneid, linkid) != 0) {
1263 err = errno;
1264 dlmgmt_log(LOG_WARNING, "unable to add link %d to zone "
1265 "%d: %s", linkid, newzoneid, strerror(err));
1266 (void) zone_add_datalink(oldzoneid, linkid);
1267 goto done;
1268 }
1269 linkp->ll_onloan = B_TRUE;
1270 }
1271
1272 avl_remove(&dlmgmt_name_avl, linkp);
1273 linkp->ll_zoneid = newzoneid;
1274 avl_add(&dlmgmt_name_avl, linkp);
1275
1276 done:
1277 dlmgmt_table_unlock();
|
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 2019 Joyent, Inc.
25 * Copyright 2023 Oxide Computer Company
26 */
27
28 /*
29 * Main door handler functions used by dlmgmtd to process the different door
30 * call requests. Door call requests can come from the user-land applications,
31 * or from the kernel.
32 *
33 * Note on zones handling:
34 *
35 * There are two zoneid's associated with a link. One is the zoneid of the
36 * zone in which the link was created (ll_zoneid in the dlmgmt_link_t), and
37 * the other is the zoneid of the zone where the link is currently assigned
38 * (the "zone" link property). The two can be different if a datalink is
39 * created in the global zone and subsequently assigned to a non-global zone
40 * via zonecfg or via explicitly setting the "zone" link property.
41 *
42 * Door clients can see links that were created in their zone, and links that
43 * are currently assigned to their zone. Door clients in a zone can only
44 * modify links that were created in their zone.
45 *
409 ucred_t *cred)
410 {
411 dlmgmt_door_getname_t *getname = argp;
412 dlmgmt_getname_retval_t *retvalp = retp;
413 dlmgmt_link_t *linkp;
414 int err = 0;
415
416 /*
417 * Hold the reader lock to access the link
418 */
419 dlmgmt_table_lock(B_FALSE);
420 if ((linkp = link_by_id(getname->ld_linkid, zoneid)) == NULL) {
421 err = ENOENT;
422 } else if (strlcpy(retvalp->lr_link, linkp->ll_link, MAXLINKNAMELEN) >=
423 MAXLINKNAMELEN) {
424 err = ENOSPC;
425 } else {
426 retvalp->lr_flags = linkp->ll_flags;
427 retvalp->lr_class = linkp->ll_class;
428 retvalp->lr_media = linkp->ll_media;
429 retvalp->lr_flags |= linkp->ll_transient ? DLMGMT_TRANSIENT : 0;
430 }
431
432
433 dlmgmt_table_unlock();
434 retvalp->lr_err = err;
435 }
436
437 /* ARGSUSED */
438 static void
439 dlmgmt_getlinkid(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
440 ucred_t *cred)
441 {
442 dlmgmt_door_getlinkid_t *getlinkid = argp;
443 dlmgmt_getlinkid_retval_t *retvalp = retp;
444 dlmgmt_link_t *linkp;
445 int err = 0;
446
447 /* Enable the global zone to lookup links it has given away. */
448 if (zoneid == GLOBAL_ZONEID && getlinkid->ld_zoneid != -1)
449 zoneid = getlinkid->ld_zoneid;
450
451 /*
452 * Hold the reader lock to access the link
453 */
454 dlmgmt_table_lock(B_FALSE);
455
456 if ((linkp = link_by_name(getlinkid->ld_link, zoneid)) == NULL) {
457 /*
458 * The link does not exist in this zone.
459 */
460 err = ENOENT;
461 goto done;
462 }
463
464 retvalp->lr_linkid = linkp->ll_linkid;
465 retvalp->lr_flags = linkp->ll_flags;
466 retvalp->lr_class = linkp->ll_class;
467 retvalp->lr_media = linkp->ll_media;
468 retvalp->lr_flags |= linkp->ll_transient ? DLMGMT_TRANSIENT : 0;
469
470 done:
471 dlmgmt_table_unlock();
472 retvalp->lr_err = err;
473 }
474
475 /* ARGSUSED */
476 static void
477 dlmgmt_getnext(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
478 ucred_t *cred)
479 {
480 dlmgmt_door_getnext_t *getnext = argp;
481 dlmgmt_getnext_retval_t *retvalp = retp;
482 dlmgmt_link_t link, *linkp;
483 avl_index_t where;
484 int err = 0;
485
486 /*
487 * Hold the reader lock to access the link
488 */
492 if ((linkp = avl_find(&dlmgmt_id_avl, &link, &where)) == NULL)
493 linkp = avl_nearest(&dlmgmt_id_avl, where, AVL_AFTER);
494
495 for (; linkp != NULL; linkp = AVL_NEXT(&dlmgmt_id_avl, linkp)) {
496 if (!link_is_visible(linkp, zoneid))
497 continue;
498 if ((linkp->ll_class & getnext->ld_class) &&
499 (linkp->ll_flags & getnext->ld_flags) &&
500 DATALINK_MEDIA_ACCEPTED(getnext->ld_dmedia,
501 linkp->ll_media))
502 break;
503 }
504
505 if (linkp == NULL) {
506 err = ENOENT;
507 } else {
508 retvalp->lr_linkid = linkp->ll_linkid;
509 retvalp->lr_class = linkp->ll_class;
510 retvalp->lr_media = linkp->ll_media;
511 retvalp->lr_flags = linkp->ll_flags;
512 retvalp->lr_flags |= linkp->ll_transient ? DLMGMT_TRANSIENT : 0;
513 }
514
515 dlmgmt_table_unlock();
516 retvalp->lr_err = err;
517 }
518
519 /* ARGSUSED */
520 static void
521 dlmgmt_upcall_getattr(void *argp, void *retp, size_t *sz, zoneid_t zoneid,
522 ucred_t *cred)
523 {
524 dlmgmt_upcall_arg_getattr_t *getattr = argp;
525 dlmgmt_getattr_retval_t *retvalp = retp;
526 dlmgmt_link_t *linkp;
527
528 /*
529 * Hold the reader lock to access the link
530 */
531 dlmgmt_table_lock(B_FALSE);
532 if ((linkp = link_by_id(getattr->ld_linkid, zoneid)) == NULL) {
1239
1240 if (oldzoneid == newzoneid)
1241 goto done;
1242
1243 /*
1244 * Before we remove the link from its current zone, make sure that
1245 * there isn't a link with the same name in the destination zone.
1246 */
1247 if (link_by_name(linkp->ll_link, newzoneid) != NULL) {
1248 err = EEXIST;
1249 goto done;
1250 }
1251
1252 if (oldzoneid != GLOBAL_ZONEID) {
1253 if (zone_remove_datalink(oldzoneid, linkid) != 0) {
1254 err = errno;
1255 dlmgmt_log(LOG_WARNING, "unable to remove link %d from "
1256 "zone %d: %s", linkid, oldzoneid, strerror(err));
1257 goto done;
1258 }
1259 linkp->ll_onloan = B_FALSE;
1260 }
1261
1262 if (newzoneid != GLOBAL_ZONEID) {
1263 if (zone_add_datalink(newzoneid, linkid) != 0) {
1264 err = errno;
1265 dlmgmt_log(LOG_WARNING, "unable to add link %d to zone "
1266 "%d: %s", linkid, newzoneid, strerror(err));
1267 (void) zone_add_datalink(oldzoneid, linkid);
1268 goto done;
1269 }
1270 linkp->ll_onloan = B_TRUE;
1271 }
1272
1273 avl_remove(&dlmgmt_name_avl, linkp);
1274 linkp->ll_zoneid = newzoneid;
1275 avl_add(&dlmgmt_name_avl, linkp);
1276
1277 done:
1278 dlmgmt_table_unlock();
|