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