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();
 
 |