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 /*
23*12582SGlenn.Faden@Sun.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
242712Snn35248 */
252712Snn35248
262712Snn35248 #include <assert.h>
272712Snn35248 #include <dirent.h>
282712Snn35248 #include <errno.h>
292712Snn35248 #include <fnmatch.h>
302712Snn35248 #include <signal.h>
312712Snn35248 #include <stdlib.h>
322712Snn35248 #include <unistd.h>
332712Snn35248 #include <strings.h>
342712Snn35248 #include <synch.h>
352712Snn35248 #include <sys/brand.h>
362712Snn35248 #include <sys/fcntl.h>
372712Snn35248 #include <sys/param.h>
382712Snn35248 #include <sys/stat.h>
392712Snn35248 #include <sys/systeminfo.h>
402712Snn35248 #include <sys/types.h>
412712Snn35248 #include <thread.h>
422712Snn35248 #include <zone.h>
432712Snn35248
442712Snn35248 #include <libbrand_impl.h>
452712Snn35248 #include <libbrand.h>
462712Snn35248
477089Sgjelinek #define DTD_ELEM_ATTACH ((const xmlChar *) "attach")
482712Snn35248 #define DTD_ELEM_BOOT ((const xmlChar *) "boot")
492712Snn35248 #define DTD_ELEM_BRAND ((const xmlChar *) "brand")
507089Sgjelinek #define DTD_ELEM_CLONE ((const xmlChar *) "clone")
512712Snn35248 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment")
527089Sgjelinek #define DTD_ELEM_DETACH ((const xmlChar *) "detach")
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")
6012578SGlenn.Faden@Sun.COM #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_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
brand_error_func(void * ctx,const char * msg,...)1052712Snn35248 brand_error_func(void *ctx, const char *msg, ...)
1062712Snn35248 {
1072712Snn35248 /*
1082712Snn35248 * Ignore error messages from libxml
1092712Snn35248 */
1102712Snn35248 }
1112712Snn35248
1122712Snn35248 static boolean_t
libbrand_initialize()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 */
14511411SSurya.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 *
get_curr_arch(void)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 *
get_curr_zone(void)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
open_xml_file(const char * file)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
brand_open(const char * name)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
brand_close(brand_handle_t bh)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
i_substitute_tokens(const char * sbuf,char * dbuf,int dbuf_size,const char * zonename,const char * zonepath,const char * username,const char * curr_zone)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
brand_get_value(struct brand_handle * bhp,const char * zonename,const char * zonepath,const char * username,const char * curr_zone,char * buf,size_t len,const xmlChar * tagname,boolean_t substitute,boolean_t optional)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
brand_get_attach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)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
brand_get_boot(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)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
brand_get_brandname(brand_handle_t bh,char * buf,size_t len)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
brand_get_clone(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)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
brand_get_detach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)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
brand_get_halt(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)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
brand_get_initname(brand_handle_t bh,char * buf,size_t len)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
brand_get_login_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)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
brand_get_forcedlogin_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)52312578SGlenn.Faden@Sun.COM brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username,
52412578SGlenn.Faden@Sun.COM char *buf, size_t len)
52512578SGlenn.Faden@Sun.COM {
52612578SGlenn.Faden@Sun.COM struct brand_handle *bhp = (struct brand_handle *)bh;
52712578SGlenn.Faden@Sun.COM const char *curr_zone = get_curr_zone();
52812578SGlenn.Faden@Sun.COM return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
52912578SGlenn.Faden@Sun.COM buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE));
53012578SGlenn.Faden@Sun.COM }
53112578SGlenn.Faden@Sun.COM
53212578SGlenn.Faden@Sun.COM int
brand_get_user_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)5334344Ssl108498 brand_get_user_cmd(brand_handle_t bh, const char *username,
5344344Ssl108498 char *buf, size_t len)
5354344Ssl108498 {
5364344Ssl108498 struct brand_handle *bhp = (struct brand_handle *)bh;
5374344Ssl108498
5384344Ssl108498 return (brand_get_value(bhp, NULL, NULL, username, NULL,
5397089Sgjelinek buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE));
5404344Ssl108498 }
5414344Ssl108498
5424344Ssl108498 int
brand_get_install(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)5432727Sedp brand_get_install(brand_handle_t bh, const char *zonename,
5447089Sgjelinek const char *zonepath, char *buf, size_t len)
5452712Snn35248 {
5462727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
5477089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
5487089Sgjelinek buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE));
5492712Snn35248 }
5502712Snn35248
5512712Snn35248 int
brand_get_installopts(brand_handle_t bh,char * buf,size_t len)5522727Sedp brand_get_installopts(brand_handle_t bh, char *buf, size_t len)
5532712Snn35248 {
5542727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
5552712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
5567089Sgjelinek buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE));
5572712Snn35248 }
5582712Snn35248
5592712Snn35248 int
brand_get_modname(brand_handle_t bh,char * buf,size_t len)5602727Sedp brand_get_modname(brand_handle_t bh, char *buf, size_t len)
5612712Snn35248 {
5622727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
5632712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
5647089Sgjelinek buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE));
5652712Snn35248 }
5662712Snn35248
5672712Snn35248 int
brand_get_postattach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)5684785Sgjelinek brand_get_postattach(brand_handle_t bh, const char *zonename,
5697089Sgjelinek const char *zonepath, char *buf, size_t len)
5704785Sgjelinek {
5714785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
5727089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
5737089Sgjelinek buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE));
5744785Sgjelinek }
5754785Sgjelinek
5764785Sgjelinek int
brand_get_postclone(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)5772727Sedp brand_get_postclone(brand_handle_t bh, const char *zonename,
5787089Sgjelinek const char *zonepath, char *buf, size_t len)
5792712Snn35248 {
5802727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
5817089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
5827089Sgjelinek buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE));
5832712Snn35248 }
5842712Snn35248
5852712Snn35248 int
brand_get_postinstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)5864586Sgjelinek brand_get_postinstall(brand_handle_t bh, const char *zonename,
5877089Sgjelinek const char *zonepath, char *buf, size_t len)
5884586Sgjelinek {
5894586Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
5907089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
5917089Sgjelinek buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE));
5927089Sgjelinek }
5937089Sgjelinek
5947089Sgjelinek int
brand_get_postsnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)5957089Sgjelinek brand_get_postsnap(brand_handle_t bh, const char *zonename,
5967089Sgjelinek const char *zonepath, char *buf, size_t len)
5977089Sgjelinek {
5987089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
5997089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6007089Sgjelinek buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE));
6014586Sgjelinek }
6024586Sgjelinek
6034586Sgjelinek int
brand_get_poststatechange(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6047370S<Gerald Jelinek> brand_get_poststatechange(brand_handle_t bh, const char *zonename,
6057370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len)
6067370S<Gerald Jelinek> {
6077370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh;
6087370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6097370S<Gerald Jelinek> buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE));
6107370S<Gerald Jelinek> }
6117370S<Gerald Jelinek>
6127370S<Gerald Jelinek> int
brand_get_predetach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6134785Sgjelinek brand_get_predetach(brand_handle_t bh, const char *zonename,
6147089Sgjelinek const char *zonepath, char *buf, size_t len)
6154785Sgjelinek {
6164785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
6177089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6187089Sgjelinek buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE));
6197089Sgjelinek }
6207089Sgjelinek
6217089Sgjelinek int
brand_get_presnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6227089Sgjelinek brand_get_presnap(brand_handle_t bh, const char *zonename,
6237089Sgjelinek const char *zonepath, char *buf, size_t len)
6247089Sgjelinek {
6257089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
6267089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6277089Sgjelinek buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE));
6284785Sgjelinek }
6294785Sgjelinek
6304785Sgjelinek int
brand_get_prestatechange(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6317370S<Gerald Jelinek> brand_get_prestatechange(brand_handle_t bh, const char *zonename,
6327370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len)
6337370S<Gerald Jelinek> {
6347370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh;
6357370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6367370S<Gerald Jelinek> buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE));
6377370S<Gerald Jelinek> }
6387370S<Gerald Jelinek>
6397370S<Gerald Jelinek> int
brand_get_preuninstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6404785Sgjelinek brand_get_preuninstall(brand_handle_t bh, const char *zonename,
6417089Sgjelinek const char *zonepath, char *buf, size_t len)
6427089Sgjelinek {
6437089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
6447089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6457089Sgjelinek buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE));
6467089Sgjelinek }
6477089Sgjelinek
6487089Sgjelinek int
brand_get_query(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6497370S<Gerald Jelinek> brand_get_query(brand_handle_t bh, const char *zonename,
6507370S<Gerald Jelinek> const char *zonepath, char *buf, size_t len)
6517370S<Gerald Jelinek> {
6527370S<Gerald Jelinek> struct brand_handle *bhp = (struct brand_handle *)bh;
6537370S<Gerald Jelinek> return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6547370S<Gerald Jelinek> buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE));
6557370S<Gerald Jelinek> }
6567370S<Gerald Jelinek>
6577370S<Gerald Jelinek> int
brand_get_uninstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6587089Sgjelinek brand_get_uninstall(brand_handle_t bh, const char *zonename,
6597089Sgjelinek const char *zonepath, char *buf, size_t len)
6604785Sgjelinek {
6614785Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
6627089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6637089Sgjelinek buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE));
6647089Sgjelinek }
6657089Sgjelinek
6667089Sgjelinek int
brand_get_validatesnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6677089Sgjelinek brand_get_validatesnap(brand_handle_t bh, const char *zonename,
6687089Sgjelinek const char *zonepath, char *buf, size_t len)
6697089Sgjelinek {
6707089Sgjelinek struct brand_handle *bhp = (struct brand_handle *)bh;
6717089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6727089Sgjelinek buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE));
6734785Sgjelinek }
6744785Sgjelinek
6754785Sgjelinek int
brand_get_verify_cfg(brand_handle_t bh,char * buf,size_t len)6762727Sedp brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len)
6772712Snn35248 {
6782727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
6792712Snn35248 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
6807089Sgjelinek buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE));
6812712Snn35248 }
6822712Snn35248
6832712Snn35248 int
brand_get_verify_adm(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)6842727Sedp brand_get_verify_adm(brand_handle_t bh, const char *zonename,
6857089Sgjelinek const char *zonepath, char *buf, size_t len)
6862712Snn35248 {
6872727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
6887089Sgjelinek return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
6897089Sgjelinek buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE));
6902712Snn35248 }
6912712Snn35248
6922712Snn35248 int
brand_get_sysboot(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)69310718SJordan.Vaughan@Sun.com brand_get_sysboot(brand_handle_t bh, const char *zonename,
69410718SJordan.Vaughan@Sun.com const char *zonepath, char *buf, size_t len)
69510718SJordan.Vaughan@Sun.com {
69610718SJordan.Vaughan@Sun.com struct brand_handle *bhp = (struct brand_handle *)bh;
69710718SJordan.Vaughan@Sun.com return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
69810718SJordan.Vaughan@Sun.com buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE));
69910718SJordan.Vaughan@Sun.com }
70010718SJordan.Vaughan@Sun.com
7013448Sdh155122 boolean_t
brand_allow_exclusive_ip(brand_handle_t bh)7023448Sdh155122 brand_allow_exclusive_ip(brand_handle_t bh)
7033448Sdh155122 {
7043448Sdh155122 struct brand_handle *bhp = (struct brand_handle *)bh;
7053448Sdh155122 xmlNodePtr node;
7063448Sdh155122 xmlChar *allow_excl;
7073448Sdh155122 boolean_t ret;
7083448Sdh155122
7093448Sdh155122 assert(bhp != NULL);
7103448Sdh155122
7113448Sdh155122 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
7123448Sdh155122 return (B_FALSE);
7133448Sdh155122
7143448Sdh155122 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL);
7153448Sdh155122 if (allow_excl == NULL)
7163448Sdh155122 return (B_FALSE);
7173448Sdh155122
7183448Sdh155122 /* Note: only return B_TRUE if it's "true" */
7193448Sdh155122 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0)
7203448Sdh155122 ret = B_TRUE;
7213448Sdh155122 else
7223448Sdh155122 ret = B_FALSE;
7233448Sdh155122
7243448Sdh155122 xmlFree(allow_excl);
7253448Sdh155122
7263448Sdh155122 return (ret);
7273448Sdh155122 }
7283448Sdh155122
7292712Snn35248 /*
7302712Snn35248 * Iterate over brand privileges
7312712Snn35248 *
7322712Snn35248 * Walks the brand config, searching for <privilege> elements, calling the
7332712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure.
7342712Snn35248 */
7352712Snn35248 int
brand_config_iter_privilege(brand_handle_t bh,int (* func)(void *,priv_iter_t *),void * data)7363673Sdh155122 brand_config_iter_privilege(brand_handle_t bh,
7373673Sdh155122 int (*func)(void *, priv_iter_t *), void *data)
7382712Snn35248 {
7392727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
7402712Snn35248 xmlNodePtr node;
7413673Sdh155122 xmlChar *name, *set, *iptype;
7423673Sdh155122 priv_iter_t priv_iter;
7432712Snn35248 int ret;
7442712Snn35248
7452712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
7462712Snn35248 return (-1);
7472712Snn35248
7482712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
7492712Snn35248
7502712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0)
7512712Snn35248 continue;
7522712Snn35248
7532712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME);
7542712Snn35248 set = xmlGetProp(node, DTD_ATTR_SET);
7553673Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
7562712Snn35248
7573673Sdh155122 if (name == NULL || set == NULL || iptype == NULL) {
7582712Snn35248 if (name != NULL)
7592712Snn35248 xmlFree(name);
7602712Snn35248 if (set != NULL)
7612712Snn35248 xmlFree(set);
7623673Sdh155122 if (iptype != NULL)
7633673Sdh155122 xmlFree(iptype);
7642712Snn35248 return (-1);
7652712Snn35248 }
7662712Snn35248
7673673Sdh155122 priv_iter.pi_name = (char *)name;
7683673Sdh155122 priv_iter.pi_set = (char *)set;
7693673Sdh155122 priv_iter.pi_iptype = (char *)iptype;
7703673Sdh155122
7713673Sdh155122 ret = func(data, &priv_iter);
7722712Snn35248
7732712Snn35248 xmlFree(name);
7742712Snn35248 xmlFree(set);
7753673Sdh155122 xmlFree(iptype);
7762712Snn35248
7772712Snn35248 if (ret != 0)
7782712Snn35248 return (-1);
7792712Snn35248 }
7802712Snn35248
7812712Snn35248 return (0);
7822712Snn35248 }
7832712Snn35248
7842712Snn35248 static int
i_brand_platform_iter_mounts(struct brand_handle * bhp,const char * zonepath,int (* func)(void *,const char *,const char *,const char *,const char *),void * data,const xmlChar * mount_type)7857089Sgjelinek i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonepath,
7862712Snn35248 int (*func)(void *, const char *, const char *, const char *,
7872712Snn35248 const char *), void *data, const xmlChar *mount_type)
7882712Snn35248 {
7892712Snn35248 xmlNodePtr node;
7902712Snn35248 xmlChar *special, *dir, *type, *opt;
7912712Snn35248 char special_exp[MAXPATHLEN];
7922712Snn35248 char opt_exp[MAXPATHLEN];
7932712Snn35248 int ret;
7942712Snn35248
7952712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
7962712Snn35248 return (-1);
7972712Snn35248
7982712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
7992712Snn35248
8002712Snn35248 if (xmlStrcmp(node->name, mount_type) != 0)
8012712Snn35248 continue;
8022712Snn35248
8032712Snn35248 special = xmlGetProp(node, DTD_ATTR_SPECIAL);
8042712Snn35248 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY);
8052712Snn35248 type = xmlGetProp(node, DTD_ATTR_TYPE);
8062712Snn35248 opt = xmlGetProp(node, DTD_ATTR_OPT);
8072712Snn35248 if ((special == NULL) || (dir == NULL) || (type == NULL) ||
8082712Snn35248 (opt == NULL)) {
8092712Snn35248 ret = -1;
8102712Snn35248 goto next;
8112712Snn35248 }
8122712Snn35248
8132712Snn35248 /* Substitute token values as needed. */
8142712Snn35248 if ((ret = i_substitute_tokens((char *)special,
8152712Snn35248 special_exp, sizeof (special_exp),
8167089Sgjelinek NULL, zonepath, NULL, NULL)) != 0)
8172712Snn35248 goto next;
8182712Snn35248
8192712Snn35248 /* opt might not be defined */
8202712Snn35248 if (strlen((const char *)opt) == 0) {
8212712Snn35248 xmlFree(opt);
8222712Snn35248 opt = NULL;
8232712Snn35248 } else {
8242712Snn35248 if ((ret = i_substitute_tokens((char *)opt,
8252712Snn35248 opt_exp, sizeof (opt_exp),
8267089Sgjelinek NULL, zonepath, NULL, NULL)) != 0)
8272712Snn35248 goto next;
8282712Snn35248 }
8292712Snn35248
8302712Snn35248 ret = func(data, (char *)special_exp, (char *)dir,
8312712Snn35248 (char *)type, ((opt != NULL) ? opt_exp : NULL));
8322712Snn35248
8332712Snn35248 next:
8342712Snn35248 if (special != NULL)
8352712Snn35248 xmlFree(special);
8362712Snn35248 if (dir != NULL)
8372712Snn35248 xmlFree(dir);
8382712Snn35248 if (type != NULL)
8392712Snn35248 xmlFree(type);
8402712Snn35248 if (opt != NULL)
8412712Snn35248 xmlFree(opt);
8422712Snn35248 if (ret != 0)
8432712Snn35248 return (-1);
8442712Snn35248 }
8452712Snn35248 return (0);
8462712Snn35248 }
8472712Snn35248
8482712Snn35248
8492712Snn35248 /*
8502712Snn35248 * Iterate over global platform filesystems
8512712Snn35248 *
8522712Snn35248 * Walks the platform, searching for <global_mount> elements, calling the
8532712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure.
8542712Snn35248 *
8552712Snn35248 * Perform the following substitutions as necessary:
8562712Snn35248 *
8577089Sgjelinek * %R Zonepath of zone
8582712Snn35248 */
8592712Snn35248 int
brand_platform_iter_gmounts(brand_handle_t bh,const char * zonepath,int (* func)(void *,const char *,const char *,const char *,const char *),void * data)8607089Sgjelinek brand_platform_iter_gmounts(brand_handle_t bh, const char *zonepath,
8612712Snn35248 int (*func)(void *, const char *, const char *, const char *,
8622712Snn35248 const char *), void *data)
8632712Snn35248 {
8642727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
8657089Sgjelinek return (i_brand_platform_iter_mounts(bhp, zonepath, func, data,
8662712Snn35248 DTD_ELEM_GLOBAL_MOUNT));
8672712Snn35248 }
8682712Snn35248
8692712Snn35248 /*
8702712Snn35248 * Iterate over non-global zone platform filesystems
8712712Snn35248 *
8722712Snn35248 * Walks the platform, searching for <mount> elements, calling the
8732712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure.
8742712Snn35248 */
8752712Snn35248 int
brand_platform_iter_mounts(brand_handle_t bh,int (* func)(void *,const char *,const char *,const char *,const char *),void * data)8762727Sedp brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *,
8772712Snn35248 const char *, const char *, const char *, const char *), void *data)
8782712Snn35248 {
8792727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
8802712Snn35248 return (i_brand_platform_iter_mounts(bhp, NULL, func, data,
8812712Snn35248 DTD_ELEM_MOUNT));
8822712Snn35248 }
8832712Snn35248
8842712Snn35248 /*
8852712Snn35248 * Iterate over platform symlinks
8862712Snn35248 *
8872712Snn35248 * Walks the platform, searching for <symlink> elements, calling the
8882712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure.
8892712Snn35248 */
8902712Snn35248 int
brand_platform_iter_link(brand_handle_t bh,int (* func)(void *,const char *,const char *),void * data)8912727Sedp brand_platform_iter_link(brand_handle_t bh,
8922712Snn35248 int (*func)(void *, const char *, const char *), void *data)
8932712Snn35248 {
8942727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
8952712Snn35248 xmlNodePtr node;
8962712Snn35248 xmlChar *source, *target;
8972712Snn35248 int ret;
8982712Snn35248
8992712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
9002712Snn35248 return (-1);
9012712Snn35248
9022712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
9032712Snn35248
9042712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0)
9052712Snn35248 continue;
9062712Snn35248
9072712Snn35248 source = xmlGetProp(node, DTD_ATTR_SOURCE);
9082712Snn35248 target = xmlGetProp(node, DTD_ATTR_TARGET);
9092712Snn35248
9102712Snn35248 if (source == NULL || target == NULL) {
9112712Snn35248 if (source != NULL)
9122712Snn35248 xmlFree(source);
9132712Snn35248 if (target != NULL)
9142712Snn35248 xmlFree(target);
9152712Snn35248 return (-1);
9162712Snn35248 }
9172712Snn35248
9182712Snn35248 ret = func(data, (char *)source, (char *)target);
9192712Snn35248
9202712Snn35248 xmlFree(source);
9212712Snn35248 xmlFree(target);
9222712Snn35248
9232712Snn35248 if (ret != 0)
9242712Snn35248 return (-1);
9252712Snn35248 }
9262712Snn35248
9272712Snn35248 return (0);
9282712Snn35248 }
9292712Snn35248
9302712Snn35248 /*
9312712Snn35248 * Iterate over platform devices
9322712Snn35248 *
9332712Snn35248 * Walks the platform, searching for <device> elements, calling the
9342712Snn35248 * specified callback for each. Returns 0 on success, or -1 on failure.
9352712Snn35248 */
9362712Snn35248 int
brand_platform_iter_devices(brand_handle_t bh,const char * zonename,int (* func)(void *,const char *,const char *),void * data,const char * curr_iptype)9372727Sedp brand_platform_iter_devices(brand_handle_t bh, const char *zonename,
9383448Sdh155122 int (*func)(void *, const char *, const char *), void *data,
9393448Sdh155122 const char *curr_iptype)
9402712Snn35248 {
9412727Sedp struct brand_handle *bhp = (struct brand_handle *)bh;
9422727Sedp const char *curr_arch = get_curr_arch();
9432727Sedp xmlNodePtr node;
9443448Sdh155122 xmlChar *match, *name, *arch, *iptype;
9452727Sedp char match_exp[MAXPATHLEN];
9462727Sedp boolean_t err = B_FALSE;
9472727Sedp int ret = 0;
9482712Snn35248
9492712Snn35248
9502712Snn35248 assert(bhp != NULL);
9512712Snn35248 assert(zonename != NULL);
9522712Snn35248 assert(func != NULL);
9533448Sdh155122 assert(curr_iptype != NULL);
9542712Snn35248
9552712Snn35248 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
9562712Snn35248 return (-1);
9572712Snn35248
9582712Snn35248 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
9592712Snn35248
9602712Snn35248 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0)
9612712Snn35248 continue;
9622712Snn35248
9632712Snn35248 match = xmlGetProp(node, DTD_ATTR_MATCH);
9642712Snn35248 name = xmlGetProp(node, DTD_ATTR_NAME);
9652712Snn35248 arch = xmlGetProp(node, DTD_ATTR_ARCH);
9663448Sdh155122 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
9673448Sdh155122 if ((match == NULL) || (name == NULL) || (arch == NULL) ||
9683448Sdh155122 (iptype == NULL)) {
9692712Snn35248 err = B_TRUE;
9702712Snn35248 goto next;
9712712Snn35248 }
9722712Snn35248
9732712Snn35248 /* check if the arch matches */
9742712Snn35248 if ((strcmp((char *)arch, "all") != 0) &&
9752712Snn35248 (strcmp((char *)arch, curr_arch) != 0))
9762712Snn35248 goto next;
9772712Snn35248
9783448Sdh155122 /* check if the iptype matches */
9793448Sdh155122 if ((strcmp((char *)iptype, "all") != 0) &&
9803448Sdh155122 (strcmp((char *)iptype, curr_iptype) != 0))
9813448Sdh155122 goto next;
9823448Sdh155122
9832712Snn35248 /* Substitute token values as needed. */
9842712Snn35248 if ((ret = i_substitute_tokens((char *)match,
9852712Snn35248 match_exp, sizeof (match_exp),
9867089Sgjelinek zonename, NULL, NULL, NULL)) != 0) {
9872712Snn35248 err = B_TRUE;
9882712Snn35248 goto next;
9892712Snn35248 }
9902712Snn35248
9912712Snn35248 /* name might not be defined */
9922712Snn35248 if (strlen((const char *)name) == 0) {
9932712Snn35248 xmlFree(name);
9942712Snn35248 name = NULL;
9952712Snn35248 }
9962712Snn35248
9972712Snn35248 /* invoke the callback */
9982712Snn35248 ret = func(data, (const char *)match_exp, (const char *)name);
9992712Snn35248
10002712Snn35248 next:
10012712Snn35248 if (match != NULL)
10022712Snn35248 xmlFree(match);
10032712Snn35248 if (name != NULL)
10042712Snn35248 xmlFree(name);
10052712Snn35248 if (arch != NULL)
10062712Snn35248 xmlFree(arch);
10073448Sdh155122 if (iptype != NULL)
10083448Sdh155122 xmlFree(iptype);
10092712Snn35248 if (err)
10102712Snn35248 return (-1);
10112712Snn35248 if (ret != 0)
10122712Snn35248 return (-1);
10132712Snn35248 }
10142712Snn35248
10152712Snn35248 return (0);
10162712Snn35248 }
1017