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 /* 2310718SJordan.Vaughan@Sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242712Snn35248 * Use is subject to license terms. 252712Snn35248 */ 262712Snn35248 272712Snn35248 #include <assert.h> 282712Snn35248 #include <dirent.h> 292712Snn35248 #include <errno.h> 302712Snn35248 #include <fnmatch.h> 312712Snn35248 #include <signal.h> 322712Snn35248 #include <stdlib.h> 332712Snn35248 #include <unistd.h> 342712Snn35248 #include <strings.h> 352712Snn35248 #include <synch.h> 362712Snn35248 #include <sys/brand.h> 372712Snn35248 #include <sys/fcntl.h> 382712Snn35248 #include <sys/param.h> 392712Snn35248 #include <sys/stat.h> 402712Snn35248 #include <sys/systeminfo.h> 412712Snn35248 #include <sys/types.h> 422712Snn35248 #include <thread.h> 432712Snn35248 #include <zone.h> 442712Snn35248 452712Snn35248 #include <libbrand_impl.h> 462712Snn35248 #include <libbrand.h> 472712Snn35248 487089Sgjelinek #define DTD_ELEM_ATTACH ((const xmlChar *) "attach") 492712Snn35248 #define DTD_ELEM_BOOT ((const xmlChar *) "boot") 502712Snn35248 #define DTD_ELEM_BRAND ((const xmlChar *) "brand") 517089Sgjelinek #define DTD_ELEM_CLONE ((const xmlChar *) "clone") 522712Snn35248 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment") 537089Sgjelinek #define DTD_ELEM_DETACH ((const xmlChar *) "detach") 542712Snn35248 #define DTD_ELEM_DEVICE ((const xmlChar *) "device") 552712Snn35248 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount") 562712Snn35248 #define DTD_ELEM_HALT ((const xmlChar *) "halt") 572712Snn35248 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname") 582712Snn35248 #define DTD_ELEM_INSTALL ((const xmlChar *) "install") 592712Snn35248 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts") 602712Snn35248 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd") 612712Snn35248 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname") 622712Snn35248 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount") 634785Sgjelinek #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach") 642712Snn35248 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone") 654586Sgjelinek #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall") 667089Sgjelinek #define DTD_ELEM_POSTSNAP ((const xmlChar *) "postsnap") 677370S<Gerald Jelinek> #define DTD_ELEM_POSTSTATECHG ((const xmlChar *) "poststatechange") 684785Sgjelinek #define DTD_ELEM_PREDETACH ((const xmlChar *) "predetach") 697089Sgjelinek #define DTD_ELEM_PRESNAP ((const xmlChar *) "presnap") 707370S<Gerald Jelinek> #define DTD_ELEM_PRESTATECHG ((const xmlChar *) "prestatechange") 714785Sgjelinek #define DTD_ELEM_PREUNINSTALL ((const xmlChar *) "preuninstall") 722712Snn35248 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege") 737370S<Gerald Jelinek> #define DTD_ELEM_QUERY ((const xmlChar *) "query") 742712Snn35248 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink") 7510718SJordan.Vaughan@Sun.com #define DTD_ELEM_SYSBOOT ((const xmlChar *) "sysboot") 767089Sgjelinek #define DTD_ELEM_UNINSTALL ((const xmlChar *) "uninstall") 774344Ssl108498 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd") 787089Sgjelinek #define DTD_ELEM_VALIDSNAP ((const xmlChar *) "validatesnap") 792712Snn35248 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg") 802712Snn35248 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm") 812712Snn35248 823448Sdh155122 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip") 832712Snn35248 #define DTD_ATTR_ARCH ((const xmlChar *) "arch") 842712Snn35248 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory") 853448Sdh155122 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type") 862712Snn35248 #define DTD_ATTR_MATCH ((const xmlChar *) "match") 872712Snn35248 #define DTD_ATTR_MODE ((const xmlChar *) "mode") 882712Snn35248 #define DTD_ATTR_NAME ((const xmlChar *) "name") 892712Snn35248 #define DTD_ATTR_OPT ((const xmlChar *) "opt") 902712Snn35248 #define DTD_ATTR_PATH ((const xmlChar *) "path") 912712Snn35248 #define DTD_ATTR_SET ((const xmlChar *) "set") 922712Snn35248 #define DTD_ATTR_SOURCE ((const xmlChar *) "source") 932712Snn35248 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special") 942712Snn35248 #define DTD_ATTR_TARGET ((const xmlChar *) "target") 952712Snn35248 #define DTD_ATTR_TYPE ((const xmlChar *) "type") 962712Snn35248 973448Sdh155122 #define DTD_ENTITY_TRUE "true" 983448Sdh155122 992712Snn35248 static volatile boolean_t libbrand_initialized = B_FALSE; 1002712Snn35248 static char i_curr_arch[MAXNAMELEN]; 1012712Snn35248 static char i_curr_zone[ZONENAME_MAX]; 1022712Snn35248 1032712Snn35248 /*ARGSUSED*/ 1042712Snn35248 static void 1052712Snn35248 brand_error_func(void *ctx, const char *msg, ...) 1062712Snn35248 { 1072712Snn35248 /* 1082712Snn35248 * Ignore error messages from libxml 1092712Snn35248 */ 1102712Snn35248 } 1112712Snn35248 1122712Snn35248 static boolean_t 1132712Snn35248 libbrand_initialize() 1142712Snn35248 { 1152712Snn35248 static mutex_t initialize_lock = DEFAULTMUTEX; 1162712Snn35248 1172712Snn35248 (void) mutex_lock(&initialize_lock); 1182712Snn35248 1192712Snn35248 if (libbrand_initialized) { 1202712Snn35248 (void) mutex_unlock(&initialize_lock); 1212712Snn35248 return (B_TRUE); 1222712Snn35248 } 1232712Snn35248 1242712Snn35248 if (sysinfo(SI_ARCHITECTURE, i_curr_arch, sizeof (i_curr_arch)) < 0) { 1252712Snn35248 (void) mutex_unlock(&initialize_lock); 1262712Snn35248 return (B_FALSE); 1272712Snn35248 } 1282712Snn35248 1292712Snn35248 if (getzonenamebyid(getzoneid(), i_curr_zone, 1302712Snn35248 sizeof (i_curr_zone)) < 0) { 1312712Snn35248 (void) mutex_unlock(&initialize_lock); 1322712Snn35248 return (B_FALSE); 1332712Snn35248 } 1342712Snn35248 1352712Snn35248 /* 1362712Snn35248 * Note that here we're initializing per-process libxml2 1372712Snn35248 * state. By doing so we're implicitly assuming that 1382712Snn35248 * no other code in this process is also trying to 1392712Snn35248 * use libxml2. But in most case we know this not to 1402712Snn35248 * be true since we're almost always used in conjunction 1412712Snn35248 * with libzonecfg, which also uses libxml2. Lucky for 1422712Snn35248 * us, libzonecfg initializes libxml2 to essentially 1432712Snn35248 * the same defaults as we're using below. 1442712Snn35248 */ 145*11411SSurya.Prakki@Sun.COM (void) xmlLineNumbersDefault(1); 1462712Snn35248 xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS; 1472712Snn35248 xmlDoValidityCheckingDefaultValue = 1; 1482712Snn35248 (void) xmlKeepBlanksDefault(0); 1492712Snn35248 xmlGetWarningsDefaultValue = 0; 1502712Snn35248 xmlSetGenericErrorFunc(NULL, brand_error_func); 1512712Snn35248 1522712Snn35248 libbrand_initialized = B_TRUE; 1532712Snn35248 (void) mutex_unlock(&initialize_lock); 1542712Snn35248 return (B_TRUE); 1552712Snn35248 } 1562712Snn35248 1572712Snn35248 static const char * 1582712Snn35248 get_curr_arch(void) 1592712Snn35248 { 1602712Snn35248 if (!libbrand_initialize()) 1612712Snn35248 return (NULL); 1622712Snn35248 1632712Snn35248 return (i_curr_arch); 1642712Snn35248 } 1652712Snn35248 1662712Snn35248 static const char * 1672712Snn35248 get_curr_zone(void) 1682712Snn35248 { 1692712Snn35248 if (!libbrand_initialize()) 1702712Snn35248 return (NULL); 1712712Snn35248 1722712Snn35248 return (i_curr_zone); 1732712Snn35248 } 1742712Snn35248 1752712Snn35248 /* 1762712Snn35248 * Internal function to open an XML file 1772712Snn35248 * 1782712Snn35248 * Returns the XML doc pointer, or NULL on failure. It will validate the 1792712Snn35248 * document, as well as removing any comments from the document structure. 1802712Snn35248 */ 1812712Snn35248 static xmlDocPtr 1822712Snn35248 open_xml_file(const char *file) 1832712Snn35248 { 1842712Snn35248 xmlDocPtr doc; 1852712Snn35248 xmlValidCtxtPtr cvp; 1862712Snn35248 int valid; 1872712Snn35248 1882712Snn35248 if (!libbrand_initialize()) 1892712Snn35248 return (NULL); 1902712Snn35248 1912712Snn35248 /* 1922712Snn35248 * Parse the file 1932712Snn35248 */ 1942712Snn35248 if ((doc = xmlParseFile(file)) == NULL) 1952712Snn35248 return (NULL); 1962712Snn35248 1972712Snn35248 /* 1982712Snn35248 * Validate the file 1992712Snn35248 */ 2002712Snn35248 if ((cvp = xmlNewValidCtxt()) == NULL) { 2012712Snn35248 xmlFreeDoc(doc); 2022712Snn35248 return (NULL); 2032712Snn35248 } 2042712Snn35248 cvp->error = brand_error_func; 2052712Snn35248 cvp->warning = brand_error_func; 2062712Snn35248 valid = xmlValidateDocument(cvp, doc); 2072712Snn35248 xmlFreeValidCtxt(cvp); 2082712Snn35248 if (valid == 0) { 2092712Snn35248 xmlFreeDoc(doc); 2102712Snn35248 return (NULL); 2112712Snn35248 } 2122712Snn35248 2132712Snn35248 return (doc); 2142712Snn35248 } 2152712Snn35248 /* 2162712Snn35248 * Open a handle to the named brand. 2172712Snn35248 * 2182712Snn35248 * Returns a handle to the named brand, which is used for all subsequent brand 2192712Snn35248 * interaction, or NULL if unable to open or initialize the brand. 2202712Snn35248 */ 2212727Sedp brand_handle_t 2222712Snn35248 brand_open(const char *name) 2232712Snn35248 { 2242727Sedp struct brand_handle *bhp; 2252712Snn35248 char path[MAXPATHLEN]; 2262712Snn35248 xmlNodePtr node; 2272712Snn35248 xmlChar *property; 2282712Snn35248 struct stat statbuf; 2292712Snn35248 2302712Snn35248 /* 2312712Snn35248 * Make sure brand name isn't too long 2322712Snn35248 */ 2332712Snn35248 if (strlen(name) >= MAXNAMELEN) 2342712Snn35248 return (NULL); 2352712Snn35248 2362712Snn35248 /* 2372712Snn35248 * Check that the brand exists 2382712Snn35248 */ 2392712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s", BRAND_DIR, name); 2402712Snn35248 2412712Snn35248 if (stat(path, &statbuf) != 0) 2422712Snn35248 return (NULL); 2432712Snn35248 2442712Snn35248 /* 2452712Snn35248 * Allocate brand handle 2462712Snn35248 */ 2472727Sedp if ((bhp = malloc(sizeof (struct brand_handle))) == NULL) 2482712Snn35248 return (NULL); 2492727Sedp bzero(bhp, sizeof (struct brand_handle)); 2502712Snn35248 2512712Snn35248 (void) strcpy(bhp->bh_name, name); 2522712Snn35248 2532712Snn35248 /* 2542712Snn35248 * Open the configuration file 2552712Snn35248 */ 2562712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2572712Snn35248 BRAND_CONFIG); 2582712Snn35248 if ((bhp->bh_config = open_xml_file(path)) == NULL) { 2592727Sedp brand_close((brand_handle_t)bhp); 2602712Snn35248 return (NULL); 2612712Snn35248 } 2622712Snn35248 2632712Snn35248 /* 2642712Snn35248 * Verify that the name of the brand matches the directory in which it 2652712Snn35248 * is installed. 2662712Snn35248 */ 2672712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) { 2682727Sedp brand_close((brand_handle_t)bhp); 2692712Snn35248 return (NULL); 2702712Snn35248 } 2712712Snn35248 2722712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) { 2732727Sedp brand_close((brand_handle_t)bhp); 2742712Snn35248 return (NULL); 2752712Snn35248 } 2762712Snn35248 2772712Snn35248 if ((property = xmlGetProp(node, DTD_ATTR_NAME)) == NULL) { 2782727Sedp brand_close((brand_handle_t)bhp); 2792712Snn35248 return (NULL); 2802712Snn35248 } 2812712Snn35248 2822712Snn35248 if (strcmp((char *)property, name) != 0) { 2832712Snn35248 xmlFree(property); 2842727Sedp brand_close((brand_handle_t)bhp); 2852712Snn35248 return (NULL); 2862712Snn35248 } 2872712Snn35248 xmlFree(property); 2882712Snn35248 2892712Snn35248 /* 2902712Snn35248 * Open handle to platform configuration file. 2912712Snn35248 */ 2922712Snn35248 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name, 2932712Snn35248 BRAND_PLATFORM); 2942712Snn35248 if ((bhp->bh_platform = open_xml_file(path)) == NULL) { 2952727Sedp brand_close((brand_handle_t)bhp); 2962712Snn35248 return (NULL); 2972712Snn35248 } 2982712Snn35248 2992727Sedp return ((brand_handle_t)bhp); 3002712Snn35248 } 3012712Snn35248 3022712Snn35248 /* 3032712Snn35248 * Closes the given brand handle 3042712Snn35248 */ 3052712Snn35248 void 3062727Sedp brand_close(brand_handle_t bh) 3072712Snn35248 { 3082727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 3092712Snn35248 if (bhp->bh_platform != NULL) 3102712Snn35248 xmlFreeDoc(bhp->bh_platform); 3112712Snn35248 if (bhp->bh_config != NULL) 3122712Snn35248 xmlFreeDoc(bhp->bh_config); 3132712Snn35248 free(bhp); 3142712Snn35248 } 3152712Snn35248 3162712Snn35248 static int 3172712Snn35248 i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size, 3187089Sgjelinek const char *zonename, const char *zonepath, const char *username, 3197089Sgjelinek const char *curr_zone) 3202712Snn35248 { 3217089Sgjelinek int dst, src; 3222712Snn35248 3232712Snn35248 /* 3242712Snn35248 * Walk through the characters, substituting values as needed. 3252712Snn35248 */ 3262712Snn35248 dbuf[0] = '\0'; 3272712Snn35248 dst = 0; 3282712Snn35248 for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) { 3292712Snn35248 if (sbuf[src] != '%') { 3302712Snn35248 dbuf[dst++] = sbuf[src]; 3312712Snn35248 continue; 3322712Snn35248 } 3332712Snn35248 3342712Snn35248 switch (sbuf[++src]) { 3352712Snn35248 case '%': 3362712Snn35248 dst += strlcpy(dbuf + dst, "%", dbuf_size - dst); 3372712Snn35248 break; 3382712Snn35248 case 'R': 3397089Sgjelinek if (zonepath == NULL) 3402712Snn35248 break; 3417089Sgjelinek dst += strlcpy(dbuf + dst, zonepath, dbuf_size - dst); 3422712Snn35248 break; 3432712Snn35248 case 'u': 3442712Snn35248 if (username == NULL) 3452712Snn35248 break; 3462712Snn35248 dst += strlcpy(dbuf + dst, username, dbuf_size - dst); 3472712Snn35248 break; 3482712Snn35248 case 'Z': 3492712Snn35248 if (curr_zone == NULL) 3502712Snn35248 break; 3512712Snn35248 /* name of the zone we're running in */ 3522712Snn35248 dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst); 3532712Snn35248 break; 3542712Snn35248 case 'z': 3552712Snn35248 /* name of the zone we're operating on */ 3562712Snn35248 if (zonename == NULL) 3572712Snn35248 break; 3582712Snn35248 dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst); 3592712Snn35248 break; 3602712Snn35248 } 3612712Snn35248 } 3622712Snn35248 3632712Snn35248 if (dst >= dbuf_size) 3642712Snn35248 return (-1); 3652712Snn35248 3662712Snn35248 dbuf[dst] = '\0'; 3672712Snn35248 return (0); 3682712Snn35248 } 3692712Snn35248 3702712Snn35248 /* 3712712Snn35248 * Retrieve the given tag from the brand. 3722712Snn35248 * Perform the following substitutions as necessary: 3732712Snn35248 * 3742712Snn35248 * %% % 3752712Snn35248 * %u Username 3762712Snn35248 * %z Name of target zone 3772712Snn35248 * %Z Name of current zone 3787089Sgjelinek * %R Zonepath of zone 3792712Snn35248 * 3802712Snn35248 * Returns 0 on success, -1 on failure. 3812712Snn35248 */ 3822712Snn35248 static int 3832727Sedp brand_get_value(struct brand_handle *bhp, const char *zonename, 3847089Sgjelinek const char *zonepath, const char *username, const char *curr_zone, 3857089Sgjelinek char *buf, size_t len, const xmlChar *tagname, 3862712Snn35248 boolean_t substitute, boolean_t optional) 3872712Snn35248 { 3882712Snn35248 xmlNodePtr node; 3892712Snn35248 xmlChar *content; 3902712Snn35248 int err = 0; 3912712Snn35248 3922712Snn35248 /* 3932712Snn35248 * Retrieve the specified value from the XML doc 3942712Snn35248 */ 3952712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 3962712Snn35248 return (-1); 3972712Snn35248 3982712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) 3992712Snn35248 return (-1); 4002712Snn35248 4012712Snn35248 for (node = node->xmlChildrenNode; node != NULL; 4022712Snn35248 node = node->next) { 4032712Snn35248 if (xmlStrcmp(node->name, tagname) == 0) 4042712Snn35248 break; 4052712Snn35248 } 4062712Snn35248 4074607Sgjelinek if (node == NULL) { 4084607Sgjelinek if (optional) { 4094607Sgjelinek buf[0] = '\0'; 4104607Sgjelinek return (0); 4114607Sgjelinek } else { 4124607Sgjelinek return (-1); 4134607Sgjelinek } 4144607Sgjelinek } 4152712Snn35248 4162712Snn35248 if ((content = xmlNodeGetContent(node)) == NULL) 4172712Snn35248 return (-1); 4182712Snn35248 4192712Snn35248 if (strlen((char *)content) == 0) { 4202712Snn35248 /* 4212712Snn35248 * If the entry in the config file is empty, check to see 4222712Snn35248 * whether this is an optional field. If so, we return the 4232712Snn35248 * empty buffer. If not, we return an error. 4242712Snn35248 */ 4252712Snn35248 if (optional) { 4262712Snn35248 buf[0] = '\0'; 4272712Snn35248 } else { 4282712Snn35248 err = -1; 4292712Snn35248 } 4302712Snn35248 } else { 4312712Snn35248 /* Substitute token values as needed. */ 4322712Snn35248 if (substitute) { 4332712Snn35248 if (i_substitute_tokens((char *)content, buf, len, 4347089Sgjelinek zonename, zonepath, username, curr_zone) != 0) 4352712Snn35248 err = -1; 4362712Snn35248 } else { 4372712Snn35248 if (strlcpy(buf, (char *)content, len) >= len) 4382712Snn35248 err = -1; 4392712Snn35248 } 4402712Snn35248 } 4412712Snn35248 4422712Snn35248 xmlFree(content); 4432712Snn35248 4442712Snn35248 return (err); 4452712Snn35248 } 4462712Snn35248 4472712Snn35248 int 4487089Sgjelinek brand_get_attach(brand_handle_t bh, const char *zonename, 4497089Sgjelinek const char *zonepath, char *buf, size_t len) 4502712Snn35248 { 4512727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4527089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 4537089Sgjelinek buf, len, DTD_ELEM_ATTACH, B_TRUE, B_TRUE)); 4547089Sgjelinek } 4557089Sgjelinek 4567089Sgjelinek int 4577089Sgjelinek brand_get_boot(brand_handle_t bh, const char *zonename, 4587089Sgjelinek const char *zonepath, char *buf, size_t len) 4597089Sgjelinek { 4607089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 4617089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 4627089Sgjelinek buf, len, DTD_ELEM_BOOT, B_TRUE, B_TRUE)); 4632712Snn35248 } 4642712Snn35248 4652712Snn35248 int 4662727Sedp brand_get_brandname(brand_handle_t bh, char *buf, size_t len) 4672712Snn35248 { 4682727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4692712Snn35248 if (len <= strlen(bhp->bh_name)) 4702712Snn35248 return (-1); 4712712Snn35248 4722712Snn35248 (void) strcpy(buf, bhp->bh_name); 4732712Snn35248 4742712Snn35248 return (0); 4752712Snn35248 } 4762712Snn35248 4772712Snn35248 int 4787089Sgjelinek brand_get_clone(brand_handle_t bh, const char *zonename, 4797089Sgjelinek const char *zonepath, char *buf, size_t len) 4802712Snn35248 { 4812727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 4827089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 4837089Sgjelinek buf, len, DTD_ELEM_CLONE, B_TRUE, B_TRUE)); 4847089Sgjelinek } 4857089Sgjelinek 4867089Sgjelinek int 4877089Sgjelinek brand_get_detach(brand_handle_t bh, const char *zonename, 4887089Sgjelinek const char *zonepath, char *buf, size_t len) 4897089Sgjelinek { 4907089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 4917089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 4927089Sgjelinek buf, len, DTD_ELEM_DETACH, B_TRUE, B_TRUE)); 4937089Sgjelinek } 4947089Sgjelinek 4957089Sgjelinek int 4967089Sgjelinek brand_get_halt(brand_handle_t bh, const char *zonename, 4977089Sgjelinek const char *zonepath, char *buf, size_t len) 4987089Sgjelinek { 4997089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 5007089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5017089Sgjelinek buf, len, DTD_ELEM_HALT, B_TRUE, B_TRUE)); 5022712Snn35248 } 5032712Snn35248 5042712Snn35248 int 5052727Sedp brand_get_initname(brand_handle_t bh, char *buf, size_t len) 5062712Snn35248 { 5072727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5082712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5097089Sgjelinek buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE)); 5102712Snn35248 } 5112712Snn35248 5122712Snn35248 int 5132727Sedp brand_get_login_cmd(brand_handle_t bh, const char *username, 5142712Snn35248 char *buf, size_t len) 5152712Snn35248 { 5162727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5172712Snn35248 const char *curr_zone = get_curr_zone(); 5182712Snn35248 return (brand_get_value(bhp, NULL, NULL, username, curr_zone, 5197089Sgjelinek buf, len, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE)); 5202712Snn35248 } 5212712Snn35248 5222712Snn35248 int 5234344Ssl108498 brand_get_user_cmd(brand_handle_t bh, const char *username, 5244344Ssl108498 char *buf, size_t len) 5254344Ssl108498 { 5264344Ssl108498 struct brand_handle *bhp = (struct brand_handle *)bh; 5274344Ssl108498 5284344Ssl108498 return (brand_get_value(bhp, NULL, NULL, username, NULL, 5297089Sgjelinek buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE)); 5304344Ssl108498 } 5314344Ssl108498 5324344Ssl108498 int 5332727Sedp brand_get_install(brand_handle_t bh, const char *zonename, 5347089Sgjelinek const char *zonepath, char *buf, size_t len) 5352712Snn35248 { 5362727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5377089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5387089Sgjelinek buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE)); 5392712Snn35248 } 5402712Snn35248 5412712Snn35248 int 5422727Sedp brand_get_installopts(brand_handle_t bh, char *buf, size_t len) 5432712Snn35248 { 5442727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5452712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5467089Sgjelinek buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE)); 5472712Snn35248 } 5482712Snn35248 5492712Snn35248 int 5502727Sedp brand_get_modname(brand_handle_t bh, char *buf, size_t len) 5512712Snn35248 { 5522727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5532712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 5547089Sgjelinek buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE)); 5552712Snn35248 } 5562712Snn35248 5572712Snn35248 int 5584785Sgjelinek brand_get_postattach(brand_handle_t bh, const char *zonename, 5597089Sgjelinek const char *zonepath, char *buf, size_t len) 5604785Sgjelinek { 5614785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 5627089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5637089Sgjelinek buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE)); 5644785Sgjelinek } 5654785Sgjelinek 5664785Sgjelinek int 5672727Sedp brand_get_postclone(brand_handle_t bh, const char *zonename, 5687089Sgjelinek const char *zonepath, char *buf, size_t len) 5692712Snn35248 { 5702727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 5717089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5727089Sgjelinek buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE)); 5732712Snn35248 } 5742712Snn35248 5752712Snn35248 int 5764586Sgjelinek brand_get_postinstall(brand_handle_t bh, const char *zonename, 5777089Sgjelinek const char *zonepath, char *buf, size_t len) 5784586Sgjelinek { 5794586Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 5807089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5817089Sgjelinek buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE)); 5827089Sgjelinek } 5837089Sgjelinek 5847089Sgjelinek int 5857089Sgjelinek brand_get_postsnap(brand_handle_t bh, const char *zonename, 5867089Sgjelinek const char *zonepath, char *buf, size_t len) 5877089Sgjelinek { 5887089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 5897089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5907089Sgjelinek buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE)); 5914586Sgjelinek } 5924586Sgjelinek 5934586Sgjelinek int 5947370S<Gerald Jelinek> brand_get_poststatechange(brand_handle_t bh, const char *zonename, 5957370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len) 5967370S<Gerald Jelinek> { 5977370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh; 5987370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 5997370S<Gerald Jelinek> buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE)); 6007370S<Gerald Jelinek> } 6017370S<Gerald Jelinek> 6027370S<Gerald Jelinek> int 6034785Sgjelinek brand_get_predetach(brand_handle_t bh, const char *zonename, 6047089Sgjelinek const char *zonepath, char *buf, size_t len) 6054785Sgjelinek { 6064785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 6077089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6087089Sgjelinek buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE)); 6097089Sgjelinek } 6107089Sgjelinek 6117089Sgjelinek int 6127089Sgjelinek brand_get_presnap(brand_handle_t bh, const char *zonename, 6137089Sgjelinek const char *zonepath, char *buf, size_t len) 6147089Sgjelinek { 6157089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 6167089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6177089Sgjelinek buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE)); 6184785Sgjelinek } 6194785Sgjelinek 6204785Sgjelinek int 6217370S<Gerald Jelinek> brand_get_prestatechange(brand_handle_t bh, const char *zonename, 6227370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len) 6237370S<Gerald Jelinek> { 6247370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh; 6257370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6267370S<Gerald Jelinek> buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE)); 6277370S<Gerald Jelinek> } 6287370S<Gerald Jelinek> 6297370S<Gerald Jelinek> int 6304785Sgjelinek brand_get_preuninstall(brand_handle_t bh, const char *zonename, 6317089Sgjelinek const char *zonepath, char *buf, size_t len) 6327089Sgjelinek { 6337089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 6347089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6357089Sgjelinek buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE)); 6367089Sgjelinek } 6377089Sgjelinek 6387089Sgjelinek int 6397370S<Gerald Jelinek> brand_get_query(brand_handle_t bh, const char *zonename, 6407370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len) 6417370S<Gerald Jelinek> { 6427370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh; 6437370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6447370S<Gerald Jelinek> buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE)); 6457370S<Gerald Jelinek> } 6467370S<Gerald Jelinek> 6477370S<Gerald Jelinek> int 6487089Sgjelinek brand_get_uninstall(brand_handle_t bh, const char *zonename, 6497089Sgjelinek const char *zonepath, char *buf, size_t len) 6504785Sgjelinek { 6514785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 6527089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6537089Sgjelinek buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE)); 6547089Sgjelinek } 6557089Sgjelinek 6567089Sgjelinek int 6577089Sgjelinek brand_get_validatesnap(brand_handle_t bh, const char *zonename, 6587089Sgjelinek const char *zonepath, char *buf, size_t len) 6597089Sgjelinek { 6607089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh; 6617089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6627089Sgjelinek buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE)); 6634785Sgjelinek } 6644785Sgjelinek 6654785Sgjelinek int 6662727Sedp brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len) 6672712Snn35248 { 6682727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 6692712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL, 6707089Sgjelinek buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE)); 6712712Snn35248 } 6722712Snn35248 6732712Snn35248 int 6742727Sedp brand_get_verify_adm(brand_handle_t bh, const char *zonename, 6757089Sgjelinek const char *zonepath, char *buf, size_t len) 6762712Snn35248 { 6772727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 6787089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 6797089Sgjelinek buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE)); 6802712Snn35248 } 6812712Snn35248 6822712Snn35248 int 68310718SJordan.Vaughan@Sun.com brand_get_sysboot(brand_handle_t bh, const char *zonename, 68410718SJordan.Vaughan@Sun.com const char *zonepath, char *buf, size_t len) 68510718SJordan.Vaughan@Sun.com { 68610718SJordan.Vaughan@Sun.com struct brand_handle *bhp = (struct brand_handle *)bh; 68710718SJordan.Vaughan@Sun.com return (brand_get_value(bhp, zonename, zonepath, NULL, NULL, 68810718SJordan.Vaughan@Sun.com buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE)); 68910718SJordan.Vaughan@Sun.com } 69010718SJordan.Vaughan@Sun.com 6913448Sdh155122 boolean_t 6923448Sdh155122 brand_allow_exclusive_ip(brand_handle_t bh) 6933448Sdh155122 { 6943448Sdh155122 struct brand_handle *bhp = (struct brand_handle *)bh; 6953448Sdh155122 xmlNodePtr node; 6963448Sdh155122 xmlChar *allow_excl; 6973448Sdh155122 boolean_t ret; 6983448Sdh155122 6993448Sdh155122 assert(bhp != NULL); 7003448Sdh155122 7013448Sdh155122 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 7023448Sdh155122 return (B_FALSE); 7033448Sdh155122 7043448Sdh155122 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL); 7053448Sdh155122 if (allow_excl == NULL) 7063448Sdh155122 return (B_FALSE); 7073448Sdh155122 7083448Sdh155122 /* Note: only return B_TRUE if it's "true" */ 7093448Sdh155122 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0) 7103448Sdh155122 ret = B_TRUE; 7113448Sdh155122 else 7123448Sdh155122 ret = B_FALSE; 7133448Sdh155122 7143448Sdh155122 xmlFree(allow_excl); 7153448Sdh155122 7163448Sdh155122 return (ret); 7173448Sdh155122 } 7183448Sdh155122 7192712Snn35248 /* 7202712Snn35248 * Iterate over brand privileges 7212712Snn35248 * 7222712Snn35248 * Walks the brand config, searching for <privilege> elements, calling the 7232712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 7242712Snn35248 */ 7252712Snn35248 int 7263673Sdh155122 brand_config_iter_privilege(brand_handle_t bh, 7273673Sdh155122 int (*func)(void *, priv_iter_t *), void *data) 7282712Snn35248 { 7292727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 7302712Snn35248 xmlNodePtr node; 7313673Sdh155122 xmlChar *name, *set, *iptype; 7323673Sdh155122 priv_iter_t priv_iter; 7332712Snn35248 int ret; 7342712Snn35248 7352712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) 7362712Snn35248 return (-1); 7372712Snn35248 7382712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 7392712Snn35248 7402712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0) 7412712Snn35248 continue; 7422712Snn35248 7432712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 7442712Snn35248 set = xmlGetProp(node, DTD_ATTR_SET); 7453673Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 7462712Snn35248 7473673Sdh155122 if (name == NULL || set == NULL || iptype == NULL) { 7482712Snn35248 if (name != NULL) 7492712Snn35248 xmlFree(name); 7502712Snn35248 if (set != NULL) 7512712Snn35248 xmlFree(set); 7523673Sdh155122 if (iptype != NULL) 7533673Sdh155122 xmlFree(iptype); 7542712Snn35248 return (-1); 7552712Snn35248 } 7562712Snn35248 7573673Sdh155122 priv_iter.pi_name = (char *)name; 7583673Sdh155122 priv_iter.pi_set = (char *)set; 7593673Sdh155122 priv_iter.pi_iptype = (char *)iptype; 7603673Sdh155122 7613673Sdh155122 ret = func(data, &priv_iter); 7622712Snn35248 7632712Snn35248 xmlFree(name); 7642712Snn35248 xmlFree(set); 7653673Sdh155122 xmlFree(iptype); 7662712Snn35248 7672712Snn35248 if (ret != 0) 7682712Snn35248 return (-1); 7692712Snn35248 } 7702712Snn35248 7712712Snn35248 return (0); 7722712Snn35248 } 7732712Snn35248 7742712Snn35248 static int 7757089Sgjelinek i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonepath, 7762712Snn35248 int (*func)(void *, const char *, const char *, const char *, 7772712Snn35248 const char *), void *data, const xmlChar *mount_type) 7782712Snn35248 { 7792712Snn35248 xmlNodePtr node; 7802712Snn35248 xmlChar *special, *dir, *type, *opt; 7812712Snn35248 char special_exp[MAXPATHLEN]; 7822712Snn35248 char opt_exp[MAXPATHLEN]; 7832712Snn35248 int ret; 7842712Snn35248 7852712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 7862712Snn35248 return (-1); 7872712Snn35248 7882712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 7892712Snn35248 7902712Snn35248 if (xmlStrcmp(node->name, mount_type) != 0) 7912712Snn35248 continue; 7922712Snn35248 7932712Snn35248 special = xmlGetProp(node, DTD_ATTR_SPECIAL); 7942712Snn35248 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY); 7952712Snn35248 type = xmlGetProp(node, DTD_ATTR_TYPE); 7962712Snn35248 opt = xmlGetProp(node, DTD_ATTR_OPT); 7972712Snn35248 if ((special == NULL) || (dir == NULL) || (type == NULL) || 7982712Snn35248 (opt == NULL)) { 7992712Snn35248 ret = -1; 8002712Snn35248 goto next; 8012712Snn35248 } 8022712Snn35248 8032712Snn35248 /* Substitute token values as needed. */ 8042712Snn35248 if ((ret = i_substitute_tokens((char *)special, 8052712Snn35248 special_exp, sizeof (special_exp), 8067089Sgjelinek NULL, zonepath, NULL, NULL)) != 0) 8072712Snn35248 goto next; 8082712Snn35248 8092712Snn35248 /* opt might not be defined */ 8102712Snn35248 if (strlen((const char *)opt) == 0) { 8112712Snn35248 xmlFree(opt); 8122712Snn35248 opt = NULL; 8132712Snn35248 } else { 8142712Snn35248 if ((ret = i_substitute_tokens((char *)opt, 8152712Snn35248 opt_exp, sizeof (opt_exp), 8167089Sgjelinek NULL, zonepath, NULL, NULL)) != 0) 8172712Snn35248 goto next; 8182712Snn35248 } 8192712Snn35248 8202712Snn35248 ret = func(data, (char *)special_exp, (char *)dir, 8212712Snn35248 (char *)type, ((opt != NULL) ? opt_exp : NULL)); 8222712Snn35248 8232712Snn35248 next: 8242712Snn35248 if (special != NULL) 8252712Snn35248 xmlFree(special); 8262712Snn35248 if (dir != NULL) 8272712Snn35248 xmlFree(dir); 8282712Snn35248 if (type != NULL) 8292712Snn35248 xmlFree(type); 8302712Snn35248 if (opt != NULL) 8312712Snn35248 xmlFree(opt); 8322712Snn35248 if (ret != 0) 8332712Snn35248 return (-1); 8342712Snn35248 } 8352712Snn35248 return (0); 8362712Snn35248 } 8372712Snn35248 8382712Snn35248 8392712Snn35248 /* 8402712Snn35248 * Iterate over global platform filesystems 8412712Snn35248 * 8422712Snn35248 * Walks the platform, searching for <global_mount> elements, calling the 8432712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 8442712Snn35248 * 8452712Snn35248 * Perform the following substitutions as necessary: 8462712Snn35248 * 8477089Sgjelinek * %R Zonepath of zone 8482712Snn35248 */ 8492712Snn35248 int 8507089Sgjelinek brand_platform_iter_gmounts(brand_handle_t bh, const char *zonepath, 8512712Snn35248 int (*func)(void *, const char *, const char *, const char *, 8522712Snn35248 const char *), void *data) 8532712Snn35248 { 8542727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 8557089Sgjelinek return (i_brand_platform_iter_mounts(bhp, zonepath, func, data, 8562712Snn35248 DTD_ELEM_GLOBAL_MOUNT)); 8572712Snn35248 } 8582712Snn35248 8592712Snn35248 /* 8602712Snn35248 * Iterate over non-global zone platform filesystems 8612712Snn35248 * 8622712Snn35248 * Walks the platform, searching for <mount> elements, calling the 8632712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 8642712Snn35248 */ 8652712Snn35248 int 8662727Sedp brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *, 8672712Snn35248 const char *, const char *, const char *, const char *), void *data) 8682712Snn35248 { 8692727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 8702712Snn35248 return (i_brand_platform_iter_mounts(bhp, NULL, func, data, 8712712Snn35248 DTD_ELEM_MOUNT)); 8722712Snn35248 } 8732712Snn35248 8742712Snn35248 /* 8752712Snn35248 * Iterate over platform symlinks 8762712Snn35248 * 8772712Snn35248 * Walks the platform, searching for <symlink> elements, calling the 8782712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 8792712Snn35248 */ 8802712Snn35248 int 8812727Sedp brand_platform_iter_link(brand_handle_t bh, 8822712Snn35248 int (*func)(void *, const char *, const char *), void *data) 8832712Snn35248 { 8842727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 8852712Snn35248 xmlNodePtr node; 8862712Snn35248 xmlChar *source, *target; 8872712Snn35248 int ret; 8882712Snn35248 8892712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 8902712Snn35248 return (-1); 8912712Snn35248 8922712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 8932712Snn35248 8942712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0) 8952712Snn35248 continue; 8962712Snn35248 8972712Snn35248 source = xmlGetProp(node, DTD_ATTR_SOURCE); 8982712Snn35248 target = xmlGetProp(node, DTD_ATTR_TARGET); 8992712Snn35248 9002712Snn35248 if (source == NULL || target == NULL) { 9012712Snn35248 if (source != NULL) 9022712Snn35248 xmlFree(source); 9032712Snn35248 if (target != NULL) 9042712Snn35248 xmlFree(target); 9052712Snn35248 return (-1); 9062712Snn35248 } 9072712Snn35248 9082712Snn35248 ret = func(data, (char *)source, (char *)target); 9092712Snn35248 9102712Snn35248 xmlFree(source); 9112712Snn35248 xmlFree(target); 9122712Snn35248 9132712Snn35248 if (ret != 0) 9142712Snn35248 return (-1); 9152712Snn35248 } 9162712Snn35248 9172712Snn35248 return (0); 9182712Snn35248 } 9192712Snn35248 9202712Snn35248 /* 9212712Snn35248 * Iterate over platform devices 9222712Snn35248 * 9232712Snn35248 * Walks the platform, searching for <device> elements, calling the 9242712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure. 9252712Snn35248 */ 9262712Snn35248 int 9272727Sedp brand_platform_iter_devices(brand_handle_t bh, const char *zonename, 9283448Sdh155122 int (*func)(void *, const char *, const char *), void *data, 9293448Sdh155122 const char *curr_iptype) 9302712Snn35248 { 9312727Sedp struct brand_handle *bhp = (struct brand_handle *)bh; 9322727Sedp const char *curr_arch = get_curr_arch(); 9332727Sedp xmlNodePtr node; 9343448Sdh155122 xmlChar *match, *name, *arch, *iptype; 9352727Sedp char match_exp[MAXPATHLEN]; 9362727Sedp boolean_t err = B_FALSE; 9372727Sedp int ret = 0; 9382712Snn35248 9392712Snn35248 9402712Snn35248 assert(bhp != NULL); 9412712Snn35248 assert(zonename != NULL); 9422712Snn35248 assert(func != NULL); 9433448Sdh155122 assert(curr_iptype != NULL); 9442712Snn35248 9452712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL) 9462712Snn35248 return (-1); 9472712Snn35248 9482712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) { 9492712Snn35248 9502712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0) 9512712Snn35248 continue; 9522712Snn35248 9532712Snn35248 match = xmlGetProp(node, DTD_ATTR_MATCH); 9542712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME); 9552712Snn35248 arch = xmlGetProp(node, DTD_ATTR_ARCH); 9563448Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE); 9573448Sdh155122 if ((match == NULL) || (name == NULL) || (arch == NULL) || 9583448Sdh155122 (iptype == NULL)) { 9592712Snn35248 err = B_TRUE; 9602712Snn35248 goto next; 9612712Snn35248 } 9622712Snn35248 9632712Snn35248 /* check if the arch matches */ 9642712Snn35248 if ((strcmp((char *)arch, "all") != 0) && 9652712Snn35248 (strcmp((char *)arch, curr_arch) != 0)) 9662712Snn35248 goto next; 9672712Snn35248 9683448Sdh155122 /* check if the iptype matches */ 9693448Sdh155122 if ((strcmp((char *)iptype, "all") != 0) && 9703448Sdh155122 (strcmp((char *)iptype, curr_iptype) != 0)) 9713448Sdh155122 goto next; 9723448Sdh155122 9732712Snn35248 /* Substitute token values as needed. */ 9742712Snn35248 if ((ret = i_substitute_tokens((char *)match, 9752712Snn35248 match_exp, sizeof (match_exp), 9767089Sgjelinek zonename, NULL, NULL, NULL)) != 0) { 9772712Snn35248 err = B_TRUE; 9782712Snn35248 goto next; 9792712Snn35248 } 9802712Snn35248 9812712Snn35248 /* name might not be defined */ 9822712Snn35248 if (strlen((const char *)name) == 0) { 9832712Snn35248 xmlFree(name); 9842712Snn35248 name = NULL; 9852712Snn35248 } 9862712Snn35248 9872712Snn35248 /* invoke the callback */ 9882712Snn35248 ret = func(data, (const char *)match_exp, (const char *)name); 9892712Snn35248 9902712Snn35248 next: 9912712Snn35248 if (match != NULL) 9922712Snn35248 xmlFree(match); 9932712Snn35248 if (name != NULL) 9942712Snn35248 xmlFree(name); 9952712Snn35248 if (arch != NULL) 9962712Snn35248 xmlFree(arch); 9973448Sdh155122 if (iptype != NULL) 9983448Sdh155122 xmlFree(iptype); 9992712Snn35248 if (err) 10002712Snn35248 return (-1); 10012712Snn35248 if (ret != 0) 10022712Snn35248 return (-1); 10032712Snn35248 } 10042712Snn35248 10052712Snn35248 return (0); 10062712Snn35248 } 1007