1 /* 2 * CDDL HEADER START 3 * 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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #pragma weak getzoneid = _getzoneid 29 #pragma weak getzoneidbyname = _getzoneidbyname 30 #pragma weak getzonenamebyid = _getzonenamebyid 31 32 #include "synonyms.h" 33 #include <sys/types.h> 34 #include <sys/syscall.h> 35 #include <sys/zone.h> 36 #include <sys/priv.h> 37 #include <priv_private.h> 38 #include <zone.h> 39 #include <sys/tsol/label.h> 40 #include <dlfcn.h> 41 #include <stdlib.h> 42 #include <errno.h> 43 44 zoneid_t 45 zone_create(const char *name, const char *root, const struct priv_set *privs, 46 const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz, 47 int *extended_error, int match, int doi, const bslabel_t *label, int flags) 48 { 49 zone_def zd; 50 priv_data_t *d; 51 52 LOADPRIVDATA(d); 53 54 zd.zone_name = name; 55 zd.zone_root = root; 56 zd.zone_privs = privs; 57 zd.zone_privssz = d->pd_setsize; 58 zd.rctlbuf = rctls; 59 zd.rctlbufsz = rctlsz; 60 zd.zfsbuf = zfs; 61 zd.zfsbufsz = zfssz; 62 zd.extended_error = extended_error; 63 zd.match = match; 64 zd.doi = doi; 65 zd.label = label; 66 zd.flags = flags; 67 68 return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd)); 69 } 70 71 int 72 zone_boot(zoneid_t zoneid) 73 { 74 return (syscall(SYS_zone, ZONE_BOOT, zoneid)); 75 } 76 77 int 78 zone_shutdown(zoneid_t zoneid) 79 { 80 return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid)); 81 } 82 83 int 84 zone_destroy(zoneid_t zoneid) 85 { 86 return (syscall(SYS_zone, ZONE_DESTROY, zoneid)); 87 } 88 89 ssize_t 90 zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size) 91 { 92 sysret_t rval; 93 int error; 94 95 error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid, 96 attr, valp, size); 97 if (error) 98 (void) __set_errno(error); 99 return ((ssize_t)rval.sys_rval1); 100 } 101 102 int 103 zone_setattr(zoneid_t zoneid, int attr, void *valp, size_t size) 104 { 105 return (syscall(SYS_zone, ZONE_SETATTR, zoneid, attr, valp, size)); 106 } 107 108 int 109 zone_enter(zoneid_t zoneid) 110 { 111 return (syscall(SYS_zone, ZONE_ENTER, zoneid)); 112 } 113 114 /* 115 * Get id (if any) for specified zone. 116 * 117 * Call the real zone_get_id() in libzonecfg.so.1 if it can be found. 118 * Otherwise, perform a stripped-down version of the function. 119 * Any changes in one version should probably be reflected in the other. 120 * 121 * This stripped-down version of the function only checks for active 122 * (booted) zones, by numeric id or name. 123 */ 124 125 typedef int (*zone_get_id_t)(const char *, zoneid_t *); 126 static zone_get_id_t real_zone_get_id = NULL; 127 128 int 129 zone_get_id(const char *str, zoneid_t *zip) 130 { 131 zoneid_t zoneid; 132 char *cp; 133 134 /* 135 * The first time we are called, attempt to dlopen() libzonecfg.so.1 136 * and get a pointer to the real zone_get_id(). 137 * If we fail, set our pointer to -1 so we won't try again. 138 */ 139 if (real_zone_get_id == NULL) { 140 /* 141 * There's no harm in doing this more than once, even 142 * concurrently. We will get the same result each time, 143 * and the dynamic linker will single-thread the dlopen() 144 * with its own internal lock. The worst that can happen 145 * is that the handle gets a reference count greater than 146 * one, which doesn't matter since we never dlclose() 147 * the handle if we successfully find the symbol; the 148 * library just stays in the address space until exit(). 149 */ 150 void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY); 151 void *sym = (void *)(-1); 152 153 if (dlhandle != NULL && 154 (sym = dlsym(dlhandle, "zone_get_id")) == NULL) { 155 sym = (void *)(-1); 156 (void) dlclose(dlhandle); 157 } 158 real_zone_get_id = (zone_get_id_t)sym; 159 } 160 161 /* 162 * If we've successfully loaded it, call the real zone_get_id(). 163 * Otherwise, perform our stripped-down version of the code. 164 */ 165 if (real_zone_get_id != (zone_get_id_t)(-1)) 166 return (real_zone_get_id(str, zip)); 167 168 /* first try looking for active zone by id */ 169 errno = 0; 170 zoneid = (zoneid_t)strtol(str, &cp, 0); 171 if (errno == 0 && cp != str && *cp == '\0' && 172 getzonenamebyid(zoneid, NULL, 0) != -1) { 173 *zip = zoneid; 174 return (0); 175 } 176 177 /* then look for active zone by name */ 178 if ((zoneid = getzoneidbyname(str)) != -1) { 179 *zip = zoneid; 180 return (0); 181 } 182 183 /* not an active zone, return error */ 184 return (-1); 185 } 186 187 int 188 zone_list(zoneid_t *zonelist, uint_t *numzones) 189 { 190 return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones)); 191 } 192 193 /* 194 * Underlying implementation for getzoneid and getzoneidbyname. 195 */ 196 static zoneid_t 197 zone_lookup(const char *name) 198 { 199 return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name)); 200 } 201 202 zoneid_t 203 getzoneid(void) 204 { 205 return (zone_lookup(NULL)); 206 } 207 208 zoneid_t 209 getzoneidbyname(const char *zonename) 210 { 211 return (zone_lookup(zonename)); 212 } 213 214 ssize_t 215 getzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen) 216 { 217 return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen)); 218 } 219 220 int 221 zone_version(int *version) 222 { 223 return (syscall(SYS_zone, ZONE_VERSION, version)); 224 } 225 226 227 int 228 zone_add_datalink(zoneid_t zoneid, char *dlname) 229 { 230 return (syscall(SYS_zone, ZONE_ADD_DATALINK, zoneid, dlname)); 231 } 232 233 int 234 zone_remove_datalink(zoneid_t zoneid, char *dlname) 235 { 236 return (syscall(SYS_zone, ZONE_DEL_DATALINK, zoneid, dlname)); 237 } 238 239 int 240 zone_check_datalink(zoneid_t *zoneidp, char *dlname) 241 { 242 return (syscall(SYS_zone, ZONE_CHECK_DATALINK, zoneidp, dlname)); 243 } 244 245 int 246 zone_list_datalink(zoneid_t zoneid, int *dlnump, char *buf) 247 { 248 return (syscall(SYS_zone, ZONE_LIST_DATALINK, zoneid, dlnump, buf)); 249 } 250