1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2015, Joyent, Inc.
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 #include <assert.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <fnmatch.h>
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <strings.h>
36 #include <synch.h>
37 #include <sys/brand.h>
38 #include <sys/fcntl.h>
39 #include <sys/param.h>
40 #include <sys/stat.h>
41 #include <sys/systeminfo.h>
42 #include <sys/types.h>
43 #include <thread.h>
44 #include <zone.h>
45
46 #include <libbrand_impl.h>
47 #include <libbrand.h>
48
49 #define DTD_ELEM_ATTACH ((const xmlChar *) "attach")
50 #define DTD_ELEM_BOOT ((const xmlChar *) "boot")
51 #define DTD_ELEM_BRAND ((const xmlChar *) "brand")
52 #define DTD_ELEM_CLONE ((const xmlChar *) "clone")
53 #define DTD_ELEM_COMMENT ((const xmlChar *) "comment")
54 #define DTD_ELEM_DETACH ((const xmlChar *) "detach")
55 #define DTD_ELEM_DEVICE ((const xmlChar *) "device")
56 #define DTD_ELEM_GLOBAL_MOUNT ((const xmlChar *) "global_mount")
57 #define DTD_ELEM_HALT ((const xmlChar *) "halt")
58 #define DTD_ELEM_INITNAME ((const xmlChar *) "initname")
59 #define DTD_ELEM_INSTALL ((const xmlChar *) "install")
60 #define DTD_ELEM_INSTALLOPTS ((const xmlChar *) "installopts")
61 #define DTD_ELEM_LOGIN_CMD ((const xmlChar *) "login_cmd")
62 #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd")
63 #define DTD_ELEM_MODNAME ((const xmlChar *) "modname")
64 #define DTD_ELEM_MOUNT ((const xmlChar *) "mount")
65 #define DTD_ELEM_RESTARTINIT ((const xmlChar *) "restartinit")
66 #define DTD_ELEM_RESTARTINIT0 ((const xmlChar *) "restartinit0")
67 #define DTD_ELEM_RESTARTINITREBOOT ((const xmlChar *) "restartinitreboot")
68 #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach")
69 #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone")
70 #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall")
71 #define DTD_ELEM_POSTSNAP ((const xmlChar *) "postsnap")
72 #define DTD_ELEM_POSTSTATECHG ((const xmlChar *) "poststatechange")
73 #define DTD_ELEM_PREDETACH ((const xmlChar *) "predetach")
74 #define DTD_ELEM_PRESNAP ((const xmlChar *) "presnap")
75 #define DTD_ELEM_PRESTATECHG ((const xmlChar *) "prestatechange")
76 #define DTD_ELEM_PREUNINSTALL ((const xmlChar *) "preuninstall")
77 #define DTD_ELEM_PRIVILEGE ((const xmlChar *) "privilege")
78 #define DTD_ELEM_QUERY ((const xmlChar *) "query")
79 #define DTD_ELEM_SECFLAGS ((const xmlChar *) "security-flags")
80 #define DTD_ELEM_SHUTDOWN ((const xmlChar *) "shutdown")
81 #define DTD_ELEM_SYMLINK ((const xmlChar *) "symlink")
82 #define DTD_ELEM_SYSBOOT ((const xmlChar *) "sysboot")
83 #define DTD_ELEM_UNINSTALL ((const xmlChar *) "uninstall")
84 #define DTD_ELEM_USER_CMD ((const xmlChar *) "user_cmd")
85 #define DTD_ELEM_VALIDSNAP ((const xmlChar *) "validatesnap")
86 #define DTD_ELEM_VERIFY_CFG ((const xmlChar *) "verify_cfg")
87 #define DTD_ELEM_VERIFY_ADM ((const xmlChar *) "verify_adm")
88
89 #define DTD_ATTR_ALLOWEXCL ((const xmlChar *) "allow-exclusive-ip")
90 #define DTD_ATTR_ARCH ((const xmlChar *) "arch")
91 #define DTD_ATTR_DIRECTORY ((const xmlChar *) "directory")
92 #define DTD_ATTR_IPTYPE ((const xmlChar *) "ip-type")
93 #define DTD_ATTR_MATCH ((const xmlChar *) "match")
94 #define DTD_ATTR_MODE ((const xmlChar *) "mode")
95 #define DTD_ATTR_NAME ((const xmlChar *) "name")
96 #define DTD_ATTR_OPT ((const xmlChar *) "opt")
97 #define DTD_ATTR_PATH ((const xmlChar *) "path")
98 #define DTD_ATTR_SET ((const xmlChar *) "set")
99 #define DTD_ATTR_SOURCE ((const xmlChar *) "source")
100 #define DTD_ATTR_SPECIAL ((const xmlChar *) "special")
101 #define DTD_ATTR_TARGET ((const xmlChar *) "target")
102 #define DTD_ATTR_TYPE ((const xmlChar *) "type")
103
104 #define DTD_ENTITY_TRUE "true"
105
106 static volatile boolean_t libbrand_initialized = B_FALSE;
107 static char i_curr_arch[MAXNAMELEN];
108 static char i_curr_zone[ZONENAME_MAX];
109
110 /*ARGSUSED*/
111 static void
brand_error_func(void * ctx,const char * msg,...)112 brand_error_func(void *ctx, const char *msg, ...)
113 {
114 /*
115 * Ignore error messages from libxml
116 */
117 }
118
119 static boolean_t
libbrand_initialize()120 libbrand_initialize()
121 {
122 static mutex_t initialize_lock = DEFAULTMUTEX;
123
124 (void) mutex_lock(&initialize_lock);
125
126 if (libbrand_initialized) {
127 (void) mutex_unlock(&initialize_lock);
128 return (B_TRUE);
129 }
130
131 if (sysinfo(SI_ARCHITECTURE, i_curr_arch, sizeof (i_curr_arch)) < 0) {
132 (void) mutex_unlock(&initialize_lock);
133 return (B_FALSE);
134 }
135
136 if (getzonenamebyid(getzoneid(), i_curr_zone,
137 sizeof (i_curr_zone)) < 0) {
138 (void) mutex_unlock(&initialize_lock);
139 return (B_FALSE);
140 }
141
142 xmlSetGenericErrorFunc(NULL, brand_error_func);
143
144 libbrand_initialized = B_TRUE;
145 (void) mutex_unlock(&initialize_lock);
146 return (B_TRUE);
147 }
148
149 static const char *
get_curr_arch(void)150 get_curr_arch(void)
151 {
152 if (!libbrand_initialize())
153 return (NULL);
154
155 return (i_curr_arch);
156 }
157
158 static const char *
get_curr_zone(void)159 get_curr_zone(void)
160 {
161 if (!libbrand_initialize())
162 return (NULL);
163
164 return (i_curr_zone);
165 }
166
167 /*
168 * Internal function to open an XML file
169 *
170 * Returns the XML doc pointer, or NULL on failure. It will validate the
171 * document, as well as removing any comments from the document structure.
172 */
173 static xmlDocPtr
open_xml_file(const char * file)174 open_xml_file(const char *file)
175 {
176 xmlDocPtr doc;
177 xmlValidCtxtPtr cvp;
178 int valid;
179
180 if (!libbrand_initialize())
181 return (NULL);
182
183 /*
184 * Parse the file
185 */
186 doc = xmlReadFile(file, NULL, XML_PARSE_DTDLOAD |
187 XML_PARSE_DTDVALID | XML_PARSE_NOBLANKS | XML_PARSE_NOWARNING);
188 if (doc == NULL)
189 return (NULL);
190
191 /*
192 * Validate the file
193 */
194 if ((cvp = xmlNewValidCtxt()) == NULL) {
195 xmlFreeDoc(doc);
196 return (NULL);
197 }
198 cvp->error = brand_error_func;
199 cvp->warning = brand_error_func;
200 valid = xmlValidateDocument(cvp, doc);
201 xmlFreeValidCtxt(cvp);
202 if (valid == 0) {
203 xmlFreeDoc(doc);
204 return (NULL);
205 }
206
207 return (doc);
208 }
209 /*
210 * Open a handle to the named brand.
211 *
212 * Returns a handle to the named brand, which is used for all subsequent brand
213 * interaction, or NULL if unable to open or initialize the brand.
214 */
215 brand_handle_t
brand_open(const char * name)216 brand_open(const char *name)
217 {
218 struct brand_handle *bhp;
219 char path[MAXPATHLEN];
220 xmlNodePtr node;
221 xmlChar *property;
222 struct stat statbuf;
223
224 /*
225 * Make sure brand name isn't too long
226 */
227 if (strlen(name) >= MAXNAMELEN)
228 return (NULL);
229
230 /*
231 * Check that the brand exists
232 */
233 (void) snprintf(path, sizeof (path), "%s/%s", BRAND_DIR, name);
234
235 if (stat(path, &statbuf) != 0)
236 return (NULL);
237
238 /*
239 * Allocate brand handle
240 */
241 if ((bhp = malloc(sizeof (struct brand_handle))) == NULL)
242 return (NULL);
243 bzero(bhp, sizeof (struct brand_handle));
244
245 (void) strcpy(bhp->bh_name, name);
246
247 /*
248 * Open the configuration file
249 */
250 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name,
251 BRAND_CONFIG);
252 if ((bhp->bh_config = open_xml_file(path)) == NULL) {
253 brand_close((brand_handle_t)bhp);
254 return (NULL);
255 }
256
257 /*
258 * Verify that the name of the brand matches the directory in which it
259 * is installed.
260 */
261 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL) {
262 brand_close((brand_handle_t)bhp);
263 return (NULL);
264 }
265
266 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0) {
267 brand_close((brand_handle_t)bhp);
268 return (NULL);
269 }
270
271 if ((property = xmlGetProp(node, DTD_ATTR_NAME)) == NULL) {
272 brand_close((brand_handle_t)bhp);
273 return (NULL);
274 }
275
276 if (strcmp((char *)property, name) != 0) {
277 xmlFree(property);
278 brand_close((brand_handle_t)bhp);
279 return (NULL);
280 }
281 xmlFree(property);
282
283 /*
284 * Open handle to platform configuration file.
285 */
286 (void) snprintf(path, sizeof (path), "%s/%s/%s", BRAND_DIR, name,
287 BRAND_PLATFORM);
288 if ((bhp->bh_platform = open_xml_file(path)) == NULL) {
289 brand_close((brand_handle_t)bhp);
290 return (NULL);
291 }
292
293 return ((brand_handle_t)bhp);
294 }
295
296 /*
297 * Closes the given brand handle
298 */
299 void
brand_close(brand_handle_t bh)300 brand_close(brand_handle_t bh)
301 {
302 struct brand_handle *bhp = (struct brand_handle *)bh;
303 if (bhp->bh_platform != NULL)
304 xmlFreeDoc(bhp->bh_platform);
305 if (bhp->bh_config != NULL)
306 xmlFreeDoc(bhp->bh_config);
307 free(bhp);
308 }
309
310 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)311 i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size,
312 const char *zonename, const char *zonepath, const char *username,
313 const char *curr_zone)
314 {
315 int dst, src;
316
317 /*
318 * Walk through the characters, substituting values as needed.
319 */
320 dbuf[0] = '\0';
321 dst = 0;
322 for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) {
323 if (sbuf[src] != '%') {
324 dbuf[dst++] = sbuf[src];
325 continue;
326 }
327
328 switch (sbuf[++src]) {
329 case '%':
330 dst += strlcpy(dbuf + dst, "%", dbuf_size - dst);
331 break;
332 case 'R':
333 if (zonepath == NULL)
334 break;
335 dst += strlcpy(dbuf + dst, zonepath, dbuf_size - dst);
336 break;
337 case 'u':
338 if (username == NULL)
339 break;
340 dst += strlcpy(dbuf + dst, username, dbuf_size - dst);
341 break;
342 case 'Z':
343 if (curr_zone == NULL)
344 break;
345 /* name of the zone we're running in */
346 dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst);
347 break;
348 case 'z':
349 /* name of the zone we're operating on */
350 if (zonename == NULL)
351 break;
352 dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst);
353 break;
354 }
355 }
356
357 if (dst >= dbuf_size)
358 return (-1);
359
360 dbuf[dst] = '\0';
361 return (0);
362 }
363
364 /*
365 * Retrieve the given tag from the brand.
366 * Perform the following substitutions as necessary:
367 *
368 * %% %
369 * %u Username
370 * %z Name of target zone
371 * %Z Name of current zone
372 * %R Zonepath of zone
373 *
374 * Returns 0 on success, -1 on failure.
375 */
376 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)377 brand_get_value(struct brand_handle *bhp, const char *zonename,
378 const char *zonepath, const char *username, const char *curr_zone,
379 char *buf, size_t len, const xmlChar *tagname,
380 boolean_t substitute, boolean_t optional)
381 {
382 xmlNodePtr node;
383 xmlChar *content;
384 int err = 0;
385
386 /*
387 * Retrieve the specified value from the XML doc
388 */
389 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
390 return (-1);
391
392 if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0)
393 return (-1);
394
395 for (node = node->xmlChildrenNode; node != NULL;
396 node = node->next) {
397 if (xmlStrcmp(node->name, tagname) == 0)
398 break;
399 }
400
401 if (node == NULL) {
402 if (optional) {
403 buf[0] = '\0';
404 return (0);
405 } else {
406 return (-1);
407 }
408 }
409
410 if ((content = xmlNodeGetContent(node)) == NULL)
411 return (-1);
412
413 if (strlen((char *)content) == 0) {
414 /*
415 * If the entry in the config file is empty, check to see
416 * whether this is an optional field. If so, we return the
417 * empty buffer. If not, we return an error.
418 */
419 if (optional) {
420 buf[0] = '\0';
421 } else {
422 err = -1;
423 }
424 } else {
425 /* Substitute token values as needed. */
426 if (substitute) {
427 if (i_substitute_tokens((char *)content, buf, len,
428 zonename, zonepath, username, curr_zone) != 0)
429 err = -1;
430 } else {
431 if (strlcpy(buf, (char *)content, len) >= len)
432 err = -1;
433 }
434 }
435
436 xmlFree(content);
437
438 return (err);
439 }
440
441 int
brand_get_attach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)442 brand_get_attach(brand_handle_t bh, const char *zonename,
443 const char *zonepath, char *buf, size_t len)
444 {
445 struct brand_handle *bhp = (struct brand_handle *)bh;
446 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
447 buf, len, DTD_ELEM_ATTACH, B_TRUE, B_TRUE));
448 }
449
450 int
brand_get_boot(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)451 brand_get_boot(brand_handle_t bh, const char *zonename,
452 const char *zonepath, char *buf, size_t len)
453 {
454 struct brand_handle *bhp = (struct brand_handle *)bh;
455 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
456 buf, len, DTD_ELEM_BOOT, B_TRUE, B_TRUE));
457 }
458
459 int
brand_get_brandname(brand_handle_t bh,char * buf,size_t len)460 brand_get_brandname(brand_handle_t bh, char *buf, size_t len)
461 {
462 struct brand_handle *bhp = (struct brand_handle *)bh;
463 if (len <= strlen(bhp->bh_name))
464 return (-1);
465
466 (void) strcpy(buf, bhp->bh_name);
467
468 return (0);
469 }
470
471 int
brand_get_clone(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)472 brand_get_clone(brand_handle_t bh, const char *zonename,
473 const char *zonepath, char *buf, size_t len)
474 {
475 struct brand_handle *bhp = (struct brand_handle *)bh;
476 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
477 buf, len, DTD_ELEM_CLONE, B_TRUE, B_TRUE));
478 }
479
480 int
brand_get_detach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)481 brand_get_detach(brand_handle_t bh, const char *zonename,
482 const char *zonepath, char *buf, size_t len)
483 {
484 struct brand_handle *bhp = (struct brand_handle *)bh;
485 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
486 buf, len, DTD_ELEM_DETACH, B_TRUE, B_TRUE));
487 }
488
489 int
brand_get_halt(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)490 brand_get_halt(brand_handle_t bh, const char *zonename,
491 const char *zonepath, char *buf, size_t len)
492 {
493 struct brand_handle *bhp = (struct brand_handle *)bh;
494 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
495 buf, len, DTD_ELEM_HALT, B_TRUE, B_TRUE));
496 }
497
498 int
brand_get_shutdown(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)499 brand_get_shutdown(brand_handle_t bh, const char *zonename,
500 const char *zonepath, char *buf, size_t len)
501 {
502 struct brand_handle *bhp = (struct brand_handle *)bh;
503 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
504 buf, len, DTD_ELEM_SHUTDOWN, B_TRUE, B_TRUE));
505 }
506
507 int
brand_get_initname(brand_handle_t bh,char * buf,size_t len)508 brand_get_initname(brand_handle_t bh, char *buf, size_t len)
509 {
510 struct brand_handle *bhp = (struct brand_handle *)bh;
511 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
512 buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE));
513 }
514
515 static boolean_t
i_brand_restartinit(brand_handle_t bh,const xmlChar * tagname,boolean_t deflt)516 i_brand_restartinit(brand_handle_t bh, const xmlChar *tagname, boolean_t deflt)
517 {
518 struct brand_handle *bhp = (struct brand_handle *)bh;
519 char val[80];
520
521 if (brand_get_value(bhp, NULL, NULL, NULL, NULL,
522 val, sizeof (val), tagname, B_FALSE, B_FALSE) != 0) {
523 return (deflt);
524 }
525
526 if (strcmp(val, "false") == 0)
527 return (B_FALSE);
528 return (B_TRUE);
529 }
530
531 boolean_t
brand_restartinit(brand_handle_t bh)532 brand_restartinit(brand_handle_t bh)
533 {
534 return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINIT, B_TRUE));
535 }
536
537 boolean_t
brand_restartinit0(brand_handle_t bh)538 brand_restartinit0(brand_handle_t bh)
539 {
540 return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINIT0, B_FALSE));
541 }
542
543 boolean_t
brand_restartinitreboot(brand_handle_t bh)544 brand_restartinitreboot(brand_handle_t bh)
545 {
546 return (i_brand_restartinit(bh, DTD_ELEM_RESTARTINITREBOOT, B_FALSE));
547 }
548
549 int
brand_get_login_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)550 brand_get_login_cmd(brand_handle_t bh, const char *username,
551 char *buf, size_t len)
552 {
553 struct brand_handle *bhp = (struct brand_handle *)bh;
554 const char *curr_zone = get_curr_zone();
555 return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
556 buf, len, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE));
557 }
558
559 int
brand_get_forcedlogin_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)560 brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username,
561 char *buf, size_t len)
562 {
563 struct brand_handle *bhp = (struct brand_handle *)bh;
564 const char *curr_zone = get_curr_zone();
565 return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
566 buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE));
567 }
568
569 int
brand_get_user_cmd(brand_handle_t bh,const char * username,char * buf,size_t len)570 brand_get_user_cmd(brand_handle_t bh, const char *username,
571 char *buf, size_t len)
572 {
573 struct brand_handle *bhp = (struct brand_handle *)bh;
574
575 return (brand_get_value(bhp, NULL, NULL, username, NULL,
576 buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE));
577 }
578
579 int
brand_get_install(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)580 brand_get_install(brand_handle_t bh, const char *zonename,
581 const char *zonepath, char *buf, size_t len)
582 {
583 struct brand_handle *bhp = (struct brand_handle *)bh;
584 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
585 buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE));
586 }
587
588 int
brand_get_installopts(brand_handle_t bh,char * buf,size_t len)589 brand_get_installopts(brand_handle_t bh, char *buf, size_t len)
590 {
591 struct brand_handle *bhp = (struct brand_handle *)bh;
592 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
593 buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE));
594 }
595
596 int
brand_get_modname(brand_handle_t bh,char * buf,size_t len)597 brand_get_modname(brand_handle_t bh, char *buf, size_t len)
598 {
599 struct brand_handle *bhp = (struct brand_handle *)bh;
600 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
601 buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE));
602 }
603
604 int
brand_get_postattach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)605 brand_get_postattach(brand_handle_t bh, const char *zonename,
606 const char *zonepath, char *buf, size_t len)
607 {
608 struct brand_handle *bhp = (struct brand_handle *)bh;
609 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
610 buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE));
611 }
612
613 int
brand_get_postclone(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)614 brand_get_postclone(brand_handle_t bh, const char *zonename,
615 const char *zonepath, char *buf, size_t len)
616 {
617 struct brand_handle *bhp = (struct brand_handle *)bh;
618 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
619 buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE));
620 }
621
622 int
brand_get_postinstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)623 brand_get_postinstall(brand_handle_t bh, const char *zonename,
624 const char *zonepath, char *buf, size_t len)
625 {
626 struct brand_handle *bhp = (struct brand_handle *)bh;
627 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
628 buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE));
629 }
630
631 int
brand_get_postsnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)632 brand_get_postsnap(brand_handle_t bh, const char *zonename,
633 const char *zonepath, char *buf, size_t len)
634 {
635 struct brand_handle *bhp = (struct brand_handle *)bh;
636 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
637 buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE));
638 }
639
640 int
brand_get_poststatechange(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)641 brand_get_poststatechange(brand_handle_t bh, const char *zonename,
642 const char *zonepath, char *buf, size_t len)
643 {
644 struct brand_handle *bhp = (struct brand_handle *)bh;
645 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
646 buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE));
647 }
648
649 int
brand_get_predetach(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)650 brand_get_predetach(brand_handle_t bh, const char *zonename,
651 const char *zonepath, char *buf, size_t len)
652 {
653 struct brand_handle *bhp = (struct brand_handle *)bh;
654 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
655 buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE));
656 }
657
658 int
brand_get_presnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)659 brand_get_presnap(brand_handle_t bh, const char *zonename,
660 const char *zonepath, char *buf, size_t len)
661 {
662 struct brand_handle *bhp = (struct brand_handle *)bh;
663 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
664 buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE));
665 }
666
667 int
brand_get_prestatechange(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)668 brand_get_prestatechange(brand_handle_t bh, const char *zonename,
669 const char *zonepath, char *buf, size_t len)
670 {
671 struct brand_handle *bhp = (struct brand_handle *)bh;
672 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
673 buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE));
674 }
675
676 int
brand_get_preuninstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)677 brand_get_preuninstall(brand_handle_t bh, const char *zonename,
678 const char *zonepath, char *buf, size_t len)
679 {
680 struct brand_handle *bhp = (struct brand_handle *)bh;
681 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
682 buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE));
683 }
684
685 int
brand_get_query(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)686 brand_get_query(brand_handle_t bh, const char *zonename,
687 const char *zonepath, char *buf, size_t len)
688 {
689 struct brand_handle *bhp = (struct brand_handle *)bh;
690 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
691 buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE));
692 }
693
694 int
brand_get_secflags(brand_handle_t bh,char * buf,size_t len)695 brand_get_secflags(brand_handle_t bh, char *buf, size_t len)
696 {
697 struct brand_handle *bhp = (struct brand_handle *)bh;
698 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
699 buf, len, DTD_ELEM_SECFLAGS, B_FALSE, B_TRUE));
700 }
701
702 int
brand_get_uninstall(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)703 brand_get_uninstall(brand_handle_t bh, const char *zonename,
704 const char *zonepath, char *buf, size_t len)
705 {
706 struct brand_handle *bhp = (struct brand_handle *)bh;
707 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
708 buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE));
709 }
710
711 int
brand_get_validatesnap(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)712 brand_get_validatesnap(brand_handle_t bh, const char *zonename,
713 const char *zonepath, char *buf, size_t len)
714 {
715 struct brand_handle *bhp = (struct brand_handle *)bh;
716 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
717 buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE));
718 }
719
720 int
brand_get_verify_cfg(brand_handle_t bh,char * buf,size_t len)721 brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len)
722 {
723 struct brand_handle *bhp = (struct brand_handle *)bh;
724 return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
725 buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE));
726 }
727
728 int
brand_get_verify_adm(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)729 brand_get_verify_adm(brand_handle_t bh, const char *zonename,
730 const char *zonepath, char *buf, size_t len)
731 {
732 struct brand_handle *bhp = (struct brand_handle *)bh;
733 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
734 buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE));
735 }
736
737 int
brand_get_sysboot(brand_handle_t bh,const char * zonename,const char * zonepath,char * buf,size_t len)738 brand_get_sysboot(brand_handle_t bh, const char *zonename,
739 const char *zonepath, char *buf, size_t len)
740 {
741 struct brand_handle *bhp = (struct brand_handle *)bh;
742 return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
743 buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE));
744 }
745
746 boolean_t
brand_allow_exclusive_ip(brand_handle_t bh)747 brand_allow_exclusive_ip(brand_handle_t bh)
748 {
749 struct brand_handle *bhp = (struct brand_handle *)bh;
750 xmlNodePtr node;
751 xmlChar *allow_excl;
752 boolean_t ret;
753
754 assert(bhp != NULL);
755
756 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
757 return (B_FALSE);
758
759 allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL);
760 if (allow_excl == NULL)
761 return (B_FALSE);
762
763 /* Note: only return B_TRUE if it's "true" */
764 if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0)
765 ret = B_TRUE;
766 else
767 ret = B_FALSE;
768
769 xmlFree(allow_excl);
770
771 return (ret);
772 }
773
774 /*
775 * Iterate over brand privileges
776 *
777 * Walks the brand config, searching for <privilege> elements, calling the
778 * specified callback for each. Returns 0 on success, or -1 on failure.
779 */
780 int
brand_config_iter_privilege(brand_handle_t bh,int (* func)(void *,priv_iter_t *),void * data)781 brand_config_iter_privilege(brand_handle_t bh,
782 int (*func)(void *, priv_iter_t *), void *data)
783 {
784 struct brand_handle *bhp = (struct brand_handle *)bh;
785 xmlNodePtr node;
786 xmlChar *name, *set, *iptype;
787 priv_iter_t priv_iter;
788 int ret;
789
790 if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
791 return (-1);
792
793 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
794
795 if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0)
796 continue;
797
798 name = xmlGetProp(node, DTD_ATTR_NAME);
799 set = xmlGetProp(node, DTD_ATTR_SET);
800 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
801
802 if (name == NULL || set == NULL || iptype == NULL) {
803 if (name != NULL)
804 xmlFree(name);
805 if (set != NULL)
806 xmlFree(set);
807 if (iptype != NULL)
808 xmlFree(iptype);
809 return (-1);
810 }
811
812 priv_iter.pi_name = (char *)name;
813 priv_iter.pi_set = (char *)set;
814 priv_iter.pi_iptype = (char *)iptype;
815
816 ret = func(data, &priv_iter);
817
818 xmlFree(name);
819 xmlFree(set);
820 xmlFree(iptype);
821
822 if (ret != 0)
823 return (-1);
824 }
825
826 return (0);
827 }
828
829 static int
i_brand_platform_iter_mounts(struct brand_handle * bhp,const char * zonename,const char * zonepath,int (* func)(void *,const char *,const char *,const char *,const char *),void * data,const xmlChar * mount_type)830 i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonename,
831 const char *zonepath, int (*func)(void *, const char *, const char *,
832 const char *, const char *), void *data, const xmlChar *mount_type)
833 {
834 xmlNodePtr node;
835 xmlChar *special, *dir, *type, *opt;
836 char special_exp[MAXPATHLEN];
837 char opt_exp[MAXPATHLEN];
838 int ret;
839
840 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
841 return (-1);
842
843 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
844
845 if (xmlStrcmp(node->name, mount_type) != 0)
846 continue;
847
848 special = xmlGetProp(node, DTD_ATTR_SPECIAL);
849 dir = xmlGetProp(node, DTD_ATTR_DIRECTORY);
850 type = xmlGetProp(node, DTD_ATTR_TYPE);
851 opt = xmlGetProp(node, DTD_ATTR_OPT);
852 if ((special == NULL) || (dir == NULL) || (type == NULL) ||
853 (opt == NULL)) {
854 ret = -1;
855 goto next;
856 }
857
858 /* Substitute token values as needed. */
859 if ((ret = i_substitute_tokens((char *)special,
860 special_exp, sizeof (special_exp),
861 zonename, zonepath, NULL, NULL)) != 0)
862 goto next;
863
864 /* opt might not be defined */
865 if (strlen((const char *)opt) == 0) {
866 xmlFree(opt);
867 opt = NULL;
868 } else {
869 if ((ret = i_substitute_tokens((char *)opt,
870 opt_exp, sizeof (opt_exp),
871 zonename, zonepath, NULL, NULL)) != 0)
872 goto next;
873 }
874
875 ret = func(data, (char *)special_exp, (char *)dir,
876 (char *)type, ((opt != NULL) ? opt_exp : NULL));
877
878 next:
879 if (special != NULL)
880 xmlFree(special);
881 if (dir != NULL)
882 xmlFree(dir);
883 if (type != NULL)
884 xmlFree(type);
885 if (opt != NULL)
886 xmlFree(opt);
887 if (ret != 0)
888 return (-1);
889 }
890 return (0);
891 }
892
893
894 /*
895 * Iterate over global platform filesystems
896 *
897 * Walks the platform, searching for <global_mount> elements, calling the
898 * specified callback for each. Returns 0 on success, or -1 on failure.
899 *
900 * Perform the following substitutions as necessary:
901 *
902 * %R Zonepath of zone
903 */
904 int
brand_platform_iter_gmounts(brand_handle_t bh,const char * zonename,const char * zonepath,int (* func)(void *,const char *,const char *,const char *,const char *),void * data)905 brand_platform_iter_gmounts(brand_handle_t bh, const char *zonename,
906 const char *zonepath, int (*func)(void *, const char *, const char *,
907 const char *, const char *), void *data)
908 {
909 struct brand_handle *bhp = (struct brand_handle *)bh;
910 return (i_brand_platform_iter_mounts(bhp, zonename, zonepath, func,
911 data, DTD_ELEM_GLOBAL_MOUNT));
912 }
913
914 /*
915 * Iterate over non-global zone platform filesystems
916 *
917 * Walks the platform, searching for <mount> elements, calling the
918 * specified callback for each. Returns 0 on success, or -1 on failure.
919 */
920 int
brand_platform_iter_mounts(brand_handle_t bh,int (* func)(void *,const char *,const char *,const char *,const char *),void * data)921 brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *,
922 const char *, const char *, const char *, const char *), void *data)
923 {
924 struct brand_handle *bhp = (struct brand_handle *)bh;
925 return (i_brand_platform_iter_mounts(bhp, NULL, NULL, func, data,
926 DTD_ELEM_MOUNT));
927 }
928
929 /*
930 * Iterate over platform symlinks
931 *
932 * Walks the platform, searching for <symlink> elements, calling the
933 * specified callback for each. Returns 0 on success, or -1 on failure.
934 */
935 int
brand_platform_iter_link(brand_handle_t bh,int (* func)(void *,const char *,const char *),void * data)936 brand_platform_iter_link(brand_handle_t bh,
937 int (*func)(void *, const char *, const char *), void *data)
938 {
939 struct brand_handle *bhp = (struct brand_handle *)bh;
940 xmlNodePtr node;
941 xmlChar *source, *target;
942 int ret;
943
944 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
945 return (-1);
946
947 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
948
949 if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0)
950 continue;
951
952 source = xmlGetProp(node, DTD_ATTR_SOURCE);
953 target = xmlGetProp(node, DTD_ATTR_TARGET);
954
955 if (source == NULL || target == NULL) {
956 if (source != NULL)
957 xmlFree(source);
958 if (target != NULL)
959 xmlFree(target);
960 return (-1);
961 }
962
963 ret = func(data, (char *)source, (char *)target);
964
965 xmlFree(source);
966 xmlFree(target);
967
968 if (ret != 0)
969 return (-1);
970 }
971
972 return (0);
973 }
974
975 /*
976 * Iterate over platform devices
977 *
978 * Walks the platform, searching for <device> elements, calling the
979 * specified callback for each. Returns 0 on success, or -1 on failure.
980 */
981 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)982 brand_platform_iter_devices(brand_handle_t bh, const char *zonename,
983 int (*func)(void *, const char *, const char *), void *data,
984 const char *curr_iptype)
985 {
986 struct brand_handle *bhp = (struct brand_handle *)bh;
987 const char *curr_arch = get_curr_arch();
988 xmlNodePtr node;
989 xmlChar *match, *name, *arch, *iptype;
990 char match_exp[MAXPATHLEN];
991 boolean_t err = B_FALSE;
992 int ret = 0;
993
994
995 assert(bhp != NULL);
996 assert(zonename != NULL);
997 assert(func != NULL);
998 assert(curr_iptype != NULL);
999
1000 if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
1001 return (-1);
1002
1003 for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
1004
1005 if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0)
1006 continue;
1007
1008 match = xmlGetProp(node, DTD_ATTR_MATCH);
1009 name = xmlGetProp(node, DTD_ATTR_NAME);
1010 arch = xmlGetProp(node, DTD_ATTR_ARCH);
1011 iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
1012 if ((match == NULL) || (name == NULL) || (arch == NULL) ||
1013 (iptype == NULL)) {
1014 err = B_TRUE;
1015 goto next;
1016 }
1017
1018 /* check if the arch matches */
1019 if ((strcmp((char *)arch, "all") != 0) &&
1020 (strcmp((char *)arch, curr_arch) != 0))
1021 goto next;
1022
1023 /* check if the iptype matches */
1024 if ((strcmp((char *)iptype, "all") != 0) &&
1025 (strcmp((char *)iptype, curr_iptype) != 0))
1026 goto next;
1027
1028 /* Substitute token values as needed. */
1029 if ((ret = i_substitute_tokens((char *)match,
1030 match_exp, sizeof (match_exp),
1031 zonename, NULL, NULL, NULL)) != 0) {
1032 err = B_TRUE;
1033 goto next;
1034 }
1035
1036 /* name might not be defined */
1037 if (strlen((const char *)name) == 0) {
1038 xmlFree(name);
1039 name = NULL;
1040 }
1041
1042 /* invoke the callback */
1043 ret = func(data, (const char *)match_exp, (const char *)name);
1044
1045 next:
1046 if (match != NULL)
1047 xmlFree(match);
1048 if (name != NULL)
1049 xmlFree(name);
1050 if (arch != NULL)
1051 xmlFree(arch);
1052 if (iptype != NULL)
1053 xmlFree(iptype);
1054 if (err)
1055 return (-1);
1056 if (ret != 0)
1057 return (-1);
1058 }
1059
1060 return (0);
1061 }
1062