Print this page
    
    
      
        | 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)
  
    | 
      ↓ open down ↓ | 
    315 lines elided | 
    
      ↑ open up ↑ | 
  
 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      -        static char *env_pool = NULL;
 327  326  
 328  327          /*
 329  328           * Walk through the characters, substituting values as needed.
 330  329           */
 331  330          dbuf[0] = '\0';
 332  331          dst = 0;
 333  332          for (src = 0; src < strlen((char *)sbuf) && dst < dbuf_size; src++) {
 334  333                  if (sbuf[src] != '%') {
 335  334                          dbuf[dst++] = sbuf[src];
 336  335                          continue;
 337  336                  }
 338  337  
 339  338                  switch (sbuf[++src]) {
 340  339                  case '%':
 341  340                          dst += strlcpy(dbuf + dst, "%", dbuf_size - dst);
 342  341                          break;
 343      -                case 'P':
 344      -                        if (env_pool == NULL)
 345      -                                env_pool = getenv("_ZONEADMD_ZPOOL");
 346      -                        if (env_pool == NULL)
 347      -                                break;
 348      -                        dst += strlcpy(dbuf + dst, env_pool, dbuf_size - dst);
 349      -                        break;
 350  342                  case 'R':
 351  343                          if (zonepath == NULL)
 352  344                                  break;
 353  345                          dst += strlcpy(dbuf + dst, zonepath, dbuf_size - dst);
 354  346                          break;
 355  347                  case 'u':
 356  348                          if (username == NULL)
 357  349                                  break;
 358  350                          dst += strlcpy(dbuf + dst, username, dbuf_size - dst);
 359  351                          break;
 360  352                  case 'Z':
 361  353                          if (curr_zone == NULL)
 362  354                                  break;
 363  355                          /* name of the zone we're running in */
 364  356                          dst += strlcpy(dbuf + dst, curr_zone, dbuf_size - dst);
 365  357                          break;
 366  358                  case 'z':
 367  359                          /* name of the zone we're operating on */
 368  360                          if (zonename == NULL)
 369  361                                  break;
 370  362                          dst += strlcpy(dbuf + dst, zonename, dbuf_size - dst);
 371  363                          break;
 372  364                  }
 373  365          }
 374  366  
 375  367          if (dst >= dbuf_size)
 376  368                  return (-1);
 377  369  
 378  370          dbuf[dst] = '\0';
 379  371          return (0);
 380  372  }
 381  373  
 382  374  /*
 383  375   * Retrieve the given tag from the brand.
 384  376   * Perform the following substitutions as necessary:
 385  377   *
 386  378   *      %%      %
 387  379   *      %u      Username
 388  380   *      %z      Name of target zone
 389  381   *      %Z      Name of current zone
 390  382   *      %R      Zonepath of zone
 391  383   *
 392  384   * Returns 0 on success, -1 on failure.
 393  385   */
 394  386  static int
 395  387  brand_get_value(struct brand_handle *bhp, const char *zonename,
 396  388      const char *zonepath, const char *username, const char *curr_zone,
 397  389      char *buf, size_t len, const xmlChar *tagname,
 398  390      boolean_t substitute, boolean_t optional)
 399  391  {
 400  392          xmlNodePtr node;
 401  393          xmlChar *content;
 402  394          int err = 0;
 403  395  
 404  396          /*
 405  397           * Retrieve the specified value from the XML doc
 406  398           */
 407  399          if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
 408  400                  return (-1);
 409  401  
 410  402          if (xmlStrcmp(node->name, DTD_ELEM_BRAND) != 0)
 411  403                  return (-1);
 412  404  
 413  405          for (node = node->xmlChildrenNode; node != NULL;
 414  406              node = node->next) {
 415  407                  if (xmlStrcmp(node->name, tagname) == 0)
 416  408                          break;
 417  409          }
 418  410  
 419  411          if (node == NULL) {
 420  412                  if (optional) {
 421  413                          buf[0] = '\0';
 422  414                          return (0);
 423  415                  } else {
 424  416                          return (-1);
 425  417                  }
 426  418          }
 427  419  
 428  420          if ((content = xmlNodeGetContent(node)) == NULL)
 429  421                  return (-1);
 430  422  
 431  423          if (strlen((char *)content) == 0) {
 432  424                  /*
 433  425                   * If the entry in the config file is empty, check to see
 434  426                   * whether this is an optional field.  If so, we return the
 435  427                   * empty buffer.  If not, we return an error.
 436  428                   */
 437  429                  if (optional) {
 438  430                          buf[0] = '\0';
 439  431                  } else {
 440  432                          err = -1;
 441  433                  }
 442  434          } else {
 443  435                  /* Substitute token values as needed. */
 444  436                  if (substitute) {
 445  437                          if (i_substitute_tokens((char *)content, buf, len,
 446  438                              zonename, zonepath, username, curr_zone) != 0)
 447  439                                  err = -1;
 448  440                  } else {
 449  441                          if (strlcpy(buf, (char *)content, len) >= len)
 450  442                                  err = -1;
 451  443                  }
 452  444          }
 453  445  
 454  446          xmlFree(content);
 455  447  
 456  448          return (err);
 457  449  }
 458  450  
 459  451  int
 460  452  brand_get_attach(brand_handle_t bh, const char *zonename,
 461  453      const char *zonepath, char *buf, size_t len)
 462  454  {
 463  455          struct brand_handle *bhp = (struct brand_handle *)bh;
 464  456          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 465  457              buf, len, DTD_ELEM_ATTACH, B_TRUE, B_TRUE));
 466  458  }
 467  459  
 468  460  int
 469  461  brand_get_boot(brand_handle_t bh, const char *zonename,
 470  462      const char *zonepath, char *buf, size_t len)
 471  463  {
 472  464          struct brand_handle *bhp = (struct brand_handle *)bh;
 473  465          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 474  466              buf, len, DTD_ELEM_BOOT, B_TRUE, B_TRUE));
 475  467  }
 476  468  
 477  469  int
 478  470  brand_get_brandname(brand_handle_t bh, char *buf, size_t len)
 479  471  {
 480  472          struct brand_handle *bhp = (struct brand_handle *)bh;
 481  473          if (len <= strlen(bhp->bh_name))
 482  474                  return (-1);
 483  475  
 484  476          (void) strcpy(buf, bhp->bh_name);
 485  477  
 486  478          return (0);
 487  479  }
 488  480  
 489  481  int
 490  482  brand_get_clone(brand_handle_t bh, const char *zonename,
 491  483      const char *zonepath, char *buf, size_t len)
 492  484  {
 493  485          struct brand_handle *bhp = (struct brand_handle *)bh;
 494  486          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 495  487              buf, len, DTD_ELEM_CLONE, B_TRUE, B_TRUE));
 496  488  }
 497  489  
 498  490  int
 499  491  brand_get_detach(brand_handle_t bh, const char *zonename,
 500  492      const char *zonepath, char *buf, size_t len)
 501  493  {
 502  494          struct brand_handle *bhp = (struct brand_handle *)bh;
 503  495          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 504  496              buf, len, DTD_ELEM_DETACH, B_TRUE, B_TRUE));
 505  497  }
 506  498  
 507  499  int
 508  500  brand_get_halt(brand_handle_t bh, const char *zonename,
 509  501      const char *zonepath, char *buf, size_t len)
 510  502  {
 511  503          struct brand_handle *bhp = (struct brand_handle *)bh;
 512  504          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 513  505              buf, len, DTD_ELEM_HALT, B_TRUE, B_TRUE));
 514  506  }
 515  507  
 516  508  int
 517  509  brand_get_shutdown(brand_handle_t bh, const char *zonename,
 518  510      const char *zonepath, char *buf, size_t len)
 519  511  {
 520  512          struct brand_handle *bhp = (struct brand_handle *)bh;
 521  513          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 522  514              buf, len, DTD_ELEM_SHUTDOWN, B_TRUE, B_TRUE));
 523  515  }
 524  516  
 525  517  int
 526  518  brand_get_initname(brand_handle_t bh, char *buf, size_t len)
 527  519  {
 528  520          struct brand_handle *bhp = (struct brand_handle *)bh;
 529  521          return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
 530  522              buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE));
 531  523  }
 532  524  
 533  525  boolean_t
 534  526  brand_restartinit(brand_handle_t bh)
 535  527  {
 536  528          struct brand_handle *bhp = (struct brand_handle *)bh;
 537  529          char val[80];
 538  530  
 539  531          if (brand_get_value(bhp, NULL, NULL, NULL, NULL,
 540  532              val, sizeof (val), DTD_ELEM_RESTARTINIT, B_FALSE, B_FALSE) != 0)
 541  533                  return (B_TRUE);
 542  534  
 543  535          if (strcmp(val, "false") == 0)
 544  536                  return (B_FALSE);
 545  537          return (B_TRUE);
 546  538  }
 547  539  
 548  540  int
 549  541  brand_get_login_cmd(brand_handle_t bh, const char *username,
 550  542      char *buf, size_t len)
 551  543  {
 552  544          struct brand_handle *bhp = (struct brand_handle *)bh;
 553  545          const char *curr_zone = get_curr_zone();
 554  546          return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
 555  547              buf, len, DTD_ELEM_LOGIN_CMD, B_TRUE, B_FALSE));
 556  548  }
 557  549  
 558  550  int
 559  551  brand_get_forcedlogin_cmd(brand_handle_t bh, const char *username,
 560  552      char *buf, size_t len)
 561  553  {
 562  554          struct brand_handle *bhp = (struct brand_handle *)bh;
 563  555          const char *curr_zone = get_curr_zone();
 564  556          return (brand_get_value(bhp, NULL, NULL, username, curr_zone,
 565  557              buf, len, DTD_ELEM_FORCELOGIN_CMD, B_TRUE, B_FALSE));
 566  558  }
 567  559  
 568  560  int
 569  561  brand_get_user_cmd(brand_handle_t bh, const char *username,
 570  562      char *buf, size_t len)
 571  563  {
 572  564          struct brand_handle *bhp = (struct brand_handle *)bh;
 573  565  
 574  566          return (brand_get_value(bhp, NULL, NULL, username, NULL,
 575  567              buf, len, DTD_ELEM_USER_CMD, B_TRUE, B_FALSE));
 576  568  }
 577  569  
 578  570  int
 579  571  brand_get_install(brand_handle_t bh, const char *zonename,
 580  572      const char *zonepath, char *buf, size_t len)
 581  573  {
 582  574          struct brand_handle *bhp = (struct brand_handle *)bh;
 583  575          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 584  576              buf, len, DTD_ELEM_INSTALL, B_TRUE, B_FALSE));
 585  577  }
 586  578  
 587  579  int
 588  580  brand_get_installopts(brand_handle_t bh, char *buf, size_t len)
 589  581  {
 590  582          struct brand_handle *bhp = (struct brand_handle *)bh;
 591  583          return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
 592  584              buf, len, DTD_ELEM_INSTALLOPTS, B_FALSE, B_TRUE));
 593  585  }
 594  586  
 595  587  int
 596  588  brand_get_modname(brand_handle_t bh, char *buf, size_t len)
 597  589  {
 598  590          struct brand_handle *bhp = (struct brand_handle *)bh;
 599  591          return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
 600  592              buf, len, DTD_ELEM_MODNAME, B_FALSE, B_TRUE));
 601  593  }
 602  594  
 603  595  int
 604  596  brand_get_postattach(brand_handle_t bh, const char *zonename,
 605  597      const char *zonepath, char *buf, size_t len)
 606  598  {
 607  599          struct brand_handle *bhp = (struct brand_handle *)bh;
 608  600          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 609  601              buf, len, DTD_ELEM_POSTATTACH, B_TRUE, B_TRUE));
 610  602  }
 611  603  
 612  604  int
 613  605  brand_get_postclone(brand_handle_t bh, const char *zonename,
 614  606      const char *zonepath, char *buf, size_t len)
 615  607  {
 616  608          struct brand_handle *bhp = (struct brand_handle *)bh;
 617  609          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 618  610              buf, len, DTD_ELEM_POSTCLONE, B_TRUE, B_TRUE));
 619  611  }
 620  612  
 621  613  int
 622  614  brand_get_postinstall(brand_handle_t bh, const char *zonename,
 623  615      const char *zonepath, char *buf, size_t len)
 624  616  {
 625  617          struct brand_handle *bhp = (struct brand_handle *)bh;
 626  618          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 627  619              buf, len, DTD_ELEM_POSTINSTALL, B_TRUE, B_TRUE));
 628  620  }
 629  621  
 630  622  int
 631  623  brand_get_postsnap(brand_handle_t bh, const char *zonename,
 632  624      const char *zonepath, char *buf, size_t len)
 633  625  {
 634  626          struct brand_handle *bhp = (struct brand_handle *)bh;
 635  627          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 636  628              buf, len, DTD_ELEM_POSTSNAP, B_TRUE, B_TRUE));
 637  629  }
 638  630  
 639  631  int
 640  632  brand_get_poststatechange(brand_handle_t bh, const char *zonename,
 641  633      const char *zonepath, char *buf, size_t len)
 642  634  {
 643  635          struct brand_handle *bhp = (struct brand_handle *)bh;
 644  636          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 645  637              buf, len, DTD_ELEM_POSTSTATECHG, B_TRUE, B_TRUE));
 646  638  }
 647  639  
 648  640  int
 649  641  brand_get_predetach(brand_handle_t bh, const char *zonename,
 650  642      const char *zonepath, char *buf, size_t len)
 651  643  {
 652  644          struct brand_handle *bhp = (struct brand_handle *)bh;
 653  645          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 654  646              buf, len, DTD_ELEM_PREDETACH, B_TRUE, B_TRUE));
 655  647  }
 656  648  
 657  649  int
 658  650  brand_get_presnap(brand_handle_t bh, const char *zonename,
 659  651      const char *zonepath, char *buf, size_t len)
 660  652  {
 661  653          struct brand_handle *bhp = (struct brand_handle *)bh;
 662  654          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 663  655              buf, len, DTD_ELEM_PRESNAP, B_TRUE, B_TRUE));
 664  656  }
 665  657  
 666  658  int
 667  659  brand_get_prestatechange(brand_handle_t bh, const char *zonename,
 668  660      const char *zonepath, char *buf, size_t len)
 669  661  {
 670  662          struct brand_handle *bhp = (struct brand_handle *)bh;
 671  663          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 672  664              buf, len, DTD_ELEM_PRESTATECHG, B_TRUE, B_TRUE));
 673  665  }
 674  666  
 675  667  int
 676  668  brand_get_preuninstall(brand_handle_t bh, const char *zonename,
 677  669      const char *zonepath, char *buf, size_t len)
 678  670  {
 679  671          struct brand_handle *bhp = (struct brand_handle *)bh;
 680  672          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 681  673              buf, len, DTD_ELEM_PREUNINSTALL, B_TRUE, B_TRUE));
 682  674  }
 683  675  
 684  676  int
 685  677  brand_get_query(brand_handle_t bh, const char *zonename,
 686  678      const char *zonepath, char *buf, size_t len)
 687  679  {
 688  680          struct brand_handle *bhp = (struct brand_handle *)bh;
 689  681          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 690  682              buf, len, DTD_ELEM_QUERY, B_TRUE, B_TRUE));
 691  683  }
 692  684  
 693  685  int
 694  686  brand_get_uninstall(brand_handle_t bh, const char *zonename,
 695  687      const char *zonepath, char *buf, size_t len)
 696  688  {
 697  689          struct brand_handle *bhp = (struct brand_handle *)bh;
 698  690          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 699  691              buf, len, DTD_ELEM_UNINSTALL, B_TRUE, B_TRUE));
 700  692  }
 701  693  
 702  694  int
 703  695  brand_get_validatesnap(brand_handle_t bh, const char *zonename,
 704  696      const char *zonepath, char *buf, size_t len)
 705  697  {
 706  698          struct brand_handle *bhp = (struct brand_handle *)bh;
 707  699          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 708  700              buf, len, DTD_ELEM_VALIDSNAP, B_TRUE, B_TRUE));
 709  701  }
 710  702  
 711  703  int
 712  704  brand_get_verify_cfg(brand_handle_t bh, char *buf, size_t len)
 713  705  {
 714  706          struct brand_handle *bhp = (struct brand_handle *)bh;
 715  707          return (brand_get_value(bhp, NULL, NULL, NULL, NULL,
 716  708              buf, len, DTD_ELEM_VERIFY_CFG, B_FALSE, B_TRUE));
 717  709  }
 718  710  
 719  711  int
 720  712  brand_get_verify_adm(brand_handle_t bh, const char *zonename,
 721  713      const char *zonepath, char *buf, size_t len)
 722  714  {
 723  715          struct brand_handle *bhp = (struct brand_handle *)bh;
 724  716          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 725  717              buf, len, DTD_ELEM_VERIFY_ADM, B_TRUE, B_TRUE));
 726  718  }
 727  719  
 728  720  int
 729  721  brand_get_sysboot(brand_handle_t bh, const char *zonename,
 730  722      const char *zonepath, char *buf, size_t len)
 731  723  {
 732  724          struct brand_handle *bhp = (struct brand_handle *)bh;
 733  725          return (brand_get_value(bhp, zonename, zonepath, NULL, NULL,
 734  726              buf, len, DTD_ELEM_SYSBOOT, B_TRUE, B_TRUE));
 735  727  }
 736  728  
 737  729  boolean_t
 738  730  brand_allow_exclusive_ip(brand_handle_t bh)
 739  731  {
 740  732          struct brand_handle     *bhp = (struct brand_handle *)bh;
 741  733          xmlNodePtr              node;
 742  734          xmlChar                 *allow_excl;
 743  735          boolean_t               ret;
 744  736  
 745  737          assert(bhp != NULL);
 746  738  
 747  739          if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
 748  740                  return (B_FALSE);
 749  741  
 750  742          allow_excl = xmlGetProp(node, DTD_ATTR_ALLOWEXCL);
 751  743          if (allow_excl == NULL)
 752  744                  return (B_FALSE);
 753  745  
 754  746          /* Note: only return B_TRUE if it's "true" */
 755  747          if (strcmp((char *)allow_excl, DTD_ENTITY_TRUE) == 0)
 756  748                  ret = B_TRUE;
 757  749          else
 758  750                  ret = B_FALSE;
 759  751  
 760  752          xmlFree(allow_excl);
 761  753  
 762  754          return (ret);
 763  755  }
 764  756  
 765  757  /*
 766  758   * Iterate over brand privileges
 767  759   *
 768  760   * Walks the brand config, searching for <privilege> elements, calling the
 769  761   * specified callback for each.  Returns 0 on success, or -1 on failure.
 770  762   */
 771  763  int
 772  764  brand_config_iter_privilege(brand_handle_t bh,
 773  765      int (*func)(void *, priv_iter_t *), void *data)
 774  766  {
 775  767          struct brand_handle     *bhp = (struct brand_handle *)bh;
 776  768          xmlNodePtr              node;
 777  769          xmlChar                 *name, *set, *iptype;
 778  770          priv_iter_t             priv_iter;
 779  771          int                     ret;
 780  772  
 781  773          if ((node = xmlDocGetRootElement(bhp->bh_config)) == NULL)
 782  774                  return (-1);
 783  775  
 784  776          for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
 785  777  
 786  778                  if (xmlStrcmp(node->name, DTD_ELEM_PRIVILEGE) != 0)
 787  779                          continue;
 788  780  
 789  781                  name = xmlGetProp(node, DTD_ATTR_NAME);
 790  782                  set = xmlGetProp(node, DTD_ATTR_SET);
 791  783                  iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
 792  784  
 793  785                  if (name == NULL || set == NULL || iptype == NULL) {
 794  786                          if (name != NULL)
 795  787                                  xmlFree(name);
 796  788                          if (set != NULL)
 797  789                                  xmlFree(set);
 798  790                          if (iptype != NULL)
 799  791                                  xmlFree(iptype);
 800  792                          return (-1);
 801  793                  }
 802  794  
 803  795                  priv_iter.pi_name = (char *)name;
 804  796                  priv_iter.pi_set = (char *)set;
 805  797                  priv_iter.pi_iptype = (char *)iptype;
 806  798  
 807  799                  ret = func(data, &priv_iter);
 808  800  
 809  801                  xmlFree(name);
 810  802                  xmlFree(set);
 811  803                  xmlFree(iptype);
 812  804  
 813  805                  if (ret != 0)
 814  806                          return (-1);
 815  807          }
 816  808  
 817  809          return (0);
 818  810  }
 819  811  
 820  812  static int
 821  813  i_brand_platform_iter_mounts(struct brand_handle *bhp, const char *zonename,
 822  814      const char *zonepath, int (*func)(void *, const char *, const char *,
 823  815      const char *, const char *), void *data, const xmlChar *mount_type)
 824  816  {
 825  817          xmlNodePtr node;
 826  818          xmlChar *special, *dir, *type, *opt;
 827  819          char special_exp[MAXPATHLEN];
 828  820          char dir_exp[MAXPATHLEN];
 829  821          char opt_exp[MAXPATHLEN];
 830  822          int ret;
 831  823  
 832  824          if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
 833  825                  return (-1);
 834  826  
 835  827          for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
 836  828  
 837  829                  if (xmlStrcmp(node->name, mount_type) != 0)
 838  830                          continue;
 839  831  
 840  832                  special = xmlGetProp(node, DTD_ATTR_SPECIAL);
 841  833                  dir = xmlGetProp(node, DTD_ATTR_DIRECTORY);
 842  834                  type = xmlGetProp(node, DTD_ATTR_TYPE);
 843  835                  opt = xmlGetProp(node, DTD_ATTR_OPT);
 844  836                  if ((special == NULL) || (dir == NULL) || (type == NULL) ||
 845  837                      (opt == NULL)) {
 846  838                          ret = -1;
 847  839                          goto next;
 848  840                  }
 849  841  
 850  842                  /* Substitute token values as needed. */
 851  843                  if ((ret = i_substitute_tokens((char *)special,
 852  844                      special_exp, sizeof (special_exp),
 853  845                      zonename, zonepath, NULL, NULL)) != 0)
 854  846                          goto next;
 855  847                  if ((ret = i_substitute_tokens((char *)dir,
 856  848                      dir_exp, sizeof (dir_exp),
 857  849                      zonename, zonepath, NULL, NULL)) != 0)
 858  850                          goto next;
 859  851  
 860  852                  /* opt might not be defined */
 861  853                  if (strlen((const char *)opt) == 0) {
 862  854                          xmlFree(opt);
 863  855                          opt = NULL;
 864  856                  } else {
 865  857                          if ((ret = i_substitute_tokens((char *)opt,
 866  858                              opt_exp, sizeof (opt_exp),
 867  859                              zonename, zonepath, NULL, NULL)) != 0)
 868  860                                  goto next;
 869  861                  }
 870  862  
 871  863                  ret = func(data, (char *)special_exp, (char *)dir_exp,
 872  864                      (char *)type, ((opt != NULL) ? opt_exp : NULL));
 873  865  
 874  866  next:
 875  867                  if (special != NULL)
 876  868                          xmlFree(special);
 877  869                  if (dir != NULL)
 878  870                          xmlFree(dir);
 879  871                  if (type != NULL)
 880  872                          xmlFree(type);
 881  873                  if (opt != NULL)
 882  874                          xmlFree(opt);
 883  875                  if (ret != 0)
 884  876                          return (-1);
 885  877          }
 886  878          return (0);
 887  879  }
 888  880  
 889  881  
 890  882  /*
 891  883   * Iterate over global platform filesystems
 892  884   *
 893  885   * Walks the platform, searching for <global_mount> elements, calling the
 894  886   * specified callback for each.  Returns 0 on success, or -1 on failure.
 895  887   *
 896  888   * Perform the following substitutions as necessary:
 897  889   *
 898  890   *      %R      Zonepath of zone
 899  891   */
 900  892  int
 901  893  brand_platform_iter_gmounts(brand_handle_t bh, const char *zonename,
 902  894      const char *zonepath, int (*func)(void *, const char *, const char *,
 903  895      const char *, const char *), void *data)
 904  896  {
 905  897          struct brand_handle *bhp = (struct brand_handle *)bh;
 906  898          return (i_brand_platform_iter_mounts(bhp, zonename, zonepath, func,
 907  899              data, DTD_ELEM_GLOBAL_MOUNT));
 908  900  }
 909  901  
 910  902  /*
 911  903   * Iterate over non-global zone platform filesystems
 912  904   *
 913  905   * Walks the platform, searching for <mount> elements, calling the
 914  906   * specified callback for each.  Returns 0 on success, or -1 on failure.
 915  907   */
 916  908  int
 917  909  brand_platform_iter_mounts(brand_handle_t bh, int (*func)(void *,
 918  910      const char *, const char *, const char *, const char *), void *data)
 919  911  {
 920  912          struct brand_handle *bhp = (struct brand_handle *)bh;
 921  913          return (i_brand_platform_iter_mounts(bhp, NULL, NULL, func, data,
 922  914              DTD_ELEM_MOUNT));
 923  915  }
 924  916  
 925  917  /*
 926  918   * Iterate over platform symlinks
 927  919   *
 928  920   * Walks the platform, searching for <symlink> elements, calling the
 929  921   * specified callback for each.  Returns 0 on success, or -1 on failure.
 930  922   */
 931  923  int
 932  924  brand_platform_iter_link(brand_handle_t bh,
 933  925      int (*func)(void *, const char *, const char *), void *data)
 934  926  {
 935  927          struct brand_handle *bhp = (struct brand_handle *)bh;
 936  928          xmlNodePtr node;
 937  929          xmlChar *source, *target;
 938  930          int ret;
 939  931  
 940  932          if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
 941  933                  return (-1);
 942  934  
 943  935          for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
 944  936  
 945  937                  if (xmlStrcmp(node->name, DTD_ELEM_SYMLINK) != 0)
 946  938                          continue;
 947  939  
 948  940                  source = xmlGetProp(node, DTD_ATTR_SOURCE);
 949  941                  target = xmlGetProp(node, DTD_ATTR_TARGET);
 950  942  
 951  943                  if (source == NULL || target == NULL) {
 952  944                          if (source != NULL)
 953  945                                  xmlFree(source);
 954  946                          if (target != NULL)
 955  947                                  xmlFree(target);
 956  948                          return (-1);
 957  949                  }
 958  950  
 959  951                  ret = func(data, (char *)source, (char *)target);
 960  952  
 961  953                  xmlFree(source);
 962  954                  xmlFree(target);
 963  955  
 964  956                  if (ret != 0)
 965  957                          return (-1);
 966  958          }
 967  959  
 968  960          return (0);
 969  961  }
 970  962  
 971  963  /*
 972  964   * Iterate over platform devices
 973  965   *
 974  966   * Walks the platform, searching for <device> elements, calling the
 975  967   * specified callback for each.  Returns 0 on success, or -1 on failure.
 976  968   */
 977  969  int
 978  970  brand_platform_iter_devices(brand_handle_t bh, const char *zonename,
 979  971      int (*func)(void *, const char *, const char *), void *data,
 980  972      const char *curr_iptype)
 981  973  {
 982  974          struct brand_handle     *bhp = (struct brand_handle *)bh;
 983  975          const char              *curr_arch = get_curr_arch();
 984  976          xmlNodePtr              node;
 985  977          xmlChar                 *match, *name, *arch, *iptype;
 986  978          char                    match_exp[MAXPATHLEN];
 987  979          boolean_t               err = B_FALSE;
 988  980          int                     ret = 0;
 989  981  
 990  982  
 991  983          assert(bhp != NULL);
 992  984          assert(zonename != NULL);
 993  985          assert(func != NULL);
 994  986          assert(curr_iptype != NULL);
 995  987  
 996  988          if ((node = xmlDocGetRootElement(bhp->bh_platform)) == NULL)
 997  989                  return (-1);
 998  990  
 999  991          for (node = node->xmlChildrenNode; node != NULL; node = node->next) {
1000  992  
1001  993                  if (xmlStrcmp(node->name, DTD_ELEM_DEVICE) != 0)
1002  994                          continue;
1003  995  
1004  996                  match = xmlGetProp(node, DTD_ATTR_MATCH);
1005  997                  name = xmlGetProp(node, DTD_ATTR_NAME);
1006  998                  arch = xmlGetProp(node, DTD_ATTR_ARCH);
1007  999                  iptype = xmlGetProp(node, DTD_ATTR_IPTYPE);
1008 1000                  if ((match == NULL) || (name == NULL) || (arch == NULL) ||
1009 1001                      (iptype == NULL)) {
1010 1002                          err = B_TRUE;
1011 1003                          goto next;
1012 1004                  }
1013 1005  
1014 1006                  /* check if the arch matches */
1015 1007                  if ((strcmp((char *)arch, "all") != 0) &&
1016 1008                      (strcmp((char *)arch, curr_arch) != 0))
1017 1009                          goto next;
1018 1010  
1019 1011                  /* check if the iptype matches */
1020 1012                  if ((strcmp((char *)iptype, "all") != 0) &&
1021 1013                      (strcmp((char *)iptype, curr_iptype) != 0))
1022 1014                          goto next;
1023 1015  
1024 1016                  /* Substitute token values as needed. */
1025 1017                  if ((ret = i_substitute_tokens((char *)match,
1026 1018                      match_exp, sizeof (match_exp),
1027 1019                      zonename, NULL, NULL, NULL)) != 0) {
1028 1020                          err = B_TRUE;
1029 1021                          goto next;
1030 1022                  }
1031 1023  
1032 1024                  /* name might not be defined */
1033 1025                  if (strlen((const char *)name) == 0) {
1034 1026                          xmlFree(name);
1035 1027                          name = NULL;
1036 1028                  }
1037 1029  
1038 1030                  /* invoke the callback */
1039 1031                  ret = func(data, (const char *)match_exp, (const char *)name);
1040 1032  
1041 1033  next:
1042 1034                  if (match != NULL)
1043 1035                          xmlFree(match);
1044 1036                  if (name != NULL)
1045 1037                          xmlFree(name);
1046 1038                  if (arch != NULL)
1047 1039                          xmlFree(arch);
1048 1040                  if (iptype != NULL)
1049 1041                          xmlFree(iptype);
1050 1042                  if (err)
1051 1043                          return (-1);
1052 1044                  if (ret != 0)
1053 1045                          return (-1);
1054 1046          }
1055 1047  
1056 1048          return (0);
1057 1049  }
  
    | 
      ↓ open down ↓ | 
    698 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX