17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
545916cdjpk * Common Development and Distribution License (the "License").
645916cdjpk * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217257d1braf
227c478bdstevel@tonic-gate/*
232b24ab6Sebastien Roy * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277257d1braf#include "lint.h"
287c478bdstevel@tonic-gate#include <sys/types.h>
297c478bdstevel@tonic-gate#include <sys/syscall.h>
307c478bdstevel@tonic-gate#include <sys/zone.h>
317c478bdstevel@tonic-gate#include <sys/priv.h>
32821c4a9dp#include <priv_private.h>
337c478bdstevel@tonic-gate#include <zone.h>
3445916cdjpk#include <sys/tsol/label.h>
357c478bdstevel@tonic-gate#include <dlfcn.h>
367c478bdstevel@tonic-gate#include <stdlib.h>
377c478bdstevel@tonic-gate#include <errno.h>
387c478bdstevel@tonic-gate
3945916cdjpkzoneid_t
40fa9e406ahrenszone_create(const char *name, const char *root, const struct priv_set *privs,
41fa9e406ahrens    const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz,
42f4b3ec6dh    int *extended_error, int match, int doi, const bslabel_t *label, int flags)
437c478bdstevel@tonic-gate{
447c478bdstevel@tonic-gate	zone_def  zd;
45821c4a9dp	priv_data_t *d;
46821c4a9dp
47821c4a9dp	LOADPRIVDATA(d);
487c478bdstevel@tonic-gate
497c478bdstevel@tonic-gate	zd.zone_name = name;
507c478bdstevel@tonic-gate	zd.zone_root = root;
517c478bdstevel@tonic-gate	zd.zone_privs = privs;
52821c4a9dp	zd.zone_privssz = d->pd_setsize;
537c478bdstevel@tonic-gate	zd.rctlbuf = rctls;
547c478bdstevel@tonic-gate	zd.rctlbufsz = rctlsz;
55fa9e406ahrens	zd.zfsbuf = zfs;
56fa9e406ahrens	zd.zfsbufsz = zfssz;
577c478bdstevel@tonic-gate	zd.extended_error = extended_error;
5845916cdjpk	zd.match = match;
5945916cdjpk	zd.doi = doi;
6045916cdjpk	zd.label = label;
61f4b3ec6dh	zd.flags = flags;
627c478bdstevel@tonic-gate
63fa9e406ahrens	return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd));
647c478bdstevel@tonic-gate}
657c478bdstevel@tonic-gate
667c478bdstevel@tonic-gateint
673f2f09cdpzone_boot(zoneid_t zoneid)
687c478bdstevel@tonic-gate{
693f2f09cdp	return (syscall(SYS_zone, ZONE_BOOT, zoneid));
707c478bdstevel@tonic-gate}
717c478bdstevel@tonic-gate
727c478bdstevel@tonic-gateint
737c478bdstevel@tonic-gatezone_shutdown(zoneid_t zoneid)
747c478bdstevel@tonic-gate{
757c478bdstevel@tonic-gate	return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid));
767c478bdstevel@tonic-gate}
777c478bdstevel@tonic-gate
787c478bdstevel@tonic-gateint
797c478bdstevel@tonic-gatezone_destroy(zoneid_t zoneid)
807c478bdstevel@tonic-gate{
817c478bdstevel@tonic-gate	return (syscall(SYS_zone, ZONE_DESTROY, zoneid));
827c478bdstevel@tonic-gate}
837c478bdstevel@tonic-gate
847c478bdstevel@tonic-gatessize_t
857c478bdstevel@tonic-gatezone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size)
867c478bdstevel@tonic-gate{
877c478bdstevel@tonic-gate	sysret_t rval;
887c478bdstevel@tonic-gate	int error;
897c478bdstevel@tonic-gate
907c478bdstevel@tonic-gate	error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
917c478bdstevel@tonic-gate	    attr, valp, size);
927c478bdstevel@tonic-gate	if (error)
937c478bdstevel@tonic-gate		(void) __set_errno(error);
947c478bdstevel@tonic-gate	return ((ssize_t)rval.sys_rval1);
957c478bdstevel@tonic-gate}
967c478bdstevel@tonic-gate
977c478bdstevel@tonic-gateint
983f2f09cdpzone_setattr(zoneid_t zoneid, int attr, void *valp, size_t size)
993f2f09cdp{
1003f2f09cdp	return (syscall(SYS_zone, ZONE_SETATTR, zoneid, attr, valp, size));
1013f2f09cdp}
1023f2f09cdp
1033f2f09cdpint
1047c478bdstevel@tonic-gatezone_enter(zoneid_t zoneid)
1057c478bdstevel@tonic-gate{
1067c478bdstevel@tonic-gate	return (syscall(SYS_zone, ZONE_ENTER, zoneid));
1077c478bdstevel@tonic-gate}
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gate/*
1107c478bdstevel@tonic-gate * Get id (if any) for specified zone.
1117c478bdstevel@tonic-gate *
1127c478bdstevel@tonic-gate * Call the real zone_get_id() in libzonecfg.so.1 if it can be found.
1137c478bdstevel@tonic-gate * Otherwise, perform a stripped-down version of the function.
1147c478bdstevel@tonic-gate * Any changes in one version should probably be reflected in the other.
1157c478bdstevel@tonic-gate *
1167c478bdstevel@tonic-gate * This stripped-down version of the function only checks for active
1177c478bdstevel@tonic-gate * (booted) zones, by numeric id or name.
1187c478bdstevel@tonic-gate */
1197c478bdstevel@tonic-gate
1207c478bdstevel@tonic-gatetypedef	int (*zone_get_id_t)(const char *, zoneid_t *);
1217c478bdstevel@tonic-gatestatic zone_get_id_t real_zone_get_id = NULL;
1227c478bdstevel@tonic-gate
1237c478bdstevel@tonic-gateint
1247c478bdstevel@tonic-gatezone_get_id(const char *str, zoneid_t *zip)
1257c478bdstevel@tonic-gate{
1267c478bdstevel@tonic-gate	zoneid_t zoneid;
1277c478bdstevel@tonic-gate	char *cp;
1287c478bdstevel@tonic-gate
1297c478bdstevel@tonic-gate	/*
1307c478bdstevel@tonic-gate	 * The first time we are called, attempt to dlopen() libzonecfg.so.1
1317c478bdstevel@tonic-gate	 * and get a pointer to the real zone_get_id().
1327c478bdstevel@tonic-gate	 * If we fail, set our pointer to -1 so we won't try again.
1337c478bdstevel@tonic-gate	 */
1347c478bdstevel@tonic-gate	if (real_zone_get_id == NULL) {
1357c478bdstevel@tonic-gate		/*
1367c478bdstevel@tonic-gate		 * There's no harm in doing this more than once, even
1377c478bdstevel@tonic-gate		 * concurrently.  We will get the same result each time,
1387c478bdstevel@tonic-gate		 * and the dynamic linker will single-thread the dlopen()
1397c478bdstevel@tonic-gate		 * with its own internal lock.  The worst that can happen
1407c478bdstevel@tonic-gate		 * is that the handle gets a reference count greater than
1417c478bdstevel@tonic-gate		 * one, which doesn't matter since we never dlclose()
1427c478bdstevel@tonic-gate		 * the handle if we successfully find the symbol; the
1437c478bdstevel@tonic-gate		 * library just stays in the address space until exit().
1447c478bdstevel@tonic-gate		 */
1457c478bdstevel@tonic-gate		void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
1467c478bdstevel@tonic-gate		void *sym = (void *)(-1);
1477c478bdstevel@tonic-gate
1487c478bdstevel@tonic-gate		if (dlhandle != NULL &&
1497c478bdstevel@tonic-gate		    (sym = dlsym(dlhandle, "zone_get_id")) == NULL) {
1507c478bdstevel@tonic-gate			sym = (void *)(-1);
1517c478bdstevel@tonic-gate			(void) dlclose(dlhandle);
1527c478bdstevel@tonic-gate		}
1537c478bdstevel@tonic-gate		real_zone_get_id = (zone_get_id_t)sym;
1547c478bdstevel@tonic-gate	}
1557c478bdstevel@tonic-gate
1567c478bdstevel@tonic-gate	/*
1577c478bdstevel@tonic-gate	 * If we've successfully loaded it, call the real zone_get_id().
1587c478bdstevel@tonic-gate	 * Otherwise, perform our stripped-down version of the code.
1597c478bdstevel@tonic-gate	 */
1607c478bdstevel@tonic-gate	if (real_zone_get_id != (zone_get_id_t)(-1))
1617c478bdstevel@tonic-gate		return (real_zone_get_id(str, zip));
1627c478bdstevel@tonic-gate
1637c478bdstevel@tonic-gate	/* first try looking for active zone by id */
1647c478bdstevel@tonic-gate	errno = 0;
1657c478bdstevel@tonic-gate	zoneid = (zoneid_t)strtol(str, &cp, 0);
1667c478bdstevel@tonic-gate	if (errno == 0 && cp != str && *cp == '\0' &&
1677c478bdstevel@tonic-gate	    getzonenamebyid(zoneid, NULL, 0) != -1) {
1687c478bdstevel@tonic-gate		*zip = zoneid;
1697c478bdstevel@tonic-gate		return (0);
1707c478bdstevel@tonic-gate	}
1717c478bdstevel@tonic-gate
1727c478bdstevel@tonic-gate	/* then look for active zone by name */
1737c478bdstevel@tonic-gate	if ((zoneid = getzoneidbyname(str)) != -1) {
1747c478bdstevel@tonic-gate		*zip = zoneid;
1757c478bdstevel@tonic-gate		return (0);
1767c478bdstevel@tonic-gate	}
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate	/* not an active zone, return error */
1797c478bdstevel@tonic-gate	return (-1);
1807c478bdstevel@tonic-gate}
1817c478bdstevel@tonic-gate
1827c478bdstevel@tonic-gateint
1837c478bdstevel@tonic-gatezone_list(zoneid_t *zonelist, uint_t *numzones)
1847c478bdstevel@tonic-gate{
1857c478bdstevel@tonic-gate	return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones));
1867c478bdstevel@tonic-gate}
1877c478bdstevel@tonic-gate
1887c478bdstevel@tonic-gate/*
1897c478bdstevel@tonic-gate * Underlying implementation for getzoneid and getzoneidbyname.
1907c478bdstevel@tonic-gate */
1917c478bdstevel@tonic-gatestatic zoneid_t
1927c478bdstevel@tonic-gatezone_lookup(const char *name)
1937c478bdstevel@tonic-gate{
1947c478bdstevel@tonic-gate	return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name));
1957c478bdstevel@tonic-gate}
1967c478bdstevel@tonic-gate
1977c478bdstevel@tonic-gatezoneid_t
1987c478bdstevel@tonic-gategetzoneid(void)
1997c478bdstevel@tonic-gate{
2007c478bdstevel@tonic-gate	return (zone_lookup(NULL));
2017c478bdstevel@tonic-gate}
2027c478bdstevel@tonic-gate
2037c478bdstevel@tonic-gatezoneid_t
2047c478bdstevel@tonic-gategetzoneidbyname(const char *zonename)
2057c478bdstevel@tonic-gate{
2067c478bdstevel@tonic-gate	return (zone_lookup(zonename));
2077c478bdstevel@tonic-gate}
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gatessize_t
2107c478bdstevel@tonic-gategetzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen)
2117c478bdstevel@tonic-gate{
2127c478bdstevel@tonic-gate	return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen));
2137c478bdstevel@tonic-gate}
214821c4a9dp
215821c4a9dpint
216821c4a9dpzone_version(int *version)
217821c4a9dp{
218821c4a9dp	return (syscall(SYS_zone, ZONE_VERSION, version));
219821c4a9dp}
220f4b3ec6dh
221f4b3ec6dhint
2222b24ab6Sebastien Royzone_add_datalink(zoneid_t zoneid, datalink_id_t linkid)
223f4b3ec6dh{
2242b24ab6Sebastien Roy	return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, linkid));
225f4b3ec6dh}
226f4b3ec6dh
227f4b3ec6dhint
2282b24ab6Sebastien Royzone_remove_datalink(zoneid_t zoneid, datalink_id_t linkid)
229f4b3ec6dh{
2302b24ab6Sebastien Roy	return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, linkid));
231f4b3ec6dh}
232f4b3ec6dh
233f4b3ec6dhint
2342b24ab6Sebastien Royzone_check_datalink(zoneid_t *zoneidp, datalink_id_t linkid)
235f4b3ec6dh{
2362b24ab6Sebastien Roy	return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, linkid));
237f4b3ec6dh}
238f4b3ec6dh
239f4b3ec6dhint
2402b24ab6Sebastien Royzone_list_datalink(zoneid_t zoneid, int *dlnump, datalink_id_t *linkids)
241f4b3ec6dh{
2422b24ab6Sebastien Roy	return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, linkids));
243f4b3ec6dh}
244