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