10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51676Sjpk * Common Development and Distribution License (the "License").
61676Sjpk * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
216812Sraf
220Sstevel@tonic-gate /*
23*10616SSebastien.Roy@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
276812Sraf #include "lint.h"
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/syscall.h>
300Sstevel@tonic-gate #include <sys/zone.h>
310Sstevel@tonic-gate #include <sys/priv.h>
32813Sdp #include <priv_private.h>
330Sstevel@tonic-gate #include <zone.h>
341676Sjpk #include <sys/tsol/label.h>
350Sstevel@tonic-gate #include <dlfcn.h>
360Sstevel@tonic-gate #include <stdlib.h>
370Sstevel@tonic-gate #include <errno.h>
380Sstevel@tonic-gate
391676Sjpk zoneid_t
zone_create(const char * name,const char * root,const struct priv_set * privs,const char * rctls,size_t rctlsz,const char * zfs,size_t zfssz,int * extended_error,int match,int doi,const bslabel_t * label,int flags)40789Sahrens zone_create(const char *name, const char *root, const struct priv_set *privs,
41789Sahrens const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz,
423448Sdh155122 int *extended_error, int match, int doi, const bslabel_t *label, int flags)
430Sstevel@tonic-gate {
440Sstevel@tonic-gate zone_def zd;
45813Sdp priv_data_t *d;
46813Sdp
47813Sdp LOADPRIVDATA(d);
480Sstevel@tonic-gate
490Sstevel@tonic-gate zd.zone_name = name;
500Sstevel@tonic-gate zd.zone_root = root;
510Sstevel@tonic-gate zd.zone_privs = privs;
52813Sdp zd.zone_privssz = d->pd_setsize;
530Sstevel@tonic-gate zd.rctlbuf = rctls;
540Sstevel@tonic-gate zd.rctlbufsz = rctlsz;
55789Sahrens zd.zfsbuf = zfs;
56789Sahrens zd.zfsbufsz = zfssz;
570Sstevel@tonic-gate zd.extended_error = extended_error;
581676Sjpk zd.match = match;
591676Sjpk zd.doi = doi;
601676Sjpk zd.label = label;
613448Sdh155122 zd.flags = flags;
620Sstevel@tonic-gate
63789Sahrens return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd));
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate int
zone_boot(zoneid_t zoneid)672267Sdp zone_boot(zoneid_t zoneid)
680Sstevel@tonic-gate {
692267Sdp return (syscall(SYS_zone, ZONE_BOOT, zoneid));
700Sstevel@tonic-gate }
710Sstevel@tonic-gate
720Sstevel@tonic-gate int
zone_shutdown(zoneid_t zoneid)730Sstevel@tonic-gate zone_shutdown(zoneid_t zoneid)
740Sstevel@tonic-gate {
750Sstevel@tonic-gate return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid));
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate int
zone_destroy(zoneid_t zoneid)790Sstevel@tonic-gate zone_destroy(zoneid_t zoneid)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate return (syscall(SYS_zone, ZONE_DESTROY, zoneid));
820Sstevel@tonic-gate }
830Sstevel@tonic-gate
840Sstevel@tonic-gate ssize_t
zone_getattr(zoneid_t zoneid,int attr,void * valp,size_t size)850Sstevel@tonic-gate zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate sysret_t rval;
880Sstevel@tonic-gate int error;
890Sstevel@tonic-gate
900Sstevel@tonic-gate error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
910Sstevel@tonic-gate attr, valp, size);
920Sstevel@tonic-gate if (error)
930Sstevel@tonic-gate (void) __set_errno(error);
940Sstevel@tonic-gate return ((ssize_t)rval.sys_rval1);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate int
zone_setattr(zoneid_t zoneid,int attr,void * valp,size_t size)982267Sdp zone_setattr(zoneid_t zoneid, int attr, void *valp, size_t size)
992267Sdp {
1002267Sdp return (syscall(SYS_zone, ZONE_SETATTR, zoneid, attr, valp, size));
1012267Sdp }
1022267Sdp
1032267Sdp int
zone_enter(zoneid_t zoneid)1040Sstevel@tonic-gate zone_enter(zoneid_t zoneid)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate return (syscall(SYS_zone, ZONE_ENTER, zoneid));
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate * Get id (if any) for specified zone.
1110Sstevel@tonic-gate *
1120Sstevel@tonic-gate * Call the real zone_get_id() in libzonecfg.so.1 if it can be found.
1130Sstevel@tonic-gate * Otherwise, perform a stripped-down version of the function.
1140Sstevel@tonic-gate * Any changes in one version should probably be reflected in the other.
1150Sstevel@tonic-gate *
1160Sstevel@tonic-gate * This stripped-down version of the function only checks for active
1170Sstevel@tonic-gate * (booted) zones, by numeric id or name.
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate typedef int (*zone_get_id_t)(const char *, zoneid_t *);
1210Sstevel@tonic-gate static zone_get_id_t real_zone_get_id = NULL;
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate int
zone_get_id(const char * str,zoneid_t * zip)1240Sstevel@tonic-gate zone_get_id(const char *str, zoneid_t *zip)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate zoneid_t zoneid;
1270Sstevel@tonic-gate char *cp;
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate /*
1300Sstevel@tonic-gate * The first time we are called, attempt to dlopen() libzonecfg.so.1
1310Sstevel@tonic-gate * and get a pointer to the real zone_get_id().
1320Sstevel@tonic-gate * If we fail, set our pointer to -1 so we won't try again.
1330Sstevel@tonic-gate */
1340Sstevel@tonic-gate if (real_zone_get_id == NULL) {
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate * There's no harm in doing this more than once, even
1370Sstevel@tonic-gate * concurrently. We will get the same result each time,
1380Sstevel@tonic-gate * and the dynamic linker will single-thread the dlopen()
1390Sstevel@tonic-gate * with its own internal lock. The worst that can happen
1400Sstevel@tonic-gate * is that the handle gets a reference count greater than
1410Sstevel@tonic-gate * one, which doesn't matter since we never dlclose()
1420Sstevel@tonic-gate * the handle if we successfully find the symbol; the
1430Sstevel@tonic-gate * library just stays in the address space until exit().
1440Sstevel@tonic-gate */
1450Sstevel@tonic-gate void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
1460Sstevel@tonic-gate void *sym = (void *)(-1);
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate if (dlhandle != NULL &&
1490Sstevel@tonic-gate (sym = dlsym(dlhandle, "zone_get_id")) == NULL) {
1500Sstevel@tonic-gate sym = (void *)(-1);
1510Sstevel@tonic-gate (void) dlclose(dlhandle);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate real_zone_get_id = (zone_get_id_t)sym;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate * If we've successfully loaded it, call the real zone_get_id().
1580Sstevel@tonic-gate * Otherwise, perform our stripped-down version of the code.
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate if (real_zone_get_id != (zone_get_id_t)(-1))
1610Sstevel@tonic-gate return (real_zone_get_id(str, zip));
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate /* first try looking for active zone by id */
1640Sstevel@tonic-gate errno = 0;
1650Sstevel@tonic-gate zoneid = (zoneid_t)strtol(str, &cp, 0);
1660Sstevel@tonic-gate if (errno == 0 && cp != str && *cp == '\0' &&
1670Sstevel@tonic-gate getzonenamebyid(zoneid, NULL, 0) != -1) {
1680Sstevel@tonic-gate *zip = zoneid;
1690Sstevel@tonic-gate return (0);
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /* then look for active zone by name */
1730Sstevel@tonic-gate if ((zoneid = getzoneidbyname(str)) != -1) {
1740Sstevel@tonic-gate *zip = zoneid;
1750Sstevel@tonic-gate return (0);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate /* not an active zone, return error */
1790Sstevel@tonic-gate return (-1);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate int
zone_list(zoneid_t * zonelist,uint_t * numzones)1830Sstevel@tonic-gate zone_list(zoneid_t *zonelist, uint_t *numzones)
1840Sstevel@tonic-gate {
1850Sstevel@tonic-gate return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones));
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate * Underlying implementation for getzoneid and getzoneidbyname.
1900Sstevel@tonic-gate */
1910Sstevel@tonic-gate static zoneid_t
zone_lookup(const char * name)1920Sstevel@tonic-gate zone_lookup(const char *name)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name));
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate zoneid_t
getzoneid(void)1980Sstevel@tonic-gate getzoneid(void)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate return (zone_lookup(NULL));
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate zoneid_t
getzoneidbyname(const char * zonename)2040Sstevel@tonic-gate getzoneidbyname(const char *zonename)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate return (zone_lookup(zonename));
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate ssize_t
getzonenamebyid(zoneid_t zoneid,char * buf,size_t buflen)2100Sstevel@tonic-gate getzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen));
2130Sstevel@tonic-gate }
214813Sdp
215813Sdp int
zone_version(int * version)216813Sdp zone_version(int *version)
217813Sdp {
218813Sdp return (syscall(SYS_zone, ZONE_VERSION, version));
219813Sdp }
2203448Sdh155122
2213448Sdh155122 int
zone_add_datalink(zoneid_t zoneid,datalink_id_t linkid)222*10616SSebastien.Roy@Sun.COM zone_add_datalink(zoneid_t zoneid, datalink_id_t linkid)
2233448Sdh155122 {
224*10616SSebastien.Roy@Sun.COM return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, linkid));
2253448Sdh155122 }
2263448Sdh155122
2273448Sdh155122 int
zone_remove_datalink(zoneid_t zoneid,datalink_id_t linkid)228*10616SSebastien.Roy@Sun.COM zone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid)
2293448Sdh155122 {
230*10616SSebastien.Roy@Sun.COM return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, linkid));
2313448Sdh155122 }
2323448Sdh155122
2333448Sdh155122 int
zone_check_datalink(zoneid_t * zoneidp,datalink_id_t linkid)234*10616SSebastien.Roy@Sun.COM zone_check_datalink(zoneid_t *zoneidp, datalink_id_t linkid)
2353448Sdh155122 {
236*10616SSebastien.Roy@Sun.COM return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, linkid));
2373448Sdh155122 }
2383448Sdh155122
2393448Sdh155122 int
zone_list_datalink(zoneid_t zoneid,int * dlnump,datalink_id_t * linkids)240*10616SSebastien.Roy@Sun.COM zone_list_datalink(zoneid_t zoneid, int *dlnump, datalink_id_t *linkids)
2413448Sdh155122 {
242*10616SSebastien.Roy@Sun.COM return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, linkids));
2433448Sdh155122 }
244