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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #pragma weak getzoneid = _getzoneid 30 #pragma weak getzoneidbyname = _getzoneidbyname 31 #pragma weak getzonenamebyid = _getzonenamebyid 32 33 #include "synonyms.h" 34 #include <sys/types.h> 35 #include <sys/syscall.h> 36 #include <sys/zone.h> 37 #include <sys/priv.h> 38 #include <zone.h> 39 #include <dlfcn.h> 40 #include <stdlib.h> 41 #include <errno.h> 42 43 extern zoneid_t 44 zone_create(const char *name, const char *root, const struct priv_set *privs, 45 const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz, 46 int *extended_error) 47 { 48 zone_def zd; 49 50 zd.zone_name = name; 51 zd.zone_root = root; 52 zd.zone_privs = privs; 53 zd.rctlbuf = rctls; 54 zd.rctlbufsz = rctlsz; 55 zd.zfsbuf = zfs; 56 zd.zfsbufsz = zfssz; 57 zd.extended_error = extended_error; 58 59 return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd)); 60 } 61 62 int 63 zone_boot(zoneid_t zoneid, const char *bootargs) 64 { 65 return (syscall(SYS_zone, ZONE_BOOT, zoneid, bootargs)); 66 } 67 68 int 69 zone_shutdown(zoneid_t zoneid) 70 { 71 return (syscall(SYS_zone, ZONE_SHUTDOWN, zoneid)); 72 } 73 74 int 75 zone_destroy(zoneid_t zoneid) 76 { 77 return (syscall(SYS_zone, ZONE_DESTROY, zoneid)); 78 } 79 80 ssize_t 81 zone_getattr(zoneid_t zoneid, int attr, void *valp, size_t size) 82 { 83 sysret_t rval; 84 int error; 85 86 error = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid, 87 attr, valp, size); 88 if (error) 89 (void) __set_errno(error); 90 return ((ssize_t)rval.sys_rval1); 91 } 92 93 int 94 zone_enter(zoneid_t zoneid) 95 { 96 return (syscall(SYS_zone, ZONE_ENTER, zoneid)); 97 } 98 99 /* 100 * Get id (if any) for specified zone. 101 * 102 * Call the real zone_get_id() in libzonecfg.so.1 if it can be found. 103 * Otherwise, perform a stripped-down version of the function. 104 * Any changes in one version should probably be reflected in the other. 105 * 106 * This stripped-down version of the function only checks for active 107 * (booted) zones, by numeric id or name. 108 */ 109 110 typedef int (*zone_get_id_t)(const char *, zoneid_t *); 111 static zone_get_id_t real_zone_get_id = NULL; 112 113 int 114 zone_get_id(const char *str, zoneid_t *zip) 115 { 116 zoneid_t zoneid; 117 char *cp; 118 119 /* 120 * The first time we are called, attempt to dlopen() libzonecfg.so.1 121 * and get a pointer to the real zone_get_id(). 122 * If we fail, set our pointer to -1 so we won't try again. 123 */ 124 if (real_zone_get_id == NULL) { 125 /* 126 * There's no harm in doing this more than once, even 127 * concurrently. We will get the same result each time, 128 * and the dynamic linker will single-thread the dlopen() 129 * with its own internal lock. The worst that can happen 130 * is that the handle gets a reference count greater than 131 * one, which doesn't matter since we never dlclose() 132 * the handle if we successfully find the symbol; the 133 * library just stays in the address space until exit(). 134 */ 135 void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY); 136 void *sym = (void *)(-1); 137 138 if (dlhandle != NULL && 139 (sym = dlsym(dlhandle, "zone_get_id")) == NULL) { 140 sym = (void *)(-1); 141 (void) dlclose(dlhandle); 142 } 143 real_zone_get_id = (zone_get_id_t)sym; 144 } 145 146 /* 147 * If we've successfully loaded it, call the real zone_get_id(). 148 * Otherwise, perform our stripped-down version of the code. 149 */ 150 if (real_zone_get_id != (zone_get_id_t)(-1)) 151 return (real_zone_get_id(str, zip)); 152 153 /* first try looking for active zone by id */ 154 errno = 0; 155 zoneid = (zoneid_t)strtol(str, &cp, 0); 156 if (errno == 0 && cp != str && *cp == '\0' && 157 getzonenamebyid(zoneid, NULL, 0) != -1) { 158 *zip = zoneid; 159 return (0); 160 } 161 162 /* then look for active zone by name */ 163 if ((zoneid = getzoneidbyname(str)) != -1) { 164 *zip = zoneid; 165 return (0); 166 } 167 168 /* not an active zone, return error */ 169 return (-1); 170 } 171 172 int 173 zone_list(zoneid_t *zonelist, uint_t *numzones) 174 { 175 return (syscall(SYS_zone, ZONE_LIST, zonelist, numzones)); 176 } 177 178 /* 179 * Underlying implementation for getzoneid and getzoneidbyname. 180 */ 181 static zoneid_t 182 zone_lookup(const char *name) 183 { 184 return ((zoneid_t)syscall(SYS_zone, ZONE_LOOKUP, name)); 185 } 186 187 zoneid_t 188 getzoneid(void) 189 { 190 return (zone_lookup(NULL)); 191 } 192 193 zoneid_t 194 getzoneidbyname(const char *zonename) 195 { 196 return (zone_lookup(zonename)); 197 } 198 199 ssize_t 200 getzonenamebyid(zoneid_t zoneid, char *buf, size_t buflen) 201 { 202 return (zone_getattr(zoneid, ZONE_ATTR_NAME, buf, buflen)); 203 } 204