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