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