12712Snn35248 /* 22712Snn35248 * CDDL HEADER START 32712Snn35248 * 42712Snn35248 * The contents of this file are subject to the terms of the 52712Snn35248 * Common Development and Distribution License (the "License"). 62712Snn35248 * You may not use this file except in compliance with the License. 72712Snn35248 * 82712Snn35248 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92712Snn35248 * or http://www.opensolaris.org/os/licensing. 102712Snn35248 * See the License for the specific language governing permissions 112712Snn35248 * and limitations under the License. 122712Snn35248 * 132712Snn35248 * When distributing Covered Code, include this CDDL HEADER in each 142712Snn35248 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152712Snn35248 * If applicable, add the following below this CDDL HEADER, with the 162712Snn35248 * fields enclosed by brackets "[]" replaced with your own identifying 172712Snn35248 * information: Portions Copyright [yyyy] [name of copyright owner] 182712Snn35248 * 192712Snn35248 * CDDL HEADER END 202712Snn35248 */ 212712Snn35248 222712Snn35248 /* 233448Sdh155122 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 242712Snn35248 * Use is subject to license terms. 252712Snn35248 */ 262712Snn35248 272712Snn35248 #pragma ident "%Z%%M% %I% %E% SMI" 282712Snn35248 292712Snn35248 #include <assert.h> 302712Snn35248 #include <dirent.h> 312712Snn35248 #include <errno.h> 322712Snn35248 #include <fnmatch.h> 332712Snn35248 #include <signal.h> 342712Snn35248 #include <stdlib.h> 352712Snn35248 #include <unistd.h> 362712Snn35248 #include <strings.h> 372712Snn35248 #include <synch.h> 382712Snn35248 #include <sys/brand.h> 392712Snn35248 #include <sys/fcntl.h> 402712Snn35248 #include <sys/param.h> 412712Snn35248 #include <sys/stat.h> 422712Snn35248 #include <sys/systeminfo.h> 432712Snn35248 #include <sys/types.h> 442712Snn35248 #include <thread.h> 452712Snn35248 #include <zone.h> 462712Snn35248 472712Snn35248 #include <libbrand_impl.h> 482712Snn35248 #include <libbrand.h> 492712Snn35248 502712Snn35248 #define DTD_ELEM_BOOT ((const xmlChar *) "boot") 512712Snn35248 #define DTD_ELEM_BRAND ((const xmlChar *) "brand") 522712Snn35248 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment") 532712Snn35248 #define DTD_ELEM_DEVICE ((const xmlChar *) "device") 542712Snn35248 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount") 552712Snn35248 #define DTD_ELEM_HALT ((const xmlChar *) "halt") 562712Snn35248 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname") 572712Snn35248 #define DTD_ELEM_INSTALL ((const xmlChar *) "install") 582712Snn35248 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts") 592712Snn35248 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd") 602712Snn35248 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname") 612712Snn35248 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount") 622712Snn35248 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone") 63*4586Sgjelinek #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall") 642712Snn35248 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege") 652712Snn35248 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink") 664344Ssl108498 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd") 672712Snn35248 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg") 682712Snn35248 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm") 692712Snn35248 703448Sdh155122 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip") 712712Snn35248 #define DTD_ATTR_ARCH ((const xmlChar *) "arch") 722712Snn35248 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory") 733448Sdh155122 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type") 742712Snn35248 #define DTD_ATTR_MATCH ((const xmlChar *) "match") 752712Snn35248 #define DTD_ATTR_MODE ((const xmlChar *) "mode") 762712Snn35248 #define DTD_ATTR_NAME ((const xmlChar *) "name") 772712Snn35248 #define DTD_ATTR_OPT ((const xmlChar *) "opt") 782712Snn35248 #define DTD_ATTR_PATH ((const xmlChar *) "path") 792712Snn35248 #define DTD_ATTR_SET ((const xmlChar *) "set") 802712Snn35248 #define DTD_ATTR_SOURCE ((const xmlChar *) "source") 812712Snn35248 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special") 822712Snn35248 #define DTD_ATTR_TARGET ((const xmlChar *) "target") 832712Snn35248 #define DTD_ATTR_TYPE ((const xmlChar *) "type") 842712Snn35248 853448Sdh155122 #define DTD_ENTITY_TRUE "true" 863448Sdh155122 872712Snn35248 static volatile boolean_t libbrand_initialized = B_FALSE; 882712Snn35248 static char i_curr_arch[MAXNAMELEN]; 892712Snn35248 static char i_curr_zone[ZONENAME_MAX]; 902712Snn35248 912712Snn35248 /*ARGSUSED*/ 922712Snn35248 static void 932712Snn35248 brand_error_func(void *ctx, const char *msg, ...) 942712Snn35248 { 952712Snn35248 /* 962712Snn35248 * Ignore error messages from libxml 972712Snn35248 */ 982712Snn35248 } 992712Snn35248 1002712Snn35248 static boolean_t 1012712Snn35248 libbrand_initialize() 1022712Snn35248 { 1032712Snn35248 static mutex_t initialize_lock = DEFAULTMUTEX; 1042712Snn35248 1052712Snn35248 (void) mutex_lock(&initialize_lock); 1062712Snn35248 1072712Snn35248 if (libbrand_initialized) { 1082712Snn35248 (void) mutex_unlock(&initialize_lock); 1092712Snn35248 return (B_TRUE); 1102712Snn35248 } 1112712Snn35248 1122712Snn35248 if (sysinfo(SI_ARCHITECTURE, i_curr_arch, sizeof (i_curr_arch)) < 0) { 1132712Snn35248 (void) mutex_unlock(&initialize_lock); 1142712Snn35248 return (B_FALSE); 1152712Snn35248 } 1162712Snn35248 1172712Snn35248 if (getzonenamebyid(getzoneid(), i_curr_zone, 1182712Snn35248 sizeof (i_curr_zone)) < 0) { 1192712Snn35248 (void) mutex_unlock(&initialize_lock); 1202712Snn35248 return (B_FALSE); 1212712Snn35248 } 1222712Snn35248 1232712Snn35248 /* 1242712Snn35248 * Note that here we're initializing per-process libxml2 1252712Snn35248 * state. By doing so we're implicitly assuming that 1262712Snn35248 * no other code in this process is also trying to 1272712Snn35248 * use libxml2. But in most case we know this not to 1282712Snn35248 * be true since we're almost always used in conjunction 1292712Snn35248 * with libzonecfg, which also uses libxml2. Lucky for 1302712Snn35248 * us, libzonecfg initializes libxml2 to essentially 1312712Snn35248 * the same defaults as we're using below. 1322712Snn35248 */ 1332712Snn35248 xmlLineNumbersDefault(1); 1342712Snn35248 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 1352712Snn35248 xmlDoValidityCheckingDefaultValue = 1; 1362712Snn35248 (void) xmlKeepBlanksDefault(0); 1372712Snn35248 xmlGetWarningsDefaultValue = 0; 1382712Snn35248 xmlSetGenericErrorFunc(NULL, brand_error_func); 1392712Snn35248 1402712Snn35248 libbrand_initialized = B_TRUE; 1412712Snn35248 (void) mutex_unlock(&initialize_lock); 1422712Snn35248 return (B_TRUE); 1432712Snn35248 } 1442712Snn35248 1452712Snn35248 static const char * 1462712Snn35248 get_curr_arch(void) 1472712Snn35248 { 1482712Snn35248 if (!libbrand_initialize()) 1492712Snn35248 return (NULL); 1502712Snn35248 1512712Snn35248 return (i_curr_arch); 1522712Snn35248 } 1532712Snn35248 1542712Snn35248 static const char * 1552712Snn35248 get_curr_zone(void) 1562712Snn35248 { 1572712Snn35248 if (!libbrand_initialize()) 1582712Snn35248 return (NULL); 1592712Snn35248 1602712Snn35248 return (i_curr_zone); 1612712Snn35248 } 1622712Snn35248 1632712Snn35248 /* 1642712Snn35248 * Internal function to open an XML file 1652712Snn35248 * 1662712Snn35248 * Returns the XML doc pointer, or NULL on failure. It will validate the 1672712Snn35248 * document, as well as removing any comments from the document structure. 1682712Snn35248 */ 1692712Snn35248 static xmlDocPtr 1702712Snn35248 open_xml_file(const char *file) 1712712Snn35248 { 1722712Snn35248 xmlDocPtr doc; 1732712Snn35248 xmlValidCtxtPtr cvp; 1742712Snn35248 int valid; 1752712Snn35248 1762712Snn35248 if (!libbrand_initialize()) 1772712Snn35248 return (NULL); 1782712Snn35248 1792712Snn35248 /* 1802712Snn35248 * Parse the file 1812712Snn35248 */ 1822712Snn35248 if ((doc = xmlParseFile(file)) == NULL) 1832712Snn35248 return (NULL); 1842712Snn35248 1852712Snn35248 /* 1862712Snn35248 * Validate the file 1872712Snn35248 */ 1882712Snn35248 if ((cvp = xmlNewValidCtxt()) == NULL) { 1892712Snn35248 xmlFreeDoc(doc); 1902712Snn35248 return (NULL); 1912712Snn35248 } 1922712Snn35248 cvp->error = brand_error_func; 1932712Snn35248 cvp->warning = brand_error_func; 1942712Snn35248 valid = xmlValidateDocument(cvp, doc); 1952712Snn35248 xmlFreeValidCtxt(cvp); 1962712Snn35248 if (valid == 0) { 1972712Snn35248 xmlFreeDoc(doc); 1982712Snn35248 return (NULL); 1992712Snn35248 } 2002712Snn35248 2012712Snn35248 return (doc); 2022712Snn35248 } 2032712Snn35248 /* 2042712Snn35248 * Open a handle to the named brand. 2052712Snn35248 * 2062712Snn35248 * Returns a handle to the named brand, which is used for all subsequent brand 2072712Snn35248 * interaction, or NULL if unable to open or initialize the brand. 2082712Snn35248 */ 2092727Sedp brand_handle_t 2102712Snn35248 brand_open(const char *name) 2112712Snn35248 { 2122727Sedp struct brand_handle *bhp; 2132712Snn35248 char path[MAXPATHLEN]; 2142712Snn35248 xmlNodePtr node; 2152712Snn35248 xmlChar *property; 2162712Snn35248 struct stat statbuf; 2172712Snn35248 2182712Snn35248 /* 2192712Snn35248 * Make sure brand name isn't too long 2202712Snn35248 */ 2212712Snn35248 if (strlen(name) >= MAXNAMELEN) 2222712Snn35248 return (NULL); 2232712Snn35248 2242712Snn35248 /* 2252712Snn35248 * Check that the brand exists 2262712Snn35248 */ 2272712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s", BRAND_DIR, name); 2282712Snn35248 2292712Snn35248 if (stat(path, &statbuf) != 0) 2302712Snn35248 return (NULL); 2312712Snn35248 2322712Snn35248 /* 2332712Snn35248 * Allocate brand handle 2342712Snn35248 */ 2352727Sedp if ((bhp = malloc(sizeof (struct brand_handle))) == NULL) 2362712Snn35248 return (NULL); 2372727Sedp bzero(bhp, sizeof (struct brand_handle)); 2382712Snn35248 2392712Snn35248 (void) strcpy(bhp->bh_name, name); 2402712Snn35248 2412712Snn35248 /* 2422712Snn35248 * Open the configuration file 2432712Snn35248 */ 2442712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2452712Snn35248 BRAND_CONFIG); 2462712Snn35248 if ((bhp->bh_config = open_xml_file(path)) == NULL) { 2472727Sedp brand_close((brand_handle_t)bhp); 2482712Snn35248 return (NULL); 2492712Snn35248 } 2502712Snn35248 2512712Snn35248 /* 2522712Snn35248 * Verify that the name of the brand matches the directory in which it 2532712Snn35248 * is installed. 2542712Snn35248 */ 2552712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) { 2562727Sedp brand_close((brand_handle_t)bhp); 2572712Snn35248 return (NULL); 2582712Snn35248 } 2592712Snn35248 2602712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) { 2612727Sedp brand_close((brand_handle_t)bhp); 2622712Snn35248 return (NULL); 2632712Snn35248 } 2642712Snn35248 2652712Snn35248 if ((property = xmlGetProp(node, DTD_ATTR_NAME)) == NULL) { 2662727Sedp brand_close((brand_handle_t)bhp); 2672712Snn35248 return (NULL); 2682712Snn35248 } 2692712Snn35248 2702712Snn35248 if (strcmp((char *)property, name) != 0) { 2712712Snn35248 xmlFree(property); 2722727Sedp brand_close((brand_handle_t)bhp); 2732712Snn35248 return (NULL); 2742712Snn35248 } 2752712Snn35248 xmlFree(property); 2762712Snn35248 2772712Snn35248 /* 2782712Snn35248 * Open handle to platform configuration file. 2792712Snn35248 */ 2802712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2812712Snn35248 BRAND_PLATFORM); 2822712Snn35248 if ((bhp->bh_platform = open_xml_file(path)) == NULL) { 2832727Sedp brand_close((brand_handle_t)bhp); 2842712Snn35248 return (NULL); 2852712Snn35248 } 2862712Snn35248 2872727Sedp return ((brand_handle_t)bhp); 2882712Snn35248 } 2892712Snn35248 2902712Snn35248 /* 2912712Snn35248 * Closes the given brand handle 2922712Snn35248 */ 2932712Snn35248 void 2942727Sedp brand_close(brand_handle_t bh) 2952712Snn35248 { 2962727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 2972712Snn35248 if (bhp->bh_platform != NULL) 2982712Snn35248 xmlFreeDoc(bhp->bh_platform); 2992712Snn35248 if (bhp->bh_config != NULL) 3002712Snn35248 xmlFreeDoc(bhp->bh_config); 3012712Snn35248 free(bhp); 3022712Snn35248 } 3032712Snn35248 3042712Snn35248 static int 3052712Snn35248 i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size, 3062712Snn35248 const char *zonename, const char *zoneroot, const char *username, 3072712Snn35248 const char *curr_zone, int argc, char **argv) 3082712Snn35248 { 3092712Snn35248 int dst, src, i; 3102712Snn35248 3112712Snn35248 assert(argc >= 0); 3122712Snn35248 assert((argc == 0) || (argv != NULL)); 3132712Snn35248 3142712Snn35248 /* 3152712Snn35248 * Walk through the characters, substituting values as needed. 3162712Snn35248 */ 3172712Snn35248 dbuf[0] = '\0'; 3182712Snn35248 dst = 0; 3192712Snn35248 for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) { 3202712Snn35248 if (sbuf[src] != '%') { 3212712Snn35248 dbuf[dst++] = sbuf[src]; 3222712Snn35248 continue; 3232712Snn35248 } 3242712Snn35248 3252712Snn35248 switch (sbuf[++src]) { 3262712Snn35248 case '%': 3272712Snn35248 dst += strlcpy(dbuf + dst, "%", dbuf_size - dst); 3282712Snn35248 break; 3292712Snn35248 case 'R': 3302712Snn35248 if (zoneroot == NULL) 3312712Snn35248 break; 3322712Snn35248 dst += strlcpy(dbuf + dst, zoneroot, dbuf_size - dst); 3332712Snn35248 break; 3342712Snn35248 case 'u': 3352712Snn35248 if (username == NULL) 3362712Snn35248 break; 3372712Snn35248 dst += strlcpy(dbuf + dst, username, dbuf_size - dst); 3382712Snn35248 break; 3392712Snn35248 case 'Z': 3402712Snn35248 if (curr_zone == NULL) 3412712Snn35248 break; 3422712Snn35248 /* name of the zone we're running in */ 3432712Snn35248 dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst); 3442712Snn35248 break; 3452712Snn35248 case 'z': 3462712Snn35248 /* name of the zone we're operating on */ 3472712Snn35248 if (zonename == NULL) 3482712Snn35248 break; 3492712Snn35248 dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst); 3502712Snn35248 break; 3512712Snn35248 case '*': 3522712Snn35248 if (argv == NULL) 3532712Snn35248 break; 3542712Snn35248 for (i = 0; i < argc; i++) 3552712Snn35248 dst += snprintf(dbuf + dst, dbuf_size - dst, 3562712Snn35248 " \"%s\"", argv[i]); 3572712Snn35248 break; 3582712Snn35248 } 3592712Snn35248 } 3602712Snn35248 3612712Snn35248 if (dst >= dbuf_size) 3622712Snn35248 return (-1); 3632712Snn35248 3642712Snn35248 dbuf[dst] = '\0'; 3652712Snn35248 return (0); 3662712Snn35248 } 3672712Snn35248 3682712Snn35248 /* 3692712Snn35248 * Retrieve the given tag from the brand. 3702712Snn35248 * Perform the following substitutions as necessary: 3712712Snn35248 * 3722712Snn35248 * %% % 3732712Snn35248 * %u Username 3742712Snn35248 * %z Name of target zone 3752712Snn35248 * %Z Name of current zone 3762712Snn35248 * %R Root of zone 3772712Snn35248 * %* Additional arguments (argc, argv) 3782712Snn35248 * 3792712Snn35248 * Returns 0 on success, -1 on failure. 3802712Snn35248 */ 3812712Snn35248 static int 3822727Sedp brand_get_value(struct brand_handle *bhp, const char *zonename, 3832712Snn35248 const char *zoneroot, const char *username, const char *curr_zone, 3842712Snn35248 char *buf, size_t len, int argc, char **argv, const xmlChar *tagname, 3852712Snn35248 boolean_t substitute, boolean_t optional) 3862712Snn35248 { 3872712Snn35248 xmlNodePtr node; 3882712Snn35248 xmlChar *content; 3892712Snn35248 int err = 0; 3902712Snn35248 3912712Snn35248 /* 3922712Snn35248 * Retrieve the specified value from the XML doc 3932712Snn35248 */ 3942712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 3952712Snn35248 return (-1); 3962712Snn35248 3972712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) 3982712Snn35248 return (-1); 3992712Snn35248 4002712Snn35248 for (node = node->xmlChildrenNode; node != NULL; 4012712Snn35248 node = node->next) { 4022712Snn35248 if (xmlStrcmp(node->name, tagname) == 0) 4032712Snn35248 break; 4042712Snn35248 } 4052712Snn35248 4062712Snn35248 if (node == NULL) 4072712Snn35248 return (-1); 4082712Snn35248 4092712Snn35248 if ((content = xmlNodeGetContent(node)) == NULL) 4102712Snn35248 return (-1); 4112712Snn35248 4122712Snn35248 if (strlen((char *)content) == 0) { 4132712Snn35248 /* 4142712Snn35248 * If the entry in the config file is empty, check to see 4152712Snn35248 * whether this is an optional field. If so, we return the 4162712Snn35248 * empty buffer. If not, we return an error. 4172712Snn35248 */ 4182712Snn35248 if (optional) { 4192712Snn35248 buf[0] = '\0'; 4202712Snn35248 } else { 4212712Snn35248 err = -1; 4222712Snn35248 } 4232712Snn35248 } else { 4242712Snn35248 /* Substitute token values as needed. */ 4252712Snn35248 if (substitute) { 4262712Snn35248 if (i_substitute_tokens((char *)content, buf, len, 4272712Snn35248 zonename, zoneroot, username, curr_zone, 4282712Snn35248 argc, argv) != 0) 4292712Snn35248 err = -1; 4302712Snn35248 } else { 4312712Snn35248 if (strlcpy(buf, (char *)content, len) >= len) 4322712Snn35248 err = -1; 4332712Snn35248 } 4342712Snn35248 } 4352712Snn35248 4362712Snn35248 xmlFree(content); 4372712Snn35248 4382712Snn35248 return (err); 4392712Snn35248 } 4402712Snn35248 4412712Snn35248 int 4422727Sedp brand_get_boot(brand_handle_t bh, const char *zonename, 4432712Snn35248 const char *zoneroot, char *buf, size_t len, int argc, char **argv) 4442712Snn35248 { 4452727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4462712Snn35248 return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 4472712Snn35248 buf, len, argc, argv, DTD_ELEM_BOOT, B_TRUE, B_TRUE)); 4482712Snn35248 } 4492712Snn35248 4502712Snn35248 int 4512727Sedp brand_get_brandname(brand_handle_t bh, char *buf, size_t len) 4522712Snn35248 { 4532727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4542712Snn35248 if (len <= strlen(bhp->bh_name)) 4552712Snn35248 return (-1); 4562712Snn35248 4572712Snn35248 (void) strcpy(buf, bhp->bh_name); 4582712Snn35248 4592712Snn35248 return (0); 4602712Snn35248 } 4612712Snn35248 4622712Snn35248 int 4632727Sedp brand_get_halt(brand_handle_t bh, const char *zonename, 4642712Snn35248 const char *zoneroot, char *buf, size_t len, int argc, char **argv) 4652712Snn35248 { 4662727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4672712Snn35248 return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 4682712Snn35248 buf, len, argc, argv, DTD_ELEM_HALT, B_TRUE, B_TRUE)); 4692712Snn35248 } 4702712Snn35248 4712712Snn35248 int 4722727Sedp brand_get_initname(brand_handle_t bh, char *buf, size_t len) 4732712Snn35248 { 4742727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4752712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 4762712Snn35248 buf, len, 0, NULL, DTD_ELEM_INITNAME, B_FALSE, B_FALSE)); 4772712Snn35248 } 4782712Snn35248 4792712Snn35248 int 4802727Sedp brand_get_login_cmd(brand_handle_t bh, const char *username, 4812712Snn35248 char *buf, size_t len) 4822712Snn35248 { 4832727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4842712Snn35248 const char *curr_zone = get_curr_zone(); 4852712Snn35248 return (brand_get_value(bhp, NULL, NULL, username, curr_zone, 4862712Snn35248 buf, len, 0, NULL, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE)); 4872712Snn35248 } 4882712Snn35248 4892712Snn35248 int 4904344Ssl108498 brand_get_user_cmd(brand_handle_t bh, const char *username, 4914344Ssl108498 char *buf, size_t len) 4924344Ssl108498 { 4934344Ssl108498 struct brand_handle *bhp = (struct brand_handle *)bh; 4944344Ssl108498 4954344Ssl108498 return (brand_get_value(bhp, NULL, NULL, username, NULL, 4964344Ssl108498 buf, len, 0, NULL, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE)); 4974344Ssl108498 } 4984344Ssl108498 4994344Ssl108498 int 5002727Sedp brand_get_install(brand_handle_t bh, const char *zonename, 5012712Snn35248 const char *zoneroot, char *buf, size_t len, int argc, char **argv) 5022712Snn35248 { 5032727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5042712Snn35248 return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 5052712Snn35248 buf, len, argc, argv, DTD_ELEM_INSTALL, B_TRUE, B_FALSE)); 5062712Snn35248 } 5072712Snn35248 5082712Snn35248 int 5092727Sedp brand_get_installopts(brand_handle_t bh, char *buf, size_t len) 5102712Snn35248 { 5112727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5122712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5132712Snn35248 buf, len, 0, NULL, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE)); 5142712Snn35248 } 5152712Snn35248 5162712Snn35248 int 5172727Sedp brand_get_modname(brand_handle_t bh, char *buf, size_t len) 5182712Snn35248 { 5192727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5202712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5212712Snn35248 buf, len, 0, NULL, DTD_ELEM_MODNAME, B_FALSE, B_TRUE)); 5222712Snn35248 } 5232712Snn35248 5242712Snn35248 int 5252727Sedp brand_get_postclone(brand_handle_t bh, const char *zonename, 5262712Snn35248 const char *zoneroot, char *buf, size_t len, int argc, char **argv) 5272712Snn35248 { 5282727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5292712Snn35248 return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 5302712Snn35248 buf, len, argc, argv, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE)); 5312712Snn35248 } 5322712Snn35248 5332712Snn35248 int 534*4586Sgjelinek brand_get_postinstall(brand_handle_t bh, const char *zonename, 535*4586Sgjelinek const char *zoneroot, char *buf, size_t len, int argc, char **argv) 536*4586Sgjelinek { 537*4586Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 538*4586Sgjelinek return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 539*4586Sgjelinek buf, len, argc, argv, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE)); 540*4586Sgjelinek } 541*4586Sgjelinek 542*4586Sgjelinek int 5432727Sedp brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len) 5442712Snn35248 { 5452727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5462712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5472712Snn35248 buf, len, 0, NULL, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE)); 5482712Snn35248 } 5492712Snn35248 5502712Snn35248 int 5512727Sedp brand_get_verify_adm(brand_handle_t bh, const char *zonename, 5522712Snn35248 const char *zoneroot, char *buf, size_t len, int argc, char **argv) 5532712Snn35248 { 5542727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5552712Snn35248 return (brand_get_value(bhp, zonename, zoneroot, NULL, NULL, 5562712Snn35248 buf, len, argc, argv, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE)); 5572712Snn35248 } 5582712Snn35248 5592712Snn35248 int 5602727Sedp brand_is_native(brand_handle_t bh) 5612712Snn35248 { 5622727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5632712Snn35248 return ((strcmp(bhp->bh_name, NATIVE_BRAND_NAME) == 0) ? 1 : 0); 5642712Snn35248 } 5652712Snn35248 5663448Sdh155122 boolean_t 5673448Sdh155122 brand_allow_exclusive_ip(brand_handle_t bh) 5683448Sdh155122 { 5693448Sdh155122 struct brand_handle *bhp = (struct brand_handle *)bh; 5703448Sdh155122 xmlNodePtr node; 5713448Sdh155122 xmlChar *allow_excl; 5723448Sdh155122 boolean_t ret; 5733448Sdh155122 5743448Sdh155122 assert(bhp != NULL); 5753448Sdh155122 5763448Sdh155122 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 5773448Sdh155122 return (B_FALSE); 5783448Sdh155122 5793448Sdh155122 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL); 5803448Sdh155122 if (allow_excl == NULL) 5813448Sdh155122 return (B_FALSE); 5823448Sdh155122 5833448Sdh155122 /* Note: only return B_TRUE if it's "true" */ 5843448Sdh155122 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0) 5853448Sdh155122 ret = B_TRUE; 5863448Sdh155122 else 5873448Sdh155122 ret = B_FALSE; 5883448Sdh155122 5893448Sdh155122 xmlFree(allow_excl); 5903448Sdh155122 5913448Sdh155122 return (ret); 5923448Sdh155122 } 5933448Sdh155122 5942712Snn35248 /* 5952712Snn35248 * Iterate over brand privileges 5962712Snn35248 * 5972712Snn35248 * Walks the brand config, searching for <privilege> elements, calling the 5982712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 5992712Snn35248 */ 6002712Snn35248 int 6013673Sdh155122 brand_config_iter_privilege(brand_handle_t bh, 6023673Sdh155122 int (*func)(void *, priv_iter_t *), void *data) 6032712Snn35248 { 6042727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 6052712Snn35248 xmlNodePtr node; 6063673Sdh155122 xmlChar *name, *set, *iptype; 6073673Sdh155122 priv_iter_t priv_iter; 6082712Snn35248 int ret; 6092712Snn35248 6102712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 6112712Snn35248 return (-1); 6122712Snn35248 6132712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 6142712Snn35248 6152712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0) 6162712Snn35248 continue; 6172712Snn35248 6182712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 6192712Snn35248 set = xmlGetProp(node, DTD_ATTR_SET); 6203673Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 6212712Snn35248 6223673Sdh155122 if (name == NULL || set == NULL || iptype == NULL) { 6232712Snn35248 if (name != NULL) 6242712Snn35248 xmlFree(name); 6252712Snn35248 if (set != NULL) 6262712Snn35248 xmlFree(set); 6273673Sdh155122 if (iptype != NULL) 6283673Sdh155122 xmlFree(iptype); 6292712Snn35248 return (-1); 6302712Snn35248 } 6312712Snn35248 6323673Sdh155122 priv_iter.pi_name = (char *)name; 6333673Sdh155122 priv_iter.pi_set = (char *)set; 6343673Sdh155122 priv_iter.pi_iptype = (char *)iptype; 6353673Sdh155122 6363673Sdh155122 ret = func(data, &priv_iter); 6372712Snn35248 6382712Snn35248 xmlFree(name); 6392712Snn35248 xmlFree(set); 6403673Sdh155122 xmlFree(iptype); 6412712Snn35248 6422712Snn35248 if (ret != 0) 6432712Snn35248 return (-1); 6442712Snn35248 } 6452712Snn35248 6462712Snn35248 return (0); 6472712Snn35248 } 6482712Snn35248 6492712Snn35248 static int 6502727Sedp i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zoneroot, 6512712Snn35248 int (*func)(void *, const char *, const char *, const char *, 6522712Snn35248 const char *), void *data, const xmlChar *mount_type) 6532712Snn35248 { 6542712Snn35248 xmlNodePtr node; 6552712Snn35248 xmlChar *special, *dir, *type, *opt; 6562712Snn35248 char special_exp[MAXPATHLEN]; 6572712Snn35248 char opt_exp[MAXPATHLEN]; 6582712Snn35248 int ret; 6592712Snn35248 6602712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 6612712Snn35248 return (-1); 6622712Snn35248 6632712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 6642712Snn35248 6652712Snn35248 if (xmlStrcmp(node->name, mount_type) != 0) 6662712Snn35248 continue; 6672712Snn35248 6682712Snn35248 special = xmlGetProp(node, DTD_ATTR_SPECIAL); 6692712Snn35248 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY); 6702712Snn35248 type = xmlGetProp(node, DTD_ATTR_TYPE); 6712712Snn35248 opt = xmlGetProp(node, DTD_ATTR_OPT); 6722712Snn35248 if ((special == NULL) || (dir == NULL) || (type == NULL) || 6732712Snn35248 (opt == NULL)) { 6742712Snn35248 ret = -1; 6752712Snn35248 goto next; 6762712Snn35248 } 6772712Snn35248 6782712Snn35248 /* Substitute token values as needed. */ 6792712Snn35248 if ((ret = i_substitute_tokens((char *)special, 6802712Snn35248 special_exp, sizeof (special_exp), 6812712Snn35248 NULL, zoneroot, NULL, NULL, 0, NULL)) != 0) 6822712Snn35248 goto next; 6832712Snn35248 6842712Snn35248 /* opt might not be defined */ 6852712Snn35248 if (strlen((const char *)opt) == 0) { 6862712Snn35248 xmlFree(opt); 6872712Snn35248 opt = NULL; 6882712Snn35248 } else { 6892712Snn35248 if ((ret = i_substitute_tokens((char *)opt, 6902712Snn35248 opt_exp, sizeof (opt_exp), 6912712Snn35248 NULL, zoneroot, NULL, NULL, 0, NULL)) != 0) 6922712Snn35248 goto next; 6932712Snn35248 } 6942712Snn35248 6952712Snn35248 ret = func(data, (char *)special_exp, (char *)dir, 6962712Snn35248 (char *)type, ((opt != NULL) ? opt_exp : NULL)); 6972712Snn35248 6982712Snn35248 next: 6992712Snn35248 if (special != NULL) 7002712Snn35248 xmlFree(special); 7012712Snn35248 if (dir != NULL) 7022712Snn35248 xmlFree(dir); 7032712Snn35248 if (type != NULL) 7042712Snn35248 xmlFree(type); 7052712Snn35248 if (opt != NULL) 7062712Snn35248 xmlFree(opt); 7072712Snn35248 if (ret != 0) 7082712Snn35248 return (-1); 7092712Snn35248 } 7102712Snn35248 return (0); 7112712Snn35248 } 7122712Snn35248 7132712Snn35248 7142712Snn35248 /* 7152712Snn35248 * Iterate over global platform filesystems 7162712Snn35248 * 7172712Snn35248 * Walks the platform, searching for <global_mount> elements, calling the 7182712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 7192712Snn35248 * 7202712Snn35248 * Perform the following substitutions as necessary: 7212712Snn35248 * 7222712Snn35248 * %R Root of zone 7232712Snn35248 */ 7242712Snn35248 int 7252727Sedp brand_platform_iter_gmounts(brand_handle_t bh, const char *zoneroot, 7262712Snn35248 int (*func)(void *, const char *, const char *, const char *, 7272712Snn35248 const char *), void *data) 7282712Snn35248 { 7292727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 7302712Snn35248 return (i_brand_platform_iter_mounts(bhp, zoneroot, func, data, 7312712Snn35248 DTD_ELEM_GLOBAL_MOUNT)); 7322712Snn35248 } 7332712Snn35248 7342712Snn35248 /* 7352712Snn35248 * Iterate over non-global zone platform filesystems 7362712Snn35248 * 7372712Snn35248 * Walks the platform, searching for <mount> elements, calling the 7382712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 7392712Snn35248 */ 7402712Snn35248 int 7412727Sedp brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *, 7422712Snn35248 const char *, const char *, const char *, const char *), void *data) 7432712Snn35248 { 7442727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 7452712Snn35248 return (i_brand_platform_iter_mounts(bhp, NULL, func, data, 7462712Snn35248 DTD_ELEM_MOUNT)); 7472712Snn35248 } 7482712Snn35248 7492712Snn35248 /* 7502712Snn35248 * Iterate over platform symlinks 7512712Snn35248 * 7522712Snn35248 * Walks the platform, searching for <symlink> elements, calling the 7532712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 7542712Snn35248 */ 7552712Snn35248 int 7562727Sedp brand_platform_iter_link(brand_handle_t bh, 7572712Snn35248 int (*func)(void *, const char *, const char *), void *data) 7582712Snn35248 { 7592727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 7602712Snn35248 xmlNodePtr node; 7612712Snn35248 xmlChar *source, *target; 7622712Snn35248 int ret; 7632712Snn35248 7642712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 7652712Snn35248 return (-1); 7662712Snn35248 7672712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 7682712Snn35248 7692712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0) 7702712Snn35248 continue; 7712712Snn35248 7722712Snn35248 source = xmlGetProp(node, DTD_ATTR_SOURCE); 7732712Snn35248 target = xmlGetProp(node, DTD_ATTR_TARGET); 7742712Snn35248 7752712Snn35248 if (source == NULL || target == NULL) { 7762712Snn35248 if (source != NULL) 7772712Snn35248 xmlFree(source); 7782712Snn35248 if (target != NULL) 7792712Snn35248 xmlFree(target); 7802712Snn35248 return (-1); 7812712Snn35248 } 7822712Snn35248 7832712Snn35248 ret = func(data, (char *)source, (char *)target); 7842712Snn35248 7852712Snn35248 xmlFree(source); 7862712Snn35248 xmlFree(target); 7872712Snn35248 7882712Snn35248 if (ret != 0) 7892712Snn35248 return (-1); 7902712Snn35248 } 7912712Snn35248 7922712Snn35248 return (0); 7932712Snn35248 } 7942712Snn35248 7952712Snn35248 /* 7962712Snn35248 * Iterate over platform devices 7972712Snn35248 * 7982712Snn35248 * Walks the platform, searching for <device> elements, calling the 7992712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 8002712Snn35248 */ 8012712Snn35248 int 8022727Sedp brand_platform_iter_devices(brand_handle_t bh, const char *zonename, 8033448Sdh155122 int (*func)(void *, const char *, const char *), void *data, 8043448Sdh155122 const char *curr_iptype) 8052712Snn35248 { 8062727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 8072727Sedp const char *curr_arch = get_curr_arch(); 8082727Sedp xmlNodePtr node; 8093448Sdh155122 xmlChar *match, *name, *arch, *iptype; 8102727Sedp char match_exp[MAXPATHLEN]; 8112727Sedp boolean_t err = B_FALSE; 8122727Sedp int ret = 0; 8132712Snn35248 8142712Snn35248 8152712Snn35248 assert(bhp != NULL); 8162712Snn35248 assert(zonename != NULL); 8172712Snn35248 assert(func != NULL); 8183448Sdh155122 assert(curr_iptype != NULL); 8192712Snn35248 8202712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 8212712Snn35248 return (-1); 8222712Snn35248 8232712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 8242712Snn35248 8252712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0) 8262712Snn35248 continue; 8272712Snn35248 8282712Snn35248 match = xmlGetProp(node, DTD_ATTR_MATCH); 8292712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 8302712Snn35248 arch = xmlGetProp(node, DTD_ATTR_ARCH); 8313448Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 8323448Sdh155122 if ((match == NULL) || (name == NULL) || (arch == NULL) || 8333448Sdh155122 (iptype == NULL)) { 8342712Snn35248 err = B_TRUE; 8352712Snn35248 goto next; 8362712Snn35248 } 8372712Snn35248 8382712Snn35248 /* check if the arch matches */ 8392712Snn35248 if ((strcmp((char *)arch, "all") != 0) && 8402712Snn35248 (strcmp((char *)arch, curr_arch) != 0)) 8412712Snn35248 goto next; 8422712Snn35248 8433448Sdh155122 /* check if the iptype matches */ 8443448Sdh155122 if ((strcmp((char *)iptype, "all") != 0) && 8453448Sdh155122 (strcmp((char *)iptype, curr_iptype) != 0)) 8463448Sdh155122 goto next; 8473448Sdh155122 8482712Snn35248 /* Substitute token values as needed. */ 8492712Snn35248 if ((ret = i_substitute_tokens((char *)match, 8502712Snn35248 match_exp, sizeof (match_exp), 8512712Snn35248 zonename, NULL, NULL, NULL, 0, NULL)) != 0) { 8522712Snn35248 err = B_TRUE; 8532712Snn35248 goto next; 8542712Snn35248 } 8552712Snn35248 8562712Snn35248 /* name might not be defined */ 8572712Snn35248 if (strlen((const char *)name) == 0) { 8582712Snn35248 xmlFree(name); 8592712Snn35248 name = NULL; 8602712Snn35248 } 8612712Snn35248 8622712Snn35248 /* invoke the callback */ 8632712Snn35248 ret = func(data, (const char *)match_exp, (const char *)name); 8642712Snn35248 8652712Snn35248 next: 8662712Snn35248 if (match != NULL) 8672712Snn35248 xmlFree(match); 8682712Snn35248 if (name != NULL) 8692712Snn35248 xmlFree(name); 8702712Snn35248 if (arch != NULL) 8712712Snn35248 xmlFree(arch); 8723448Sdh155122 if (iptype != NULL) 8733448Sdh155122 xmlFree(iptype); 8742712Snn35248 if (err) 8752712Snn35248 return (-1); 8762712Snn35248 if (ret != 0) 8772712Snn35248 return (-1); 8782712Snn35248 } 8792712Snn35248 8802712Snn35248 return (0); 8812712Snn35248 } 882