19acbbeafSnn35248 /* 29acbbeafSnn35248 * CDDL HEADER START 39acbbeafSnn35248 * 49acbbeafSnn35248 * The contents of this file are subject to the terms of the 59acbbeafSnn35248 * Common Development and Distribution License (the "License"). 69acbbeafSnn35248 * You may not use this file except in compliance with the License. 79acbbeafSnn35248 * 89acbbeafSnn35248 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99acbbeafSnn35248 * or http://www.opensolaris.org/os/licensing. 109acbbeafSnn35248 * See the License for the specific language governing permissions 119acbbeafSnn35248 * and limitations under the License. 129acbbeafSnn35248 * 139acbbeafSnn35248 * When distributing Covered Code, include this CDDL HEADER in each 149acbbeafSnn35248 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159acbbeafSnn35248 * If applicable, add the following below this CDDL HEADER, with the 169acbbeafSnn35248 * fields enclosed by brackets "[]" replaced with your own identifying 179acbbeafSnn35248 * information: Portions Copyright [yyyy] [name of copyright owner] 189acbbeafSnn35248 * 199acbbeafSnn35248 * CDDL HEADER END 209acbbeafSnn35248 */ 219acbbeafSnn35248 229acbbeafSnn35248 /* 23a20ee416SGlenn Faden * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24*bafd1f14SJerry Jelinek * Copyright (c) 2011, Joyent, Inc. All rights reserved. 253c7284bdSAlexander Eremin * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 269acbbeafSnn35248 */ 279acbbeafSnn35248 289acbbeafSnn35248 #include <assert.h> 299acbbeafSnn35248 #include <dirent.h> 309acbbeafSnn35248 #include <errno.h> 319acbbeafSnn35248 #include <fnmatch.h> 329acbbeafSnn35248 #include <signal.h> 339acbbeafSnn35248 #include <stdlib.h> 349acbbeafSnn35248 #include <unistd.h> 359acbbeafSnn35248 #include <strings.h> 369acbbeafSnn35248 #include <synch.h> 379acbbeafSnn35248 #include <sys/brand.h> 389acbbeafSnn35248 #include <sys/fcntl.h> 399acbbeafSnn35248 #include <sys/param.h> 409acbbeafSnn35248 #include <sys/stat.h> 419acbbeafSnn35248 #include <sys/systeminfo.h> 429acbbeafSnn35248 #include <sys/types.h> 439acbbeafSnn35248 #include <thread.h> 449acbbeafSnn35248 #include <zone.h> 459acbbeafSnn35248 469acbbeafSnn35248 #include <libbrand_impl.h> 479acbbeafSnn35248 #include <libbrand.h> 489acbbeafSnn35248 49ff17c8bfSgjelinek #define DTD_ELEM_ATTACH ((const xmlChar *) "attach") 509acbbeafSnn35248 #define DTD_ELEM_BOOT ((const xmlChar *) "boot") 519acbbeafSnn35248 #define DTD_ELEM_BRAND ((const xmlChar *) "brand") 52ff17c8bfSgjelinek #define DTD_ELEM_CLONE ((const xmlChar *) "clone") 539acbbeafSnn35248 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment") 54ff17c8bfSgjelinek #define DTD_ELEM_DETACH ((const xmlChar *) "detach") 559acbbeafSnn35248 #define DTD_ELEM_DEVICE ((const xmlChar *) "device") 569acbbeafSnn35248 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount") 579acbbeafSnn35248 #define DTD_ELEM_HALT ((const xmlChar *) "halt") 589acbbeafSnn35248 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname") 599acbbeafSnn35248 #define DTD_ELEM_INSTALL ((const xmlChar *) "install") 609acbbeafSnn35248 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts") 619acbbeafSnn35248 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd") 62cb8a054bSGlenn Faden #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd") 639acbbeafSnn35248 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname") 649acbbeafSnn35248 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount") 65*bafd1f14SJerry Jelinek #define DTD_ELEM_RESTARTINIT ((const xmlChar *) "restartinit") 6637774979Sgjelinek #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach") 679acbbeafSnn35248 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone") 681100f00dSgjelinek #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall") 69ff17c8bfSgjelinek #define DTD_ELEM_POSTSNAP ((const xmlChar *) "postsnap") 70c5cd6260S #define DTD_ELEM_POSTSTATECHG ((const xmlChar *) "poststatechange") 7137774979Sgjelinek #define DTD_ELEM_PREDETACH ((const xmlChar *) "predetach") 72ff17c8bfSgjelinek #define DTD_ELEM_PRESNAP ((const xmlChar *) "presnap") 73c5cd6260S #define DTD_ELEM_PRESTATECHG ((const xmlChar *) "prestatechange") 7437774979Sgjelinek #define DTD_ELEM_PREUNINSTALL ((const xmlChar *) "preuninstall") 759acbbeafSnn35248 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege") 76c5cd6260S #define DTD_ELEM_QUERY ((const xmlChar *) "query") 773c7284bdSAlexander Eremin #define DTD_ELEM_SHUTDOWN ((const xmlChar *) "shutdown") 789acbbeafSnn35248 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink") 79fbbfbc6eSjv227347 #define DTD_ELEM_SYSBOOT ((const xmlChar *) "sysboot") 80ff17c8bfSgjelinek #define DTD_ELEM_UNINSTALL ((const xmlChar *) "uninstall") 81858a4b99Ssl108498 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd") 82ff17c8bfSgjelinek #define DTD_ELEM_VALIDSNAP ((const xmlChar *) "validatesnap") 839acbbeafSnn35248 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg") 849acbbeafSnn35248 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm") 859acbbeafSnn35248 86f4b3ec61Sdh155122 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip") 879acbbeafSnn35248 #define DTD_ATTR_ARCH ((const xmlChar *) "arch") 889acbbeafSnn35248 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory") 89f4b3ec61Sdh155122 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type") 909acbbeafSnn35248 #define DTD_ATTR_MATCH ((const xmlChar *) "match") 919acbbeafSnn35248 #define DTD_ATTR_MODE ((const xmlChar *) "mode") 929acbbeafSnn35248 #define DTD_ATTR_NAME ((const xmlChar *) "name") 939acbbeafSnn35248 #define DTD_ATTR_OPT ((const xmlChar *) "opt") 949acbbeafSnn35248 #define DTD_ATTR_PATH ((const xmlChar *) "path") 959acbbeafSnn35248 #define DTD_ATTR_SET ((const xmlChar *) "set") 969acbbeafSnn35248 #define DTD_ATTR_SOURCE ((const xmlChar *) "source") 979acbbeafSnn35248 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special") 989acbbeafSnn35248 #define DTD_ATTR_TARGET ((const xmlChar *) "target") 999acbbeafSnn35248 #define DTD_ATTR_TYPE ((const xmlChar *) "type") 1009acbbeafSnn35248 101f4b3ec61Sdh155122 #define DTD_ENTITY_TRUE "true" 102f4b3ec61Sdh155122 1039acbbeafSnn35248 static volatile boolean_t libbrand_initialized = B_FALSE; 1049acbbeafSnn35248 static char i_curr_arch[MAXNAMELEN]; 1059acbbeafSnn35248 static char i_curr_zone[ZONENAME_MAX]; 1069acbbeafSnn35248 1079acbbeafSnn35248 /*ARGSUSED*/ 1089acbbeafSnn35248 static void 1099acbbeafSnn35248 brand_error_func(void *ctx, const char *msg, ...) 1109acbbeafSnn35248 { 1119acbbeafSnn35248 /* 1129acbbeafSnn35248 * Ignore error messages from libxml 1139acbbeafSnn35248 */ 1149acbbeafSnn35248 } 1159acbbeafSnn35248 1169acbbeafSnn35248 static boolean_t 1179acbbeafSnn35248 libbrand_initialize() 1189acbbeafSnn35248 { 1199acbbeafSnn35248 static mutex_t initialize_lock = DEFAULTMUTEX; 1209acbbeafSnn35248 1219acbbeafSnn35248 (void) mutex_lock(&initialize_lock); 1229acbbeafSnn35248 1239acbbeafSnn35248 if (libbrand_initialized) { 1249acbbeafSnn35248 (void) mutex_unlock(&initialize_lock); 1259acbbeafSnn35248 return (B_TRUE); 1269acbbeafSnn35248 } 1279acbbeafSnn35248 1289acbbeafSnn35248 if (sysinfo(SI_ARCHITECTURE, i_curr_arch, sizeof (i_curr_arch)) < 0) { 1299acbbeafSnn35248 (void) mutex_unlock(&initialize_lock); 1309acbbeafSnn35248 return (B_FALSE); 1319acbbeafSnn35248 } 1329acbbeafSnn35248 1339acbbeafSnn35248 if (getzonenamebyid(getzoneid(), i_curr_zone, 1349acbbeafSnn35248 sizeof (i_curr_zone)) < 0) { 1359acbbeafSnn35248 (void) mutex_unlock(&initialize_lock); 1369acbbeafSnn35248 return (B_FALSE); 1379acbbeafSnn35248 } 1389acbbeafSnn35248 1399acbbeafSnn35248 /* 1409acbbeafSnn35248 * Note that here we're initializing per-process libxml2 1419acbbeafSnn35248 * state. By doing so we're implicitly assuming that 1429acbbeafSnn35248 * no other code in this process is also trying to 1439acbbeafSnn35248 * use libxml2. But in most case we know this not to 1449acbbeafSnn35248 * be true since we're almost always used in conjunction 1459acbbeafSnn35248 * with libzonecfg, which also uses libxml2. Lucky for 1469acbbeafSnn35248 * us, libzonecfg initializes libxml2 to essentially 1479acbbeafSnn35248 * the same defaults as we're using below. 1489acbbeafSnn35248 */ 1495ad42b1bSSurya Prakki (void) xmlLineNumbersDefault(1); 1509acbbeafSnn35248 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 1519acbbeafSnn35248 xmlDoValidityCheckingDefaultValue = 1; 1529acbbeafSnn35248 (void) xmlKeepBlanksDefault(0); 1539acbbeafSnn35248 xmlGetWarningsDefaultValue = 0; 1549acbbeafSnn35248 xmlSetGenericErrorFunc(NULL, brand_error_func); 1559acbbeafSnn35248 1569acbbeafSnn35248 libbrand_initialized = B_TRUE; 1579acbbeafSnn35248 (void) mutex_unlock(&initialize_lock); 1589acbbeafSnn35248 return (B_TRUE); 1599acbbeafSnn35248 } 1609acbbeafSnn35248 1619acbbeafSnn35248 static const char * 1629acbbeafSnn35248 get_curr_arch(void) 1639acbbeafSnn35248 { 1649acbbeafSnn35248 if (!libbrand_initialize()) 1659acbbeafSnn35248 return (NULL); 1669acbbeafSnn35248 1679acbbeafSnn35248 return (i_curr_arch); 1689acbbeafSnn35248 } 1699acbbeafSnn35248 1709acbbeafSnn35248 static const char * 1719acbbeafSnn35248 get_curr_zone(void) 1729acbbeafSnn35248 { 1739acbbeafSnn35248 if (!libbrand_initialize()) 1749acbbeafSnn35248 return (NULL); 1759acbbeafSnn35248 1769acbbeafSnn35248 return (i_curr_zone); 1779acbbeafSnn35248 } 1789acbbeafSnn35248 1799acbbeafSnn35248 /* 1809acbbeafSnn35248 * Internal function to open an XML file 1819acbbeafSnn35248 * 1829acbbeafSnn35248 * Returns the XML doc pointer, or NULL on failure. It will validate the 1839acbbeafSnn35248 * document, as well as removing any comments from the document structure. 1849acbbeafSnn35248 */ 1859acbbeafSnn35248 static xmlDocPtr 1869acbbeafSnn35248 open_xml_file(const char *file) 1879acbbeafSnn35248 { 1889acbbeafSnn35248 xmlDocPtr doc; 1899acbbeafSnn35248 xmlValidCtxtPtr cvp; 1909acbbeafSnn35248 int valid; 1919acbbeafSnn35248 1929acbbeafSnn35248 if (!libbrand_initialize()) 1939acbbeafSnn35248 return (NULL); 1949acbbeafSnn35248 1959acbbeafSnn35248 /* 1969acbbeafSnn35248 * Parse the file 1979acbbeafSnn35248 */ 1989acbbeafSnn35248 if ((doc = xmlParseFile(file)) == NULL) 1999acbbeafSnn35248 return (NULL); 2009acbbeafSnn35248 2019acbbeafSnn35248 /* 2029acbbeafSnn35248 * Validate the file 2039acbbeafSnn35248 */ 2049acbbeafSnn35248 if ((cvp = xmlNewValidCtxt()) == NULL) { 2059acbbeafSnn35248 xmlFreeDoc(doc); 2069acbbeafSnn35248 return (NULL); 2079acbbeafSnn35248 } 2089acbbeafSnn35248 cvp->error = brand_error_func; 2099acbbeafSnn35248 cvp->warning = brand_error_func; 2109acbbeafSnn35248 valid = xmlValidateDocument(cvp, doc); 2119acbbeafSnn35248 xmlFreeValidCtxt(cvp); 2129acbbeafSnn35248 if (valid == 0) { 2139acbbeafSnn35248 xmlFreeDoc(doc); 2149acbbeafSnn35248 return (NULL); 2159acbbeafSnn35248 } 2169acbbeafSnn35248 2179acbbeafSnn35248 return (doc); 2189acbbeafSnn35248 } 2199acbbeafSnn35248 /* 2209acbbeafSnn35248 * Open a handle to the named brand. 2219acbbeafSnn35248 * 2229acbbeafSnn35248 * Returns a handle to the named brand, which is used for all subsequent brand 2239acbbeafSnn35248 * interaction, or NULL if unable to open or initialize the brand. 2249acbbeafSnn35248 */ 225123807fbSedp brand_handle_t 2269acbbeafSnn35248 brand_open(const char *name) 2279acbbeafSnn35248 { 228123807fbSedp struct brand_handle *bhp; 2299acbbeafSnn35248 char path[MAXPATHLEN]; 2309acbbeafSnn35248 xmlNodePtr node; 2319acbbeafSnn35248 xmlChar *property; 2329acbbeafSnn35248 struct stat statbuf; 2339acbbeafSnn35248 2349acbbeafSnn35248 /* 2359acbbeafSnn35248 * Make sure brand name isn't too long 2369acbbeafSnn35248 */ 2379acbbeafSnn35248 if (strlen(name) >= MAXNAMELEN) 2389acbbeafSnn35248 return (NULL); 2399acbbeafSnn35248 2409acbbeafSnn35248 /* 2419acbbeafSnn35248 * Check that the brand exists 2429acbbeafSnn35248 */ 2439acbbeafSnn35248 (void) snprintf(path, sizeof (path), "%s/%s", BRAND_DIR, name); 2449acbbeafSnn35248 2459acbbeafSnn35248 if (stat(path, &statbuf) != 0) 2469acbbeafSnn35248 return (NULL); 2479acbbeafSnn35248 2489acbbeafSnn35248 /* 2499acbbeafSnn35248 * Allocate brand handle 2509acbbeafSnn35248 */ 251123807fbSedp if ((bhp = malloc(sizeof (struct brand_handle))) == NULL) 2529acbbeafSnn35248 return (NULL); 253123807fbSedp bzero(bhp, sizeof (struct brand_handle)); 2549acbbeafSnn35248 2559acbbeafSnn35248 (void) strcpy(bhp->bh_name, name); 2569acbbeafSnn35248 2579acbbeafSnn35248 /* 2589acbbeafSnn35248 * Open the configuration file 2599acbbeafSnn35248 */ 2609acbbeafSnn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2619acbbeafSnn35248 BRAND_CONFIG); 2629acbbeafSnn35248 if ((bhp->bh_config = open_xml_file(path)) == NULL) { 263123807fbSedp brand_close((brand_handle_t)bhp); 2649acbbeafSnn35248 return (NULL); 2659acbbeafSnn35248 } 2669acbbeafSnn35248 2679acbbeafSnn35248 /* 2689acbbeafSnn35248 * Verify that the name of the brand matches the directory in which it 2699acbbeafSnn35248 * is installed. 2709acbbeafSnn35248 */ 2719acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) { 272123807fbSedp brand_close((brand_handle_t)bhp); 2739acbbeafSnn35248 return (NULL); 2749acbbeafSnn35248 } 2759acbbeafSnn35248 2769acbbeafSnn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) { 277123807fbSedp brand_close((brand_handle_t)bhp); 2789acbbeafSnn35248 return (NULL); 2799acbbeafSnn35248 } 2809acbbeafSnn35248 2819acbbeafSnn35248 if ((property = xmlGetProp(node, DTD_ATTR_NAME)) == NULL) { 282123807fbSedp brand_close((brand_handle_t)bhp); 2839acbbeafSnn35248 return (NULL); 2849acbbeafSnn35248 } 2859acbbeafSnn35248 2869acbbeafSnn35248 if (strcmp((char *)property, name) != 0) { 2879acbbeafSnn35248 xmlFree(property); 288123807fbSedp brand_close((brand_handle_t)bhp); 2899acbbeafSnn35248 return (NULL); 2909acbbeafSnn35248 } 2919acbbeafSnn35248 xmlFree(property); 2929acbbeafSnn35248 2939acbbeafSnn35248 /* 2949acbbeafSnn35248 * Open handle to platform configuration file. 2959acbbeafSnn35248 */ 2969acbbeafSnn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2979acbbeafSnn35248 BRAND_PLATFORM); 2989acbbeafSnn35248 if ((bhp->bh_platform = open_xml_file(path)) == NULL) { 299123807fbSedp brand_close((brand_handle_t)bhp); 3009acbbeafSnn35248 return (NULL); 3019acbbeafSnn35248 } 3029acbbeafSnn35248 303123807fbSedp return ((brand_handle_t)bhp); 3049acbbeafSnn35248 } 3059acbbeafSnn35248 3069acbbeafSnn35248 /* 3079acbbeafSnn35248 * Closes the given brand handle 3089acbbeafSnn35248 */ 3099acbbeafSnn35248 void 310123807fbSedp brand_close(brand_handle_t bh) 3119acbbeafSnn35248 { 312123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 3139acbbeafSnn35248 if (bhp->bh_platform != NULL) 3149acbbeafSnn35248 xmlFreeDoc(bhp->bh_platform); 3159acbbeafSnn35248 if (bhp->bh_config != NULL) 3169acbbeafSnn35248 xmlFreeDoc(bhp->bh_config); 3179acbbeafSnn35248 free(bhp); 3189acbbeafSnn35248 } 3199acbbeafSnn35248 3209acbbeafSnn35248 static int 3219acbbeafSnn35248 i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size, 322ff17c8bfSgjelinek const char *zonename, const char *zonepath, const char *username, 323ff17c8bfSgjelinek const char *curr_zone) 3249acbbeafSnn35248 { 325ff17c8bfSgjelinek int dst, src; 3269acbbeafSnn35248 3279acbbeafSnn35248 /* 3289acbbeafSnn35248 * Walk through the characters, substituting values as needed. 3299acbbeafSnn35248 */ 3309acbbeafSnn35248 dbuf[0] = '\0'; 3319acbbeafSnn35248 dst = 0; 3329acbbeafSnn35248 for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) { 3339acbbeafSnn35248 if (sbuf[src] != '%') { 3349acbbeafSnn35248 dbuf[dst++] = sbuf[src]; 3359acbbeafSnn35248 continue; 3369acbbeafSnn35248 } 3379acbbeafSnn35248 3389acbbeafSnn35248 switch (sbuf[++src]) { 3399acbbeafSnn35248 case '%': 3409acbbeafSnn35248 dst += strlcpy(dbuf + dst, "%", dbuf_size - dst); 3419acbbeafSnn35248 break; 3429acbbeafSnn35248 case 'R': 343ff17c8bfSgjelinek if (zonepath == NULL) 3449acbbeafSnn35248 break; 345ff17c8bfSgjelinek dst += strlcpy(dbuf + dst, zonepath, dbuf_size - dst); 3469acbbeafSnn35248 break; 3479acbbeafSnn35248 case 'u': 3489acbbeafSnn35248 if (username == NULL) 3499acbbeafSnn35248 break; 3509acbbeafSnn35248 dst += strlcpy(dbuf + dst, username, dbuf_size - dst); 3519acbbeafSnn35248 break; 3529acbbeafSnn35248 case 'Z': 3539acbbeafSnn35248 if (curr_zone == NULL) 3549acbbeafSnn35248 break; 3559acbbeafSnn35248 /* name of the zone we're running in */ 3569acbbeafSnn35248 dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst); 3579acbbeafSnn35248 break; 3589acbbeafSnn35248 case 'z': 3599acbbeafSnn35248 /* name of the zone we're operating on */ 3609acbbeafSnn35248 if (zonename == NULL) 3619acbbeafSnn35248 break; 3629acbbeafSnn35248 dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst); 3639acbbeafSnn35248 break; 3649acbbeafSnn35248 } 3659acbbeafSnn35248 } 3669acbbeafSnn35248 3679acbbeafSnn35248 if (dst >= dbuf_size) 3689acbbeafSnn35248 return (-1); 3699acbbeafSnn35248 3709acbbeafSnn35248 dbuf[dst] = '\0'; 3719acbbeafSnn35248 return (0); 3729acbbeafSnn35248 } 3739acbbeafSnn35248 3749acbbeafSnn35248 /* 3759acbbeafSnn35248 * Retrieve the given tag from the brand. 3769acbbeafSnn35248 * Perform the following substitutions as necessary: 3779acbbeafSnn35248 * 3789acbbeafSnn35248 * %% % 3799acbbeafSnn35248 * %u Username 3809acbbeafSnn35248 * %z Name of target zone 3819acbbeafSnn35248 * %Z Name of current zone 382ff17c8bfSgjelinek * %R Zonepath of zone 3839acbbeafSnn35248 * 3849acbbeafSnn35248 * Returns 0 on success, -1 on failure. 3859acbbeafSnn35248 */ 3869acbbeafSnn35248 static int 387123807fbSedp brand_get_value(struct brand_handle *bhp, const char *zonename, 388ff17c8bfSgjelinek const char *zonepath, const char *username, const char *curr_zone, 389ff17c8bfSgjelinek char *buf, size_t len, const xmlChar *tagname, 3909acbbeafSnn35248 boolean_t substitute, boolean_t optional) 3919acbbeafSnn35248 { 3929acbbeafSnn35248 xmlNodePtr node; 3939acbbeafSnn35248 xmlChar *content; 3949acbbeafSnn35248 int err = 0; 3959acbbeafSnn35248 3969acbbeafSnn35248 /* 3979acbbeafSnn35248 * Retrieve the specified value from the XML doc 3989acbbeafSnn35248 */ 3999acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 4009acbbeafSnn35248 return (-1); 4019acbbeafSnn35248 4029acbbeafSnn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) 4039acbbeafSnn35248 return (-1); 4049acbbeafSnn35248 4059acbbeafSnn35248 for (node = node->xmlChildrenNode; node != NULL; 4069acbbeafSnn35248 node = node->next) { 4079acbbeafSnn35248 if (xmlStrcmp(node->name, tagname) == 0) 4089acbbeafSnn35248 break; 4099acbbeafSnn35248 } 4109acbbeafSnn35248 411db52f3aeSgjelinek if (node == NULL) { 412db52f3aeSgjelinek if (optional) { 413db52f3aeSgjelinek buf[0] = '\0'; 414db52f3aeSgjelinek return (0); 415db52f3aeSgjelinek } else { 4169acbbeafSnn35248 return (-1); 417db52f3aeSgjelinek } 418db52f3aeSgjelinek } 4199acbbeafSnn35248 4209acbbeafSnn35248 if ((content = xmlNodeGetContent(node)) == NULL) 4219acbbeafSnn35248 return (-1); 4229acbbeafSnn35248 4239acbbeafSnn35248 if (strlen((char *)content) == 0) { 4249acbbeafSnn35248 /* 4259acbbeafSnn35248 * If the entry in the config file is empty, check to see 4269acbbeafSnn35248 * whether this is an optional field. If so, we return the 4279acbbeafSnn35248 * empty buffer. If not, we return an error. 4289acbbeafSnn35248 */ 4299acbbeafSnn35248 if (optional) { 4309acbbeafSnn35248 buf[0] = '\0'; 4319acbbeafSnn35248 } else { 4329acbbeafSnn35248 err = -1; 4339acbbeafSnn35248 } 4349acbbeafSnn35248 } else { 4359acbbeafSnn35248 /* Substitute token values as needed. */ 4369acbbeafSnn35248 if (substitute) { 4379acbbeafSnn35248 if (i_substitute_tokens((char *)content, buf, len, 438ff17c8bfSgjelinek zonename, zonepath, username, curr_zone) != 0) 4399acbbeafSnn35248 err = -1; 4409acbbeafSnn35248 } else { 4419acbbeafSnn35248 if (strlcpy(buf, (char *)content, len) >= len) 4429acbbeafSnn35248 err = -1; 4439acbbeafSnn35248 } 4449acbbeafSnn35248 } 4459acbbeafSnn35248 4469acbbeafSnn35248 xmlFree(content); 4479acbbeafSnn35248 4489acbbeafSnn35248 return (err); 4499acbbeafSnn35248 } 4509acbbeafSnn35248 4519acbbeafSnn35248 int 452ff17c8bfSgjelinek brand_get_attach(brand_handle_t bh, const char *zonename, 453ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 4549acbbeafSnn35248 { 455123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 456ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 457ff17c8bfSgjelinek buf, len, DTD_ELEM_ATTACH, B_TRUE, B_TRUE)); 458ff17c8bfSgjelinek } 459ff17c8bfSgjelinek 460ff17c8bfSgjelinek int 461ff17c8bfSgjelinek brand_get_boot(brand_handle_t bh, const char *zonename, 462ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 463ff17c8bfSgjelinek { 464ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 465ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 466ff17c8bfSgjelinek buf, len, DTD_ELEM_BOOT, B_TRUE, B_TRUE)); 4679acbbeafSnn35248 } 4689acbbeafSnn35248 4699acbbeafSnn35248 int 470123807fbSedp brand_get_brandname(brand_handle_t bh, char *buf, size_t len) 4719acbbeafSnn35248 { 472123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 4739acbbeafSnn35248 if (len <= strlen(bhp->bh_name)) 4749acbbeafSnn35248 return (-1); 4759acbbeafSnn35248 4769acbbeafSnn35248 (void) strcpy(buf, bhp->bh_name); 4779acbbeafSnn35248 4789acbbeafSnn35248 return (0); 4799acbbeafSnn35248 } 4809acbbeafSnn35248 4819acbbeafSnn35248 int 482ff17c8bfSgjelinek brand_get_clone(brand_handle_t bh, const char *zonename, 483ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 4849acbbeafSnn35248 { 485123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 486ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 487ff17c8bfSgjelinek buf, len, DTD_ELEM_CLONE, B_TRUE, B_TRUE)); 488ff17c8bfSgjelinek } 489ff17c8bfSgjelinek 490ff17c8bfSgjelinek int 491ff17c8bfSgjelinek brand_get_detach(brand_handle_t bh, const char *zonename, 492ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 493ff17c8bfSgjelinek { 494ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 495ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 496ff17c8bfSgjelinek buf, len, DTD_ELEM_DETACH, B_TRUE, B_TRUE)); 497ff17c8bfSgjelinek } 498ff17c8bfSgjelinek 499ff17c8bfSgjelinek int 500ff17c8bfSgjelinek brand_get_halt(brand_handle_t bh, const char *zonename, 501ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 502ff17c8bfSgjelinek { 503ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 504ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 505ff17c8bfSgjelinek buf, len, DTD_ELEM_HALT, B_TRUE, B_TRUE)); 5069acbbeafSnn35248 } 5079acbbeafSnn35248 5089acbbeafSnn35248 int 5093c7284bdSAlexander Eremin brand_get_shutdown(brand_handle_t bh, const char *zonename, 5103c7284bdSAlexander Eremin const char *zonepath, char *buf, size_t len) 5113c7284bdSAlexander Eremin { 5123c7284bdSAlexander Eremin struct brand_handle *bhp = (struct brand_handle *)bh; 5133c7284bdSAlexander Eremin return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5143c7284bdSAlexander Eremin buf, len, DTD_ELEM_SHUTDOWN, B_TRUE, B_TRUE)); 5153c7284bdSAlexander Eremin } 5163c7284bdSAlexander Eremin 5173c7284bdSAlexander Eremin int 518123807fbSedp brand_get_initname(brand_handle_t bh, char *buf, size_t len) 5199acbbeafSnn35248 { 520123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 5219acbbeafSnn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 522ff17c8bfSgjelinek buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE)); 5239acbbeafSnn35248 } 5249acbbeafSnn35248 525*bafd1f14SJerry Jelinek boolean_t 526*bafd1f14SJerry Jelinek brand_restartinit(brand_handle_t bh) 527*bafd1f14SJerry Jelinek { 528*bafd1f14SJerry Jelinek struct brand_handle *bhp = (struct brand_handle *)bh; 529*bafd1f14SJerry Jelinek char val[80]; 530*bafd1f14SJerry Jelinek 531*bafd1f14SJerry Jelinek if (brand_get_value(bhp, NULL, NULL, NULL, NULL, 532*bafd1f14SJerry Jelinek val, sizeof (val), DTD_ELEM_RESTARTINIT, B_FALSE, B_FALSE) != 0) 533*bafd1f14SJerry Jelinek return (B_TRUE); 534*bafd1f14SJerry Jelinek 535*bafd1f14SJerry Jelinek if (strcmp(val, "false") == 0) 536*bafd1f14SJerry Jelinek return (B_FALSE); 537*bafd1f14SJerry Jelinek return (B_TRUE); 538*bafd1f14SJerry Jelinek } 539*bafd1f14SJerry Jelinek 5409acbbeafSnn35248 int 541123807fbSedp brand_get_login_cmd(brand_handle_t bh, const char *username, 5429acbbeafSnn35248 char *buf, size_t len) 5439acbbeafSnn35248 { 544123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 5459acbbeafSnn35248 const char *curr_zone = get_curr_zone(); 5469acbbeafSnn35248 return (brand_get_value(bhp, NULL, NULL, username, curr_zone, 547ff17c8bfSgjelinek buf, len, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE)); 5489acbbeafSnn35248 } 5499acbbeafSnn35248 5509acbbeafSnn35248 int 551cb8a054bSGlenn Faden brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username, 552cb8a054bSGlenn Faden char *buf, size_t len) 553cb8a054bSGlenn Faden { 554cb8a054bSGlenn Faden struct brand_handle *bhp = (struct brand_handle *)bh; 555cb8a054bSGlenn Faden const char *curr_zone = get_curr_zone(); 556cb8a054bSGlenn Faden return (brand_get_value(bhp, NULL, NULL, username, curr_zone, 557cb8a054bSGlenn Faden buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE)); 558cb8a054bSGlenn Faden } 559cb8a054bSGlenn Faden 560cb8a054bSGlenn Faden int 561858a4b99Ssl108498 brand_get_user_cmd(brand_handle_t bh, const char *username, 562858a4b99Ssl108498 char *buf, size_t len) 563858a4b99Ssl108498 { 564858a4b99Ssl108498 struct brand_handle *bhp = (struct brand_handle *)bh; 565858a4b99Ssl108498 566858a4b99Ssl108498 return (brand_get_value(bhp, NULL, NULL, username, NULL, 567ff17c8bfSgjelinek buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE)); 568858a4b99Ssl108498 } 569858a4b99Ssl108498 570858a4b99Ssl108498 int 571123807fbSedp brand_get_install(brand_handle_t bh, const char *zonename, 572ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 5739acbbeafSnn35248 { 574123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 575ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 576ff17c8bfSgjelinek buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE)); 5779acbbeafSnn35248 } 5789acbbeafSnn35248 5799acbbeafSnn35248 int 580123807fbSedp brand_get_installopts(brand_handle_t bh, char *buf, size_t len) 5819acbbeafSnn35248 { 582123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 5839acbbeafSnn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 584ff17c8bfSgjelinek buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE)); 5859acbbeafSnn35248 } 5869acbbeafSnn35248 5879acbbeafSnn35248 int 588123807fbSedp brand_get_modname(brand_handle_t bh, char *buf, size_t len) 5899acbbeafSnn35248 { 590123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 5919acbbeafSnn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 592ff17c8bfSgjelinek buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE)); 5939acbbeafSnn35248 } 5949acbbeafSnn35248 5959acbbeafSnn35248 int 59637774979Sgjelinek brand_get_postattach(brand_handle_t bh, const char *zonename, 597ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 59837774979Sgjelinek { 59937774979Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 600ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 601ff17c8bfSgjelinek buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE)); 60237774979Sgjelinek } 60337774979Sgjelinek 60437774979Sgjelinek int 605123807fbSedp brand_get_postclone(brand_handle_t bh, const char *zonename, 606ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 6079acbbeafSnn35248 { 608123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 609ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 610ff17c8bfSgjelinek buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE)); 6119acbbeafSnn35248 } 6129acbbeafSnn35248 6139acbbeafSnn35248 int 6141100f00dSgjelinek brand_get_postinstall(brand_handle_t bh, const char *zonename, 615ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 6161100f00dSgjelinek { 6171100f00dSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 618ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 619ff17c8bfSgjelinek buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE)); 620ff17c8bfSgjelinek } 621ff17c8bfSgjelinek 622ff17c8bfSgjelinek int 623ff17c8bfSgjelinek brand_get_postsnap(brand_handle_t bh, const char *zonename, 624ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 625ff17c8bfSgjelinek { 626ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 627ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 628ff17c8bfSgjelinek buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE)); 6291100f00dSgjelinek } 6301100f00dSgjelinek 6311100f00dSgjelinek int 632c5cd6260S brand_get_poststatechange(brand_handle_t bh, const char *zonename, 633c5cd6260S const char *zonepath, char *buf, size_t len) 634c5cd6260S { 635c5cd6260S struct brand_handle *bhp = (struct brand_handle *)bh; 636c5cd6260S return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 637c5cd6260S buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE)); 638c5cd6260S } 639c5cd6260S 640c5cd6260S int 64137774979Sgjelinek brand_get_predetach(brand_handle_t bh, const char *zonename, 642ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 64337774979Sgjelinek { 64437774979Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 645ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 646ff17c8bfSgjelinek buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE)); 647ff17c8bfSgjelinek } 648ff17c8bfSgjelinek 649ff17c8bfSgjelinek int 650ff17c8bfSgjelinek brand_get_presnap(brand_handle_t bh, const char *zonename, 651ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 652ff17c8bfSgjelinek { 653ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 654ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 655ff17c8bfSgjelinek buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE)); 65637774979Sgjelinek } 65737774979Sgjelinek 65837774979Sgjelinek int 659c5cd6260S brand_get_prestatechange(brand_handle_t bh, const char *zonename, 660c5cd6260S const char *zonepath, char *buf, size_t len) 661c5cd6260S { 662c5cd6260S struct brand_handle *bhp = (struct brand_handle *)bh; 663c5cd6260S return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 664c5cd6260S buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE)); 665c5cd6260S } 666c5cd6260S 667c5cd6260S int 66837774979Sgjelinek brand_get_preuninstall(brand_handle_t bh, const char *zonename, 669ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 67037774979Sgjelinek { 67137774979Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 672ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 673ff17c8bfSgjelinek buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE)); 674ff17c8bfSgjelinek } 675ff17c8bfSgjelinek 676ff17c8bfSgjelinek int 677c5cd6260S brand_get_query(brand_handle_t bh, const char *zonename, 678c5cd6260S const char *zonepath, char *buf, size_t len) 679c5cd6260S { 680c5cd6260S struct brand_handle *bhp = (struct brand_handle *)bh; 681c5cd6260S return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 682c5cd6260S buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE)); 683c5cd6260S } 684c5cd6260S 685c5cd6260S int 686ff17c8bfSgjelinek brand_get_uninstall(brand_handle_t bh, const char *zonename, 687ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 688ff17c8bfSgjelinek { 689ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 690ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 691ff17c8bfSgjelinek buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE)); 692ff17c8bfSgjelinek } 693ff17c8bfSgjelinek 694ff17c8bfSgjelinek int 695ff17c8bfSgjelinek brand_get_validatesnap(brand_handle_t bh, const char *zonename, 696ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 697ff17c8bfSgjelinek { 698ff17c8bfSgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 699ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 700ff17c8bfSgjelinek buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE)); 70137774979Sgjelinek } 70237774979Sgjelinek 70337774979Sgjelinek int 704123807fbSedp brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len) 7059acbbeafSnn35248 { 706123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 7079acbbeafSnn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 708ff17c8bfSgjelinek buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE)); 7099acbbeafSnn35248 } 7109acbbeafSnn35248 7119acbbeafSnn35248 int 712123807fbSedp brand_get_verify_adm(brand_handle_t bh, const char *zonename, 713ff17c8bfSgjelinek const char *zonepath, char *buf, size_t len) 7149acbbeafSnn35248 { 715123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 716ff17c8bfSgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 717ff17c8bfSgjelinek buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE)); 7189acbbeafSnn35248 } 7199acbbeafSnn35248 7209acbbeafSnn35248 int 721fbbfbc6eSjv227347 brand_get_sysboot(brand_handle_t bh, const char *zonename, 722fbbfbc6eSjv227347 const char *zonepath, char *buf, size_t len) 723fbbfbc6eSjv227347 { 724fbbfbc6eSjv227347 struct brand_handle *bhp = (struct brand_handle *)bh; 725fbbfbc6eSjv227347 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 726fbbfbc6eSjv227347 buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE)); 727fbbfbc6eSjv227347 } 728fbbfbc6eSjv227347 729f4b3ec61Sdh155122 boolean_t 730f4b3ec61Sdh155122 brand_allow_exclusive_ip(brand_handle_t bh) 731f4b3ec61Sdh155122 { 732f4b3ec61Sdh155122 struct brand_handle *bhp = (struct brand_handle *)bh; 733f4b3ec61Sdh155122 xmlNodePtr node; 734f4b3ec61Sdh155122 xmlChar *allow_excl; 735f4b3ec61Sdh155122 boolean_t ret; 736f4b3ec61Sdh155122 737f4b3ec61Sdh155122 assert(bhp != NULL); 738f4b3ec61Sdh155122 739f4b3ec61Sdh155122 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 740f4b3ec61Sdh155122 return (B_FALSE); 741f4b3ec61Sdh155122 742f4b3ec61Sdh155122 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL); 743f4b3ec61Sdh155122 if (allow_excl == NULL) 744f4b3ec61Sdh155122 return (B_FALSE); 745f4b3ec61Sdh155122 746f4b3ec61Sdh155122 /* Note: only return B_TRUE if it's "true" */ 747f4b3ec61Sdh155122 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0) 748f4b3ec61Sdh155122 ret = B_TRUE; 749f4b3ec61Sdh155122 else 750f4b3ec61Sdh155122 ret = B_FALSE; 751f4b3ec61Sdh155122 752f4b3ec61Sdh155122 xmlFree(allow_excl); 753f4b3ec61Sdh155122 754f4b3ec61Sdh155122 return (ret); 755f4b3ec61Sdh155122 } 756f4b3ec61Sdh155122 7579acbbeafSnn35248 /* 7589acbbeafSnn35248 * Iterate over brand privileges 7599acbbeafSnn35248 * 7609acbbeafSnn35248 * Walks the brand config, searching for <privilege> elements, calling the 7619acbbeafSnn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 7629acbbeafSnn35248 */ 7639acbbeafSnn35248 int 764bf1d7e28Sdh155122 brand_config_iter_privilege(brand_handle_t bh, 765bf1d7e28Sdh155122 int (*func)(void *, priv_iter_t *), void *data) 7669acbbeafSnn35248 { 767123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 7689acbbeafSnn35248 xmlNodePtr node; 769bf1d7e28Sdh155122 xmlChar *name, *set, *iptype; 770bf1d7e28Sdh155122 priv_iter_t priv_iter; 7719acbbeafSnn35248 int ret; 7729acbbeafSnn35248 7739acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 7749acbbeafSnn35248 return (-1); 7759acbbeafSnn35248 7769acbbeafSnn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 7779acbbeafSnn35248 7789acbbeafSnn35248 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0) 7799acbbeafSnn35248 continue; 7809acbbeafSnn35248 7819acbbeafSnn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 7829acbbeafSnn35248 set = xmlGetProp(node, DTD_ATTR_SET); 783bf1d7e28Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 7849acbbeafSnn35248 785bf1d7e28Sdh155122 if (name == NULL || set == NULL || iptype == NULL) { 7869acbbeafSnn35248 if (name != NULL) 7879acbbeafSnn35248 xmlFree(name); 7889acbbeafSnn35248 if (set != NULL) 7899acbbeafSnn35248 xmlFree(set); 790bf1d7e28Sdh155122 if (iptype != NULL) 791bf1d7e28Sdh155122 xmlFree(iptype); 7929acbbeafSnn35248 return (-1); 7939acbbeafSnn35248 } 7949acbbeafSnn35248 795bf1d7e28Sdh155122 priv_iter.pi_name = (char *)name; 796bf1d7e28Sdh155122 priv_iter.pi_set = (char *)set; 797bf1d7e28Sdh155122 priv_iter.pi_iptype = (char *)iptype; 798bf1d7e28Sdh155122 799bf1d7e28Sdh155122 ret = func(data, &priv_iter); 8009acbbeafSnn35248 8019acbbeafSnn35248 xmlFree(name); 8029acbbeafSnn35248 xmlFree(set); 803bf1d7e28Sdh155122 xmlFree(iptype); 8049acbbeafSnn35248 8059acbbeafSnn35248 if (ret != 0) 8069acbbeafSnn35248 return (-1); 8079acbbeafSnn35248 } 8089acbbeafSnn35248 8099acbbeafSnn35248 return (0); 8109acbbeafSnn35248 } 8119acbbeafSnn35248 8129acbbeafSnn35248 static int 813ff17c8bfSgjelinek i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonepath, 8149acbbeafSnn35248 int (*func)(void *, const char *, const char *, const char *, 8159acbbeafSnn35248 const char *), void *data, const xmlChar *mount_type) 8169acbbeafSnn35248 { 8179acbbeafSnn35248 xmlNodePtr node; 8189acbbeafSnn35248 xmlChar *special, *dir, *type, *opt; 8199acbbeafSnn35248 char special_exp[MAXPATHLEN]; 8209acbbeafSnn35248 char opt_exp[MAXPATHLEN]; 8219acbbeafSnn35248 int ret; 8229acbbeafSnn35248 8239acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 8249acbbeafSnn35248 return (-1); 8259acbbeafSnn35248 8269acbbeafSnn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 8279acbbeafSnn35248 8289acbbeafSnn35248 if (xmlStrcmp(node->name, mount_type) != 0) 8299acbbeafSnn35248 continue; 8309acbbeafSnn35248 8319acbbeafSnn35248 special = xmlGetProp(node, DTD_ATTR_SPECIAL); 8329acbbeafSnn35248 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY); 8339acbbeafSnn35248 type = xmlGetProp(node, DTD_ATTR_TYPE); 8349acbbeafSnn35248 opt = xmlGetProp(node, DTD_ATTR_OPT); 8359acbbeafSnn35248 if ((special == NULL) || (dir == NULL) || (type == NULL) || 8369acbbeafSnn35248 (opt == NULL)) { 8379acbbeafSnn35248 ret = -1; 8389acbbeafSnn35248 goto next; 8399acbbeafSnn35248 } 8409acbbeafSnn35248 8419acbbeafSnn35248 /* Substitute token values as needed. */ 8429acbbeafSnn35248 if ((ret = i_substitute_tokens((char *)special, 8439acbbeafSnn35248 special_exp, sizeof (special_exp), 844ff17c8bfSgjelinek NULL, zonepath, NULL, NULL)) != 0) 8459acbbeafSnn35248 goto next; 8469acbbeafSnn35248 8479acbbeafSnn35248 /* opt might not be defined */ 8489acbbeafSnn35248 if (strlen((const char *)opt) == 0) { 8499acbbeafSnn35248 xmlFree(opt); 8509acbbeafSnn35248 opt = NULL; 8519acbbeafSnn35248 } else { 8529acbbeafSnn35248 if ((ret = i_substitute_tokens((char *)opt, 8539acbbeafSnn35248 opt_exp, sizeof (opt_exp), 854ff17c8bfSgjelinek NULL, zonepath, NULL, NULL)) != 0) 8559acbbeafSnn35248 goto next; 8569acbbeafSnn35248 } 8579acbbeafSnn35248 8589acbbeafSnn35248 ret = func(data, (char *)special_exp, (char *)dir, 8599acbbeafSnn35248 (char *)type, ((opt != NULL) ? opt_exp : NULL)); 8609acbbeafSnn35248 8619acbbeafSnn35248 next: 8629acbbeafSnn35248 if (special != NULL) 8639acbbeafSnn35248 xmlFree(special); 8649acbbeafSnn35248 if (dir != NULL) 8659acbbeafSnn35248 xmlFree(dir); 8669acbbeafSnn35248 if (type != NULL) 8679acbbeafSnn35248 xmlFree(type); 8689acbbeafSnn35248 if (opt != NULL) 8699acbbeafSnn35248 xmlFree(opt); 8709acbbeafSnn35248 if (ret != 0) 8719acbbeafSnn35248 return (-1); 8729acbbeafSnn35248 } 8739acbbeafSnn35248 return (0); 8749acbbeafSnn35248 } 8759acbbeafSnn35248 8769acbbeafSnn35248 8779acbbeafSnn35248 /* 8789acbbeafSnn35248 * Iterate over global platform filesystems 8799acbbeafSnn35248 * 8809acbbeafSnn35248 * Walks the platform, searching for <global_mount> elements, calling the 8819acbbeafSnn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 8829acbbeafSnn35248 * 8839acbbeafSnn35248 * Perform the following substitutions as necessary: 8849acbbeafSnn35248 * 885ff17c8bfSgjelinek * %R Zonepath of zone 8869acbbeafSnn35248 */ 8879acbbeafSnn35248 int 888ff17c8bfSgjelinek brand_platform_iter_gmounts(brand_handle_t bh, const char *zonepath, 8899acbbeafSnn35248 int (*func)(void *, const char *, const char *, const char *, 8909acbbeafSnn35248 const char *), void *data) 8919acbbeafSnn35248 { 892123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 893ff17c8bfSgjelinek return (i_brand_platform_iter_mounts(bhp, zonepath, func, data, 8949acbbeafSnn35248 DTD_ELEM_GLOBAL_MOUNT)); 8959acbbeafSnn35248 } 8969acbbeafSnn35248 8979acbbeafSnn35248 /* 8989acbbeafSnn35248 * Iterate over non-global zone platform filesystems 8999acbbeafSnn35248 * 9009acbbeafSnn35248 * Walks the platform, searching for <mount> elements, calling the 9019acbbeafSnn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 9029acbbeafSnn35248 */ 9039acbbeafSnn35248 int 904123807fbSedp brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *, 9059acbbeafSnn35248 const char *, const char *, const char *, const char *), void *data) 9069acbbeafSnn35248 { 907123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 9089acbbeafSnn35248 return (i_brand_platform_iter_mounts(bhp, NULL, func, data, 9099acbbeafSnn35248 DTD_ELEM_MOUNT)); 9109acbbeafSnn35248 } 9119acbbeafSnn35248 9129acbbeafSnn35248 /* 9139acbbeafSnn35248 * Iterate over platform symlinks 9149acbbeafSnn35248 * 9159acbbeafSnn35248 * Walks the platform, searching for <symlink> elements, calling the 9169acbbeafSnn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 9179acbbeafSnn35248 */ 9189acbbeafSnn35248 int 919123807fbSedp brand_platform_iter_link(brand_handle_t bh, 9209acbbeafSnn35248 int (*func)(void *, const char *, const char *), void *data) 9219acbbeafSnn35248 { 922123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 9239acbbeafSnn35248 xmlNodePtr node; 9249acbbeafSnn35248 xmlChar *source, *target; 9259acbbeafSnn35248 int ret; 9269acbbeafSnn35248 9279acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 9289acbbeafSnn35248 return (-1); 9299acbbeafSnn35248 9309acbbeafSnn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 9319acbbeafSnn35248 9329acbbeafSnn35248 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0) 9339acbbeafSnn35248 continue; 9349acbbeafSnn35248 9359acbbeafSnn35248 source = xmlGetProp(node, DTD_ATTR_SOURCE); 9369acbbeafSnn35248 target = xmlGetProp(node, DTD_ATTR_TARGET); 9379acbbeafSnn35248 9389acbbeafSnn35248 if (source == NULL || target == NULL) { 9399acbbeafSnn35248 if (source != NULL) 9409acbbeafSnn35248 xmlFree(source); 9419acbbeafSnn35248 if (target != NULL) 9429acbbeafSnn35248 xmlFree(target); 9439acbbeafSnn35248 return (-1); 9449acbbeafSnn35248 } 9459acbbeafSnn35248 9469acbbeafSnn35248 ret = func(data, (char *)source, (char *)target); 9479acbbeafSnn35248 9489acbbeafSnn35248 xmlFree(source); 9499acbbeafSnn35248 xmlFree(target); 9509acbbeafSnn35248 9519acbbeafSnn35248 if (ret != 0) 9529acbbeafSnn35248 return (-1); 9539acbbeafSnn35248 } 9549acbbeafSnn35248 9559acbbeafSnn35248 return (0); 9569acbbeafSnn35248 } 9579acbbeafSnn35248 9589acbbeafSnn35248 /* 9599acbbeafSnn35248 * Iterate over platform devices 9609acbbeafSnn35248 * 9619acbbeafSnn35248 * Walks the platform, searching for <device> elements, calling the 9629acbbeafSnn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 9639acbbeafSnn35248 */ 9649acbbeafSnn35248 int 965123807fbSedp brand_platform_iter_devices(brand_handle_t bh, const char *zonename, 966f4b3ec61Sdh155122 int (*func)(void *, const char *, const char *), void *data, 967f4b3ec61Sdh155122 const char *curr_iptype) 9689acbbeafSnn35248 { 969123807fbSedp struct brand_handle *bhp = (struct brand_handle *)bh; 9709acbbeafSnn35248 const char *curr_arch = get_curr_arch(); 9719acbbeafSnn35248 xmlNodePtr node; 972f4b3ec61Sdh155122 xmlChar *match, *name, *arch, *iptype; 9739acbbeafSnn35248 char match_exp[MAXPATHLEN]; 9749acbbeafSnn35248 boolean_t err = B_FALSE; 9759acbbeafSnn35248 int ret = 0; 9769acbbeafSnn35248 9779acbbeafSnn35248 9789acbbeafSnn35248 assert(bhp != NULL); 9799acbbeafSnn35248 assert(zonename != NULL); 9809acbbeafSnn35248 assert(func != NULL); 981f4b3ec61Sdh155122 assert(curr_iptype != NULL); 9829acbbeafSnn35248 9839acbbeafSnn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 9849acbbeafSnn35248 return (-1); 9859acbbeafSnn35248 9869acbbeafSnn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 9879acbbeafSnn35248 9889acbbeafSnn35248 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0) 9899acbbeafSnn35248 continue; 9909acbbeafSnn35248 9919acbbeafSnn35248 match = xmlGetProp(node, DTD_ATTR_MATCH); 9929acbbeafSnn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 9939acbbeafSnn35248 arch = xmlGetProp(node, DTD_ATTR_ARCH); 994f4b3ec61Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 995f4b3ec61Sdh155122 if ((match == NULL) || (name == NULL) || (arch == NULL) || 996f4b3ec61Sdh155122 (iptype == NULL)) { 9979acbbeafSnn35248 err = B_TRUE; 9989acbbeafSnn35248 goto next; 9999acbbeafSnn35248 } 10009acbbeafSnn35248 10019acbbeafSnn35248 /* check if the arch matches */ 10029acbbeafSnn35248 if ((strcmp((char *)arch, "all") != 0) && 10039acbbeafSnn35248 (strcmp((char *)arch, curr_arch) != 0)) 10049acbbeafSnn35248 goto next; 10059acbbeafSnn35248 1006f4b3ec61Sdh155122 /* check if the iptype matches */ 1007f4b3ec61Sdh155122 if ((strcmp((char *)iptype, "all") != 0) && 1008f4b3ec61Sdh155122 (strcmp((char *)iptype, curr_iptype) != 0)) 1009f4b3ec61Sdh155122 goto next; 1010f4b3ec61Sdh155122 10119acbbeafSnn35248 /* Substitute token values as needed. */ 10129acbbeafSnn35248 if ((ret = i_substitute_tokens((char *)match, 10139acbbeafSnn35248 match_exp, sizeof (match_exp), 1014ff17c8bfSgjelinek zonename, NULL, NULL, NULL)) != 0) { 10159acbbeafSnn35248 err = B_TRUE; 10169acbbeafSnn35248 goto next; 10179acbbeafSnn35248 } 10189acbbeafSnn35248 10199acbbeafSnn35248 /* name might not be defined */ 10209acbbeafSnn35248 if (strlen((const char *)name) == 0) { 10219acbbeafSnn35248 xmlFree(name); 10229acbbeafSnn35248 name = NULL; 10239acbbeafSnn35248 } 10249acbbeafSnn35248 10259acbbeafSnn35248 /* invoke the callback */ 10269acbbeafSnn35248 ret = func(data, (const char *)match_exp, (const char *)name); 10279acbbeafSnn35248 10289acbbeafSnn35248 next: 10299acbbeafSnn35248 if (match != NULL) 10309acbbeafSnn35248 xmlFree(match); 10319acbbeafSnn35248 if (name != NULL) 10329acbbeafSnn35248 xmlFree(name); 10339acbbeafSnn35248 if (arch != NULL) 10349acbbeafSnn35248 xmlFree(arch); 1035f4b3ec61Sdh155122 if (iptype != NULL) 1036f4b3ec61Sdh155122 xmlFree(iptype); 10379acbbeafSnn35248 if (err) 10389acbbeafSnn35248 return (-1); 10399acbbeafSnn35248 if (ret != 0) 10409acbbeafSnn35248 return (-1); 10419acbbeafSnn35248 } 10429acbbeafSnn35248 10439acbbeafSnn35248 return (0); 10449acbbeafSnn35248 } 1045