Print this page
OS-200 need a better mechanism for storing persistent zone_did
OS-511 make zonecfg device resource extensible, like the net resource
OS-224 add more zonecfg net properties
OS-216 store all net config info on zone
OS-4361 libzonecfg should be aware of branded zone native root
Reviewed by: Robert Mustacchi <rm@joyent.com>
OS-3437 zonecfg failure when pool is full leaves VMs appearing to be missing
OS-399 zone phys. mem. cap should be a rctl and have associated kstat

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libzonecfg/common/libzonecfg.c
          +++ new/usr/src/lib/libzonecfg/common/libzonecfg.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  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 2014 Gary Mills
  24   24   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  25   25   * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
       26 + * Copyright 2015 Joyent Inc.
  26   27   */
  27   28  
  28   29  #include <libsysevent.h>
  29   30  #include <pthread.h>
  30   31  #include <stdlib.h>
  31   32  #include <errno.h>
  32   33  #include <fnmatch.h>
  33   34  #include <strings.h>
  34   35  #include <unistd.h>
  35   36  #include <assert.h>
↓ open down ↓ 16 lines elided ↑ open up ↑
  52   53  #include <libproc.h>
  53   54  #include <sys/priocntl.h>
  54   55  #include <libuutil.h>
  55   56  #include <wait.h>
  56   57  #include <bsm/adt.h>
  57   58  #include <auth_attr.h>
  58   59  #include <auth_list.h>
  59   60  #include <secdb.h>
  60   61  #include <user_attr.h>
  61   62  #include <prof_attr.h>
       63 +#include <sys/debug.h>
       64 +#include <os_dtd.h>
  62   65  
  63   66  #include <arpa/inet.h>
  64   67  #include <netdb.h>
  65   68  
  66   69  #include <libxml/xmlmemory.h>
  67   70  #include <libxml/parser.h>
  68   71  
  69   72  #include <libdevinfo.h>
  70   73  #include <uuid/uuid.h>
  71   74  #include <dirent.h>
  72   75  #include <libbrand.h>
  73   76  
  74   77  #include <libzonecfg.h>
  75   78  #include "zonecfg_impl.h"
  76   79  
  77   80  #define _PATH_TMPFILE   "/zonecfg.XXXXXX"
  78   81  #define ZONE_CB_RETRY_COUNT             10
  79   82  #define ZONE_EVENT_PING_SUBCLASS        "ping"
  80   83  #define ZONE_EVENT_PING_PUBLISHER       "solaris"
  81   84  
       85 +#define DEBUGID_FILE    "/etc/zones/did.txt"
       86 +
  82   87  /* Hard-code the DTD element/attribute/entity names just once, here. */
  83   88  #define DTD_ELEM_ATTR           (const xmlChar *) "attr"
  84   89  #define DTD_ELEM_COMMENT        (const xmlChar *) "comment"
  85   90  #define DTD_ELEM_DEVICE         (const xmlChar *) "device"
  86   91  #define DTD_ELEM_FS             (const xmlChar *) "filesystem"
  87   92  #define DTD_ELEM_FSOPTION       (const xmlChar *) "fsoption"
  88   93  #define DTD_ELEM_NET            (const xmlChar *) "network"
       94 +#define DTD_ELEM_NETATTR        (const xmlChar *) "net-attr"
  89   95  #define DTD_ELEM_RCTL           (const xmlChar *) "rctl"
  90   96  #define DTD_ELEM_RCTLVALUE      (const xmlChar *) "rctl-value"
  91   97  #define DTD_ELEM_ZONE           (const xmlChar *) "zone"
  92   98  #define DTD_ELEM_DATASET        (const xmlChar *) "dataset"
  93   99  #define DTD_ELEM_TMPPOOL        (const xmlChar *) "tmp_pool"
  94  100  #define DTD_ELEM_PSET           (const xmlChar *) "pset"
  95  101  #define DTD_ELEM_MCAP           (const xmlChar *) "mcap"
  96  102  #define DTD_ELEM_PACKAGE        (const xmlChar *) "package"
  97  103  #define DTD_ELEM_OBSOLETES      (const xmlChar *) "obsoletes"
  98  104  #define DTD_ELEM_DEV_PERM       (const xmlChar *) "dev-perm"
  99  105  #define DTD_ELEM_ADMIN          (const xmlChar *) "admin"
 100  106  
 101  107  #define DTD_ATTR_ACTION         (const xmlChar *) "action"
 102  108  #define DTD_ATTR_ADDRESS        (const xmlChar *) "address"
 103  109  #define DTD_ATTR_ALLOWED_ADDRESS        (const xmlChar *) "allowed-address"
 104  110  #define DTD_ATTR_AUTOBOOT       (const xmlChar *) "autoboot"
 105  111  #define DTD_ATTR_IPTYPE         (const xmlChar *) "ip-type"
 106  112  #define DTD_ATTR_DEFROUTER      (const xmlChar *) "defrouter"
 107  113  #define DTD_ATTR_DIR            (const xmlChar *) "directory"
      114 +#define DTD_ATTR_GNIC           (const xmlChar *) "global-nic"
 108  115  #define DTD_ATTR_LIMIT          (const xmlChar *) "limit"
 109  116  #define DTD_ATTR_LIMITPRIV      (const xmlChar *) "limitpriv"
 110  117  #define DTD_ATTR_BOOTARGS       (const xmlChar *) "bootargs"
 111  118  #define DTD_ATTR_SCHED          (const xmlChar *) "scheduling-class"
      119 +#define DTD_ATTR_MAC            (const xmlChar *) "mac-addr"
 112  120  #define DTD_ATTR_MATCH          (const xmlChar *) "match"
 113  121  #define DTD_ATTR_NAME           (const xmlChar *) "name"
 114  122  #define DTD_ATTR_PHYSICAL       (const xmlChar *) "physical"
 115  123  #define DTD_ATTR_POOL           (const xmlChar *) "pool"
 116  124  #define DTD_ATTR_PRIV           (const xmlChar *) "priv"
 117  125  #define DTD_ATTR_RAW            (const xmlChar *) "raw"
 118  126  #define DTD_ATTR_SPECIAL        (const xmlChar *) "special"
 119  127  #define DTD_ATTR_TYPE           (const xmlChar *) "type"
 120  128  #define DTD_ATTR_VALUE          (const xmlChar *) "value"
      129 +#define DTD_ATTR_VLANID         (const xmlChar *) "vlan-id"
 121  130  #define DTD_ATTR_ZONEPATH       (const xmlChar *) "zonepath"
 122  131  #define DTD_ATTR_NCPU_MIN       (const xmlChar *) "ncpu_min"
 123  132  #define DTD_ATTR_NCPU_MAX       (const xmlChar *) "ncpu_max"
 124  133  #define DTD_ATTR_IMPORTANCE     (const xmlChar *) "importance"
 125  134  #define DTD_ATTR_PHYSCAP        (const xmlChar *) "physcap"
 126  135  #define DTD_ATTR_VERSION        (const xmlChar *) "version"
 127  136  #define DTD_ATTR_ID             (const xmlChar *) "id"
 128  137  #define DTD_ATTR_UID            (const xmlChar *) "uid"
 129  138  #define DTD_ATTR_GID            (const xmlChar *) "gid"
 130  139  #define DTD_ATTR_MODE           (const xmlChar *) "mode"
 131  140  #define DTD_ATTR_ACL            (const xmlChar *) "acl"
 132  141  #define DTD_ATTR_BRAND          (const xmlChar *) "brand"
      142 +#define DTD_ATTR_DID            (const xmlChar *) "debugid"
 133  143  #define DTD_ATTR_HOSTID         (const xmlChar *) "hostid"
 134  144  #define DTD_ATTR_USER           (const xmlChar *) "user"
 135  145  #define DTD_ATTR_AUTHS          (const xmlChar *) "auths"
 136  146  #define DTD_ATTR_FS_ALLOWED     (const xmlChar *) "fs-allowed"
 137  147  
 138  148  #define DTD_ENTITY_BOOLEAN      "boolean"
 139  149  #define DTD_ENTITY_DEVPATH      "devpath"
 140  150  #define DTD_ENTITY_DRIVER       "driver"
 141  151  #define DTD_ENTITY_DRVMIN       "drv_min"
 142  152  #define DTD_ENTITY_FALSE        "false"
↓ open down ↓ 26 lines elided ↑ open up ↑
 169  179          char *action;
 170  180          uint64_t low_limit;
 171  181  } aliases[] = {
 172  182          {ALIAS_MAXLWPS, "zone.max-lwps", "privileged", "deny", 100},
 173  183          {ALIAS_MAXSHMMEM, "zone.max-shm-memory", "privileged", "deny", 0},
 174  184          {ALIAS_MAXSHMIDS, "zone.max-shm-ids", "privileged", "deny", 0},
 175  185          {ALIAS_MAXMSGIDS, "zone.max-msg-ids", "privileged", "deny", 0},
 176  186          {ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0},
 177  187          {ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0},
 178  188          {ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0},
      189 +        {ALIAS_MAXPHYSMEM, "zone.max-physical-memory", "privileged", "deny",
      190 +            1048576},
 179  191          {ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0},
 180  192          {ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0},
 181  193          {ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100},
 182  194          {NULL, NULL, NULL, NULL, 0}
 183  195  };
 184  196  
 185  197  /*
 186  198   * Structure for applying rctls to a running zone.  It allows important
 187  199   * process values to be passed together easily.
 188  200   */
↓ open down ↓ 73 lines elided ↑ open up ↑
 262  274  {
 263  275          return (*zonecfg_root != '\0');
 264  276  }
 265  277  
 266  278  /*
 267  279   * Callers of the _file_path() functions are expected to have the second
 268  280   * parameter be a (char foo[MAXPATHLEN]).
 269  281   */
 270  282  
 271  283  static boolean_t
 272      -config_file_path(const char *zonename, char *answer)
      284 +file_path_common(const char *zonename, const char *subdir, const char *stem,
      285 +    char *answer, size_t answer_size)
 273  286  {
 274      -        return (snprintf(answer, MAXPATHLEN, "%s%s/%s.xml", zonecfg_root,
 275      -            ZONE_CONFIG_ROOT, zonename) < MAXPATHLEN);
      287 +        const char *native_root = zone_get_nroot();
      288 +
      289 +        if (native_root == NULL || zonecfg_in_alt_root()) {
      290 +                /*
      291 +                 * Do not prepend the native system root (e.g. "/native") if an
      292 +                 * alternative configuration root has been selected.
      293 +                 */
      294 +                native_root = "";
      295 +        }
      296 +
      297 +        return (snprintf(answer, answer_size, "%s%s%s/%s.%s", native_root,
      298 +            zonecfg_root, subdir, zonename, stem) < answer_size);
 276  299  }
 277  300  
 278  301  static boolean_t
 279      -snap_file_path(const char *zonename, char *answer)
      302 +config_file_path(const char *zonename, char *answer, size_t answer_size)
 280  303  {
 281      -        return (snprintf(answer, MAXPATHLEN, "%s%s/%s.snapshot.xml",
 282      -            zonecfg_root, ZONE_SNAPSHOT_ROOT, zonename) < MAXPATHLEN);
      304 +        return (file_path_common(zonename, ZONE_CONFIG_ROOT, "xml", answer,
      305 +            answer_size));
 283  306  }
 284  307  
      308 +static boolean_t
      309 +snap_file_path(const char *zonename, char *answer, size_t answer_size)
      310 +{
      311 +        return (file_path_common(zonename, ZONE_SNAPSHOT_ROOT, "snapshot.xml",
      312 +            answer, answer_size));
      313 +}
      314 +
 285  315  /*ARGSUSED*/
 286  316  static void
 287  317  zonecfg_error_func(void *ctx, const char *msg, ...)
 288  318  {
 289  319          /*
 290  320           * This function does nothing by design.  Its purpose is to prevent
 291  321           * libxml from dumping unwanted messages to stdout/stderr.
 292  322           */
 293  323  }
 294  324  
↓ open down ↓ 48 lines elided ↑ open up ↑
 343  373  }
 344  374  
 345  375  int
 346  376  zonecfg_destroy(const char *zonename, boolean_t force)
 347  377  {
 348  378          char path[MAXPATHLEN];
 349  379          struct zoneent ze;
 350  380          int err, state_err;
 351  381          zone_state_t state;
 352  382  
 353      -        if (!config_file_path(zonename, path))
      383 +        if (!config_file_path(zonename, path, sizeof (path)))
 354  384                  return (Z_MISC_FS);
 355  385  
 356  386          state_err = zone_get_state((char *)zonename, &state);
 357  387          err = access(path, W_OK);
 358  388  
 359  389          /*
 360  390           * If there is no file, and no index entry, reliably indicate that no
 361  391           * such zone exists.
 362  392           */
 363  393          if ((state_err == Z_NO_ZONE) && (err == -1) && (errno == ENOENT))
↓ open down ↓ 36 lines elided ↑ open up ↑
 400  430          if (err == Z_OK || err == Z_NO_ZONE)
 401  431                  return (Z_OK);
 402  432          return (err);
 403  433  }
 404  434  
 405  435  int
 406  436  zonecfg_destroy_snapshot(const char *zonename)
 407  437  {
 408  438          char path[MAXPATHLEN];
 409  439  
 410      -        if (!snap_file_path(zonename, path))
      440 +        if (!snap_file_path(zonename, path, sizeof (path)))
 411  441                  return (Z_MISC_FS);
 412  442          return (zonecfg_destroy_impl(path));
 413  443  }
 414  444  
 415  445  static int
 416  446  getroot(zone_dochandle_t handle, xmlNodePtr *root)
 417  447  {
 418  448          if (zonecfg_check_handle(handle) == Z_BAD_HANDLE)
 419  449                  return (Z_BAD_HANDLE);
 420  450  
↓ open down ↓ 146 lines elided ↑ open up ↑
 567  597                          xmlUnlinkNode(child);
 568  598                          xmlFreeNode(child);
 569  599                  }
 570  600          }
 571  601  }
 572  602  
 573  603  static int
 574  604  zonecfg_get_handle_impl(const char *zonename, const char *filename,
 575  605      zone_dochandle_t handle)
 576  606  {
 577      -        xmlValidCtxtPtr cvp;
 578  607          struct stat statbuf;
 579      -        int valid;
      608 +        boolean_t valid;
 580  609  
 581  610          if (zonename == NULL)
 582  611                  return (Z_NO_ZONE);
 583  612  
 584  613          if ((handle->zone_dh_doc = xmlParseFile(filename)) == NULL) {
 585  614                  /* distinguish file not found vs. found but not parsed */
 586  615                  if (stat(filename, &statbuf) == 0)
 587  616                          return (Z_INVALID_DOCUMENT);
 588  617                  return (Z_NO_ZONE);
 589  618          }
 590      -        if ((cvp = xmlNewValidCtxt()) == NULL)
      619 +
      620 +        if (os_dtd_validate(handle->zone_dh_doc, B_FALSE, &valid) != 0) {
 591  621                  return (Z_NOMEM);
 592      -        cvp->error = zonecfg_error_func;
 593      -        cvp->warning = zonecfg_error_func;
 594      -        valid = xmlValidateDocument(cvp, handle->zone_dh_doc);
 595      -        xmlFreeValidCtxt(cvp);
 596      -        if (valid == 0)
      622 +        }
      623 +        if (!valid) {
 597  624                  return (Z_INVALID_DOCUMENT);
      625 +        }
 598  626  
 599  627          /* delete any comments such as inherited Sun copyright / ident str */
 600  628          stripcomments(handle);
 601  629          return (Z_OK);
 602  630  }
 603  631  
 604  632  int
 605  633  zonecfg_get_handle(const char *zonename, zone_dochandle_t handle)
 606  634  {
 607  635          char path[MAXPATHLEN];
 608  636  
 609      -        if (!config_file_path(zonename, path))
      637 +        if (!config_file_path(zonename, path, sizeof (path)))
 610  638                  return (Z_MISC_FS);
 611  639          handle->zone_dh_newzone = B_FALSE;
 612  640  
 613  641          return (zonecfg_get_handle_impl(zonename, path, handle));
 614  642  }
 615  643  
 616  644  int
 617  645  zonecfg_get_attach_handle(const char *path, const char *fname,
 618  646      const char *zonename, boolean_t preserve_sw, zone_dochandle_t handle)
 619  647  {
↓ open down ↓ 23 lines elided ↑ open up ↑
 643  671                  return (err);
 644  672  
 645  673          return (setrootattr(handle, DTD_ATTR_NAME, zonename));
 646  674  }
 647  675  
 648  676  int
 649  677  zonecfg_get_snapshot_handle(const char *zonename, zone_dochandle_t handle)
 650  678  {
 651  679          char path[MAXPATHLEN];
 652  680  
 653      -        if (!snap_file_path(zonename, path))
      681 +        if (!snap_file_path(zonename, path, sizeof (path)))
 654  682                  return (Z_MISC_FS);
 655  683          handle->zone_dh_newzone = B_FALSE;
 656  684          return (zonecfg_get_handle_impl(zonename, path, handle));
 657  685  }
 658  686  
 659  687  int
 660  688  zonecfg_get_template_handle(const char *template, const char *zonename,
 661  689      zone_dochandle_t handle)
 662  690  {
 663  691          char path[MAXPATHLEN];
 664  692          int err;
 665  693  
 666      -        if (!config_file_path(template, path))
      694 +        if (!config_file_path(template, path, sizeof (path)))
 667  695                  return (Z_MISC_FS);
 668  696  
 669  697          if ((err = zonecfg_get_handle_impl(template, path, handle)) != Z_OK)
 670  698                  return (err);
 671  699          handle->zone_dh_newzone = B_TRUE;
 672  700          return (setrootattr(handle, DTD_ATTR_NAME, zonename));
 673  701  }
 674  702  
 675  703  int
 676  704  zonecfg_get_xml_handle(const char *path, zone_dochandle_t handle)
↓ open down ↓ 13 lines elided ↑ open up ↑
 690  718  /*
 691  719   * Initialize two handles from the manifest read on fd.  The rem_handle
 692  720   * is initialized from the input file, including the sw inventory.  The
 693  721   * local_handle is initialized with the same zone configuration but with
 694  722   * no sw inventory.
 695  723   */
 696  724  int
 697  725  zonecfg_attach_manifest(int fd, zone_dochandle_t local_handle,
 698  726      zone_dochandle_t rem_handle)
 699  727  {
 700      -        xmlValidCtxtPtr cvp;
 701      -        int valid;
      728 +        boolean_t valid;
 702  729  
 703  730          /* load the manifest into the handle for the remote system */
 704  731          if ((rem_handle->zone_dh_doc = xmlReadFd(fd, NULL, NULL, 0)) == NULL) {
 705  732                  return (Z_INVALID_DOCUMENT);
 706  733          }
 707      -        if ((cvp = xmlNewValidCtxt()) == NULL)
      734 +
      735 +        if (os_dtd_validate(rem_handle->zone_dh_doc, B_FALSE, &valid) != 0) {
 708  736                  return (Z_NOMEM);
 709      -        cvp->error = zonecfg_error_func;
 710      -        cvp->warning = zonecfg_error_func;
 711      -        valid = xmlValidateDocument(cvp, rem_handle->zone_dh_doc);
 712      -        xmlFreeValidCtxt(cvp);
 713      -        if (valid == 0)
      737 +        }
      738 +        if (!valid) {
 714  739                  return (Z_INVALID_DOCUMENT);
      740 +        }
 715  741  
 716  742          /* delete any comments such as inherited Sun copyright / ident str */
 717  743          stripcomments(rem_handle);
 718  744  
 719  745          rem_handle->zone_dh_newzone = B_TRUE;
 720  746          rem_handle->zone_dh_sw_inv = B_TRUE;
 721  747  
 722  748          /*
 723  749           * Now use the remote system handle to generate a local system handle
 724  750           * with an identical zones configuration but no sw inventory.
 725  751           */
 726  752          if ((local_handle->zone_dh_doc = xmlCopyDoc(rem_handle->zone_dh_doc,
 727  753              1)) == NULL) {
 728  754                  return (Z_INVALID_DOCUMENT);
 729  755          }
 730  756  
 731  757          /*
 732  758           * We need to re-run xmlValidateDocument on local_handle to properly
 733  759           * update the in-core representation of the configuration.
 734  760           */
 735      -        if ((cvp = xmlNewValidCtxt()) == NULL)
      761 +        if (os_dtd_validate(local_handle->zone_dh_doc, B_FALSE, &valid) != 0) {
 736  762                  return (Z_NOMEM);
 737      -        cvp->error = zonecfg_error_func;
 738      -        cvp->warning = zonecfg_error_func;
 739      -        valid = xmlValidateDocument(cvp, local_handle->zone_dh_doc);
 740      -        xmlFreeValidCtxt(cvp);
 741      -        if (valid == 0)
      763 +        }
      764 +        if (!valid) {
 742  765                  return (Z_INVALID_DOCUMENT);
      766 +        }
 743  767  
 744  768          strip_sw_inv(local_handle);
 745  769  
 746  770          local_handle->zone_dh_newzone = B_TRUE;
 747  771          local_handle->zone_dh_sw_inv = B_FALSE;
 748  772  
 749  773          return (Z_OK);
 750  774  }
 751  775  
 752  776  static boolean_t
↓ open down ↓ 433 lines elided ↑ open up ↑
1186 1210   *      Write XML to tmpfile
1187 1211   *      Rename tmpfile to xmlfile (zonecfg.xxxxxx -> bar.xml)
1188 1212   *      Add entry for 'bar' to index file, Remove entry for 'foo' (refresh)
1189 1213   *      If it fails, delete bar.xml; foo.xml is left behind.
1190 1214   */
1191 1215  static int
1192 1216  zonecfg_save_impl(zone_dochandle_t handle, char *filename)
1193 1217  {
1194 1218          char tmpfile[MAXPATHLEN];
1195 1219          char bakdir[MAXPATHLEN], bakbase[MAXPATHLEN], bakfile[MAXPATHLEN];
1196      -        int tmpfd, err, valid;
1197      -        xmlValidCtxt cvp = { NULL };
     1220 +        int tmpfd, err;
1198 1221          boolean_t backup;
     1222 +        boolean_t valid;
1199 1223  
1200 1224          (void) strlcpy(tmpfile, filename, sizeof (tmpfile));
1201 1225          (void) dirname(tmpfile);
1202 1226          (void) strlcat(tmpfile, _PATH_TMPFILE, sizeof (tmpfile));
1203 1227  
1204 1228          tmpfd = mkstemp(tmpfile);
1205 1229          if (tmpfd == -1) {
1206 1230                  (void) unlink(tmpfile);
1207 1231                  return (Z_TEMP_FILE);
1208 1232          }
1209 1233          (void) close(tmpfd);
1210 1234  
1211      -        cvp.error = zonecfg_error_func;
1212      -        cvp.warning = zonecfg_error_func;
1213      -
1214 1235          /*
1215 1236           * We do a final validation of the document.  Since the library has
1216 1237           * malfunctioned if it fails to validate, we follow-up with an
1217 1238           * assert() that the doc is valid.
1218 1239           */
1219      -        valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
1220      -        assert(valid != 0);
     1240 +        VERIFY0(os_dtd_validate(handle->zone_dh_doc, B_FALSE, &valid));
     1241 +        VERIFY(valid == B_TRUE);
1221 1242  
1222 1243          if (xmlSaveFormatFile(tmpfile, handle->zone_dh_doc, 1) <= 0)
1223 1244                  goto err;
1224 1245  
1225 1246          (void) chmod(tmpfile, 0644);
1226 1247  
1227 1248          /*
1228 1249           * In the event we are doing a standard save, hard link a copy of the
1229 1250           * original file in .backup.<pid>.filename so we can restore it if
1230 1251           * something goes wrong.
↓ open down ↓ 34 lines elided ↑ open up ↑
1265 1286           */
1266 1287          if (is_snapshot(handle))
1267 1288                  return (Z_OK);
1268 1289  
1269 1290          /* now update the index file to reflect whatever we just did */
1270 1291          if ((err = zonecfg_refresh_index_file(handle)) != Z_OK) {
1271 1292                  if (backup) {
1272 1293                          /*
1273 1294                           * Try to restore from our backup.
1274 1295                           */
1275      -                        (void) unlink(filename);
1276 1296                          (void) rename(bakfile, filename);
1277 1297                  } else {
1278 1298                          /*
1279 1299                           * Either the zone is new, in which case we can delete
1280 1300                           * new.xml, or we're doing a rename, so ditto.
1281 1301                           */
1282 1302                          assert(is_new(handle) || is_renaming(handle));
1283 1303                          (void) unlink(filename);
1284 1304                  }
1285 1305                  return (Z_UPDATING_INDEX);
↓ open down ↓ 22 lines elided ↑ open up ↑
1308 1328          /*
1309 1329           * We don't support saving snapshots or a tree containing a sw
1310 1330           * inventory at this time.
1311 1331           */
1312 1332          if (handle->zone_dh_snapshot || handle->zone_dh_sw_inv)
1313 1333                  return (Z_INVAL);
1314 1334  
1315 1335          if ((err = zonecfg_get_name(handle, zname, sizeof (zname))) != Z_OK)
1316 1336                  return (err);
1317 1337  
1318      -        if (!config_file_path(zname, path))
     1338 +        if (!config_file_path(zname, path, sizeof (path)))
1319 1339                  return (Z_MISC_FS);
1320 1340  
1321 1341          addcomment(handle, "\n    DO NOT EDIT THIS "
1322 1342              "FILE.  Use zonecfg(1M) instead.\n");
1323 1343  
1324 1344          /*
1325 1345           * Update user_attr first so that it will be older
1326 1346           * than the config file.
1327 1347           */
1328 1348          (void) zonecfg_authorize_users(handle, zname);
1329 1349          err = zonecfg_save_impl(handle, path);
1330 1350  
1331 1351          stripcomments(handle);
1332 1352  
1333 1353          if (err != Z_OK)
1334 1354                  return (err);
1335 1355  
1336 1356          handle->zone_dh_newzone = B_FALSE;
1337 1357  
1338 1358          if (is_renaming(handle)) {
1339      -                if (config_file_path(handle->zone_dh_delete_name, delpath))
     1359 +                if (config_file_path(handle->zone_dh_delete_name, delpath,
     1360 +                    sizeof (delpath))) {
1340 1361                          (void) unlink(delpath);
     1362 +                }
1341 1363                  handle->zone_dh_delete_name[0] = '\0';
1342 1364          }
1343 1365  
1344 1366          return (Z_OK);
1345 1367  }
1346 1368  
1347 1369  int
1348 1370  zonecfg_verify_save(zone_dochandle_t handle, char *filename)
1349 1371  {
1350      -        int valid;
     1372 +        boolean_t valid;
1351 1373  
1352      -        xmlValidCtxt cvp = { NULL };
1353      -
1354 1374          if (zonecfg_check_handle(handle) != Z_OK)
1355 1375                  return (Z_BAD_HANDLE);
1356 1376  
1357      -        cvp.error = zonecfg_error_func;
1358      -        cvp.warning = zonecfg_error_func;
1359      -
1360 1377          /*
1361 1378           * We do a final validation of the document.  Since the library has
1362 1379           * malfunctioned if it fails to validate, we follow-up with an
1363 1380           * assert() that the doc is valid.
1364 1381           */
1365      -        valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
1366      -        assert(valid != 0);
     1382 +        VERIFY0(os_dtd_validate(handle->zone_dh_doc, B_FALSE, &valid));
     1383 +        VERIFY(valid == B_TRUE);
1367 1384  
1368 1385          if (xmlSaveFormatFile(filename, handle->zone_dh_doc, 1) <= 0)
1369 1386                  return (Z_SAVING_FILE);
1370 1387  
1371 1388          return (Z_OK);
1372 1389  }
1373 1390  
1374 1391  int
1375 1392  zonecfg_detach_save(zone_dochandle_t handle, uint_t flags)
1376 1393  {
1377 1394          char zname[ZONENAME_MAX];
1378 1395          char path[MAXPATHLEN];
1379 1396          char migpath[MAXPATHLEN];
1380      -        xmlValidCtxt cvp = { NULL };
1381 1397          int err = Z_SAVING_FILE;
1382      -        int valid;
     1398 +        boolean_t valid;
1383 1399  
1384 1400          if (zonecfg_check_handle(handle) != Z_OK)
1385 1401                  return (Z_BAD_HANDLE);
1386 1402  
1387 1403          if (flags & ZONE_DRY_RUN) {
1388 1404                  (void) strlcpy(migpath, "-", sizeof (migpath));
1389 1405          } else {
1390 1406                  if ((err = zonecfg_get_name(handle, zname, sizeof (zname)))
1391 1407                      != Z_OK)
1392 1408                          return (err);
↓ open down ↓ 6 lines elided ↑ open up ↑
1399 1415                      ZONE_DETACHED) >= sizeof (migpath))
1400 1416                          return (Z_NOMEM);
1401 1417          }
1402 1418  
1403 1419          if ((err = operation_prep(handle)) != Z_OK)
1404 1420                  return (err);
1405 1421  
1406 1422          addcomment(handle, "\n    DO NOT EDIT THIS FILE.  "
1407 1423              "Use zonecfg(1M) and zoneadm(1M) attach.\n");
1408 1424  
1409      -        cvp.error = zonecfg_error_func;
1410      -        cvp.warning = zonecfg_error_func;
1411      -
1412 1425          /*
1413 1426           * We do a final validation of the document.  Since the library has
1414 1427           * malfunctioned if it fails to validate, we follow-up with an
1415 1428           * assert() that the doc is valid.
1416 1429           */
1417      -        valid = xmlValidateDocument(&cvp, handle->zone_dh_doc);
1418      -        assert(valid != 0);
     1430 +        VERIFY0(os_dtd_validate(handle->zone_dh_doc, B_FALSE, &valid));
     1431 +        VERIFY(valid == B_TRUE);
1419 1432  
1420 1433          if (xmlSaveFormatFile(migpath, handle->zone_dh_doc, 1) <= 0)
1421 1434                  return (Z_SAVING_FILE);
1422 1435  
1423 1436          if (!(flags & ZONE_DRY_RUN))
1424 1437                  (void) chmod(migpath, 0644);
1425 1438  
1426 1439          stripcomments(handle);
1427 1440  
1428 1441          handle->zone_dh_newzone = B_FALSE;
↓ open down ↓ 52 lines elided ↑ open up ↑
1481 1494   * ZONE_CONFIG_ROOT instead of config_file_path(zonename).  This is how we
1482 1495   * work around the case of a config file which has not been created yet:
1483 1496   * the user will need access to the directory so use that as a heuristic.
1484 1497   */
1485 1498  
1486 1499  int
1487 1500  zonecfg_access(const char *zonename, int amode)
1488 1501  {
1489 1502          char path[MAXPATHLEN];
1490 1503  
1491      -        if (!config_file_path(zonename, path))
     1504 +        if (!config_file_path(zonename, path, sizeof (path)))
1492 1505                  return (Z_INVAL);
1493 1506          if (access(path, amode) == 0)
1494 1507                  return (Z_OK);
1495 1508          if (errno == ENOENT) {
1496 1509                  if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1497 1510                      ZONE_CONFIG_ROOT) >= sizeof (path))
1498 1511                          return (Z_INVAL);
1499 1512                  if (access(path, amode) == 0)
1500 1513                          return (Z_OK);
1501 1514          }
↓ open down ↓ 44 lines elided ↑ open up ↑
1546 1559          if (snprintf(path, sizeof (path), "%s%s", zonecfg_root,
1547 1560              ZONE_SNAPSHOT_ROOT) >= sizeof (path)) {
1548 1561                  error = Z_MISC_FS;
1549 1562                  goto out;
1550 1563          }
1551 1564          if ((mkdir(path, S_IRWXU) == -1) && (errno != EEXIST)) {
1552 1565                  error = Z_MISC_FS;
1553 1566                  goto out;
1554 1567          }
1555 1568  
1556      -        if (!snap_file_path(zonename, path)) {
     1569 +        if (!snap_file_path(zonename, path, sizeof (path))) {
1557 1570                  error = Z_MISC_FS;
1558 1571                  goto out;
1559 1572          }
1560 1573  
1561 1574          addcomment(handle, "\n    DO NOT EDIT THIS FILE.  "
1562 1575              "It is a snapshot of running zone state.\n");
1563 1576  
1564 1577          error = zonecfg_save_impl(handle, path);
1565 1578  
1566 1579          stripcomments(handle);
↓ open down ↓ 510 lines elided ↑ open up ↑
2077 2090   *
2078 2091   * Errors might also be returned if the entry that exactly matches the
2079 2092   * query lacks critical network resource information.
2080 2093   *
2081 2094   * If there is a single match, then the matching entry's physical interface, IP
2082 2095   * address, and default router information are stored in 'tabptr'.
2083 2096   */
2084 2097  int
2085 2098  zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2086 2099  {
2087      -        xmlNodePtr cur;
     2100 +        xmlNodePtr cur, val;
2088 2101          xmlNodePtr firstmatch;
2089 2102          int err;
2090 2103          char address[INET6_ADDRSTRLEN];
2091 2104          char physical[LIFNAMSIZ];
     2105 +        char mac[MAXMACADDRLEN];
     2106 +        char gnic[LIFNAMSIZ];
2092 2107          size_t addrspec;                /* nonzero if tabptr has IP addr */
2093 2108          size_t physspec;                /* nonzero if tabptr has interface */
     2109 +        size_t macspec;                 /* nonzero if tabptr has mac addr */
     2110 +        size_t gnicspec;                /* nonzero if tabptr has gnic */
2094 2111          size_t defrouterspec;           /* nonzero if tabptr has def. router */
2095 2112          size_t allowed_addrspec;
2096 2113          zone_iptype_t iptype;
2097 2114  
2098 2115          if (tabptr == NULL)
2099 2116                  return (Z_INVAL);
2100 2117  
2101 2118          /*
2102 2119           * Determine the fields that will be searched.  There must be at least
2103 2120           * one.
2104 2121           *
2105      -         * zone_nwif_address, zone_nwif_physical, and zone_nwif_defrouter are
     2122 +         * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter,
     2123 +         * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic  are
2106 2124           * arrays, so no NULL checks are necessary.
2107 2125           */
2108 2126          addrspec = strlen(tabptr->zone_nwif_address);
2109 2127          physspec = strlen(tabptr->zone_nwif_physical);
     2128 +        macspec = strlen(tabptr->zone_nwif_mac);
     2129 +        gnicspec = strlen(tabptr->zone_nwif_gnic);
2110 2130          defrouterspec = strlen(tabptr->zone_nwif_defrouter);
2111 2131          allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address);
2112 2132          if (addrspec != 0 && allowed_addrspec != 0)
2113 2133                  return (Z_INVAL); /* can't specify both */
2114 2134          if (addrspec == 0 && physspec == 0 && defrouterspec == 0 &&
2115      -            allowed_addrspec == 0)
     2135 +            allowed_addrspec == 0 && macspec == 0 && gnicspec == 0)
2116 2136                  return (Z_INSUFFICIENT_SPEC);
2117 2137  
2118 2138          if ((err = operation_prep(handle)) != Z_OK)
2119 2139                  return (err);
2120 2140  
2121 2141          if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK)
2122 2142                  return (err);
2123 2143          /*
2124 2144           * Iterate over the configuration's elements and look for net elements
2125 2145           * that match the query.
↓ open down ↓ 6 lines elided ↑ open up ↑
2132 2152                          continue;
2133 2153  
2134 2154                  /*
2135 2155                   * If any relevant fields don't match the query, then skip
2136 2156                   * the current net element.
2137 2157                   */
2138 2158                  if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
2139 2159                      physical, sizeof (physical)) != Z_OK ||
2140 2160                      strcmp(tabptr->zone_nwif_physical, physical) != 0))
2141 2161                          continue;
     2162 +                if (iptype == ZS_EXCLUSIVE && macspec != 0 &&
     2163 +                    (fetchprop(cur, DTD_ATTR_MAC, mac, sizeof (mac)) != Z_OK ||
     2164 +                    strcmp(tabptr->zone_nwif_mac, mac) != 0))
     2165 +                        continue;
     2166 +                if (iptype == ZS_EXCLUSIVE && gnicspec != 0 &&
     2167 +                    (fetchprop(cur, DTD_ATTR_GNIC, gnic,
     2168 +                    sizeof (gnic)) != Z_OK ||
     2169 +                    strcmp(tabptr->zone_nwif_gnic, gnic) != 0))
     2170 +                        continue;
2142 2171                  if (iptype == ZS_SHARED && addrspec != 0 &&
2143 2172                      (fetchprop(cur, DTD_ATTR_ADDRESS, address,
2144 2173                      sizeof (address)) != Z_OK ||
2145 2174                      !zonecfg_same_net_address(tabptr->zone_nwif_address,
2146 2175                      address)))
2147 2176                          continue;
2148 2177                  if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2149 2178                      (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2150 2179                      sizeof (address)) != Z_OK ||
2151 2180                      !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
↓ open down ↓ 22 lines elided ↑ open up ↑
2174 2203          if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
2175 2204              sizeof (tabptr->zone_nwif_physical))) != Z_OK)
2176 2205                  return (err);
2177 2206  
2178 2207          if (iptype == ZS_SHARED &&
2179 2208              (err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
2180 2209              sizeof (tabptr->zone_nwif_address))) != Z_OK)
2181 2210                  return (err);
2182 2211  
2183 2212          if (iptype == ZS_EXCLUSIVE &&
     2213 +            (err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac,
     2214 +            sizeof (tabptr->zone_nwif_mac))) != Z_OK)
     2215 +                return (err);
     2216 +
     2217 +        if (iptype == ZS_EXCLUSIVE &&
     2218 +            (err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id,
     2219 +            sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK)
     2220 +                return (err);
     2221 +
     2222 +        if (iptype == ZS_EXCLUSIVE &&
     2223 +            (err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic,
     2224 +            sizeof (tabptr->zone_nwif_gnic))) != Z_OK)
     2225 +                return (err);
     2226 +
     2227 +        if (iptype == ZS_EXCLUSIVE &&
2184 2228              (err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2185 2229              tabptr->zone_nwif_allowed_address,
2186 2230              sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK)
2187 2231                  return (err);
2188 2232  
2189 2233          if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
2190 2234              tabptr->zone_nwif_defrouter,
2191 2235              sizeof (tabptr->zone_nwif_defrouter))) != Z_OK)
2192 2236                  return (err);
2193 2237  
     2238 +        tabptr->zone_nwif_attrp = NULL;
     2239 +        for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
     2240 +                struct zone_res_attrtab *valptr;
     2241 +
     2242 +                valptr = (struct zone_res_attrtab *)malloc(
     2243 +                    sizeof (struct zone_res_attrtab));
     2244 +                if (valptr == NULL)
     2245 +                        return (Z_NOMEM);
     2246 +
     2247 +                valptr->zone_res_attr_name[0] =
     2248 +                    valptr->zone_res_attr_value[0] = '\0';
     2249 +                if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr)
     2250 +                    != Z_OK) {
     2251 +                        free(valptr);
     2252 +                        break;
     2253 +                }
     2254 +
     2255 +                if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
     2256 +                    sizeof (valptr->zone_res_attr_name)) != Z_OK))
     2257 +                        break;
     2258 +                if ((fetchprop(val, DTD_ATTR_VALUE,
     2259 +                    valptr->zone_res_attr_value,
     2260 +                    sizeof (valptr->zone_res_attr_value)) != Z_OK))
     2261 +                        break;
     2262 +        }
     2263 +
2194 2264          return (Z_OK);
2195 2265  }
2196 2266  
2197 2267  static int
2198 2268  zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2199 2269  {
2200      -        xmlNodePtr newnode, cur = handle->zone_dh_cur;
     2270 +        xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
     2271 +        struct zone_res_attrtab *valptr;
2201 2272          int err;
2202 2273  
2203 2274          newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
2204 2275          if (strlen(tabptr->zone_nwif_address) > 0 &&
2205 2276              (err = newprop(newnode, DTD_ATTR_ADDRESS,
2206 2277              tabptr->zone_nwif_address)) != Z_OK)
2207 2278                  return (err);
2208 2279          if (strlen(tabptr->zone_nwif_allowed_address) > 0 &&
2209 2280              (err = newprop(newnode, DTD_ATTR_ALLOWED_ADDRESS,
2210 2281              tabptr->zone_nwif_allowed_address)) != Z_OK)
2211 2282                  return (err);
2212 2283          if ((err = newprop(newnode, DTD_ATTR_PHYSICAL,
2213 2284              tabptr->zone_nwif_physical)) != Z_OK)
2214 2285                  return (err);
2215 2286          /*
2216      -         * Do not add this property when it is not set, for backwards
2217      -         * compatibility and because it is optional.
     2287 +         * Do not add these properties when they are not set, for backwards
     2288 +         * compatibility and because they are optional.
2218 2289           */
2219 2290          if ((strlen(tabptr->zone_nwif_defrouter) > 0) &&
2220 2291              ((err = newprop(newnode, DTD_ATTR_DEFROUTER,
2221 2292              tabptr->zone_nwif_defrouter)) != Z_OK))
2222 2293                  return (err);
     2294 +        if (strlen(tabptr->zone_nwif_mac) > 0 &&
     2295 +            (err = newprop(newnode, DTD_ATTR_MAC,
     2296 +            tabptr->zone_nwif_mac)) != Z_OK)
     2297 +                return (err);
     2298 +        if (strlen(tabptr->zone_nwif_vlan_id) > 0 &&
     2299 +            (err = newprop(newnode, DTD_ATTR_VLANID,
     2300 +            tabptr->zone_nwif_vlan_id)) != Z_OK)
     2301 +                return (err);
     2302 +        if (strlen(tabptr->zone_nwif_gnic) > 0 &&
     2303 +            (err = newprop(newnode, DTD_ATTR_GNIC,
     2304 +            tabptr->zone_nwif_gnic)) != Z_OK)
     2305 +                return (err);
     2306 +
     2307 +        for (valptr = tabptr->zone_nwif_attrp; valptr != NULL;
     2308 +            valptr = valptr->zone_res_attr_next) {
     2309 +                valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR,
     2310 +                    NULL);
     2311 +                err = newprop(valnode, DTD_ATTR_NAME,
     2312 +                    valptr->zone_res_attr_name);
     2313 +                if (err != Z_OK)
     2314 +                        return (err);
     2315 +                err = newprop(valnode, DTD_ATTR_VALUE,
     2316 +                    valptr->zone_res_attr_value);
     2317 +                if (err != Z_OK)
     2318 +                        return (err);
     2319 +        }
     2320 +
2223 2321          return (Z_OK);
2224 2322  }
2225 2323  
2226 2324  int
2227 2325  zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2228 2326  {
2229 2327          int err;
2230 2328  
2231 2329          if (tabptr == NULL)
2232 2330                  return (Z_INVAL);
↓ open down ↓ 4 lines elided ↑ open up ↑
2237 2335          if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
2238 2336                  return (err);
2239 2337  
2240 2338          return (Z_OK);
2241 2339  }
2242 2340  
2243 2341  static int
2244 2342  zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2245 2343  {
2246 2344          xmlNodePtr cur = handle->zone_dh_cur;
2247      -        boolean_t addr_match, phys_match, allowed_addr_match;
     2345 +        boolean_t addr_match, phys_match, allowed_addr_match, mac_match,
     2346 +            gnic_match;
2248 2347  
2249 2348          for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2250 2349                  if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2251 2350                          continue;
2252 2351  
2253 2352                  addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
2254 2353                      tabptr->zone_nwif_address);
2255 2354                  allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2256 2355                      tabptr->zone_nwif_allowed_address);
2257 2356                  phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
2258 2357                      tabptr->zone_nwif_physical);
     2358 +                mac_match = match_prop(cur, DTD_ATTR_MAC,
     2359 +                    tabptr->zone_nwif_mac);
     2360 +                gnic_match = match_prop(cur, DTD_ATTR_GNIC,
     2361 +                    tabptr->zone_nwif_gnic);
2259 2362  
2260      -                if (addr_match && allowed_addr_match && phys_match) {
     2363 +                if ((addr_match || allowed_addr_match || mac_match ||
     2364 +                    gnic_match) && phys_match) {
2261 2365                          xmlUnlinkNode(cur);
2262 2366                          xmlFreeNode(cur);
2263 2367                          return (Z_OK);
2264 2368                  }
2265 2369          }
2266 2370          return (Z_NO_RESOURCE_ID);
2267 2371  }
2268 2372  
2269 2373  int
2270 2374  zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
↓ open down ↓ 28 lines elided ↑ open up ↑
2299 2403  
2300 2404          if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
2301 2405                  return (err);
2302 2406  
2303 2407          if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
2304 2408                  return (err);
2305 2409  
2306 2410          return (Z_OK);
2307 2411  }
2308 2412  
     2413 +void
     2414 +zonecfg_free_res_attr_list(struct zone_res_attrtab *valtab)
     2415 +{
     2416 +        if (valtab == NULL)
     2417 +                return;
     2418 +        zonecfg_free_res_attr_list(valtab->zone_res_attr_next);
     2419 +        free(valtab);
     2420 +}
     2421 +
     2422 +int
     2423 +zonecfg_add_res_attr(struct zone_res_attrtab **headptr,
     2424 +    struct zone_res_attrtab *valtabptr)
     2425 +{
     2426 +        struct zone_res_attrtab *last, *old, *new;
     2427 +
     2428 +        last = *headptr;
     2429 +        for (old = last; old != NULL; old = old->zone_res_attr_next)
     2430 +                last = old;     /* walk to the end of the list */
     2431 +        new = valtabptr;        /* alloc'd by caller */
     2432 +        new->zone_res_attr_next = NULL;
     2433 +        if (last == NULL)
     2434 +                *headptr = new;
     2435 +        else
     2436 +                last->zone_res_attr_next = new;
     2437 +        return (Z_OK);
     2438 +}
     2439 +
     2440 +int
     2441 +zonecfg_remove_res_attr(struct zone_res_attrtab **headptr,
     2442 +    struct zone_res_attrtab *valtabptr)
     2443 +{
     2444 +        struct zone_res_attrtab *last, *this, *next;
     2445 +
     2446 +        last = *headptr;
     2447 +        for (this = last; this != NULL; this = this->zone_res_attr_next) {
     2448 +                if (strcmp(this->zone_res_attr_name,
     2449 +                    valtabptr->zone_res_attr_name) == 0 &&
     2450 +                    strcmp(this->zone_res_attr_value,
     2451 +                    valtabptr->zone_res_attr_value) == 0) {
     2452 +                        next = this->zone_res_attr_next;
     2453 +                        if (this == *headptr)
     2454 +                                *headptr = next;
     2455 +                        else
     2456 +                                last->zone_res_attr_next = next;
     2457 +                        free(this);
     2458 +                        return (Z_OK);
     2459 +                } else
     2460 +                        last = this;
     2461 +        }
     2462 +        return (Z_NO_PROPERTY_ID);
     2463 +}
     2464 +
2309 2465  /*
2310 2466   * Must be a comma-separated list of alpha-numeric file system names.
2311 2467   */
2312 2468  static int
2313 2469  zonecfg_valid_fs_allowed(const char *fsallowedp)
2314 2470  {
2315 2471          char tmp[ZONE_FS_ALLOWED_MAX];
2316 2472          char *cp = tmp;
2317 2473          char *p;
2318 2474  
↓ open down ↓ 129 lines elided ↑ open up ↑
2448 2604           * hostid.
2449 2605           */
2450 2606          if (hostidp == NULL || (err = zonecfg_valid_hostid(hostidp)) == Z_OK)
2451 2607                  return (setrootattr(handle, DTD_ATTR_HOSTID, hostidp));
2452 2608          return (err);
2453 2609  }
2454 2610  
2455 2611  int
2456 2612  zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2457 2613  {
2458      -        xmlNodePtr cur, firstmatch;
     2614 +        xmlNodePtr cur, val, firstmatch;
2459 2615          int err;
2460 2616          char match[MAXPATHLEN];
2461 2617  
2462 2618          if (tabptr == NULL)
2463 2619                  return (Z_INVAL);
2464 2620  
2465 2621          if ((err = operation_prep(handle)) != Z_OK)
2466 2622                  return (err);
2467 2623  
2468 2624          cur = handle->zone_dh_cur;
↓ open down ↓ 24 lines elided ↑ open up ↑
2493 2649          }
2494 2650          if (firstmatch == NULL)
2495 2651                  return (Z_NO_RESOURCE_ID);
2496 2652  
2497 2653          cur = firstmatch;
2498 2654  
2499 2655          if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
2500 2656              sizeof (tabptr->zone_dev_match))) != Z_OK)
2501 2657                  return (err);
2502 2658  
     2659 +        tabptr->zone_dev_attrp = NULL;
     2660 +        for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
     2661 +                struct zone_res_attrtab *valptr;
     2662 +
     2663 +                valptr = (struct zone_res_attrtab *)malloc(
     2664 +                    sizeof (struct zone_res_attrtab));
     2665 +                if (valptr == NULL)
     2666 +                        return (Z_NOMEM);
     2667 +
     2668 +                valptr->zone_res_attr_name[0] =
     2669 +                    valptr->zone_res_attr_value[0] = '\0';
     2670 +                if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr)
     2671 +                    != Z_OK) {
     2672 +                        free(valptr);
     2673 +                        break;
     2674 +                }
     2675 +
     2676 +                if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
     2677 +                    sizeof (valptr->zone_res_attr_name)) != Z_OK))
     2678 +                        break;
     2679 +                if ((fetchprop(val, DTD_ATTR_VALUE,
     2680 +                    valptr->zone_res_attr_value,
     2681 +                    sizeof (valptr->zone_res_attr_value)) != Z_OK))
     2682 +                        break;
     2683 +        }
     2684 +
2503 2685          return (Z_OK);
2504 2686  }
2505 2687  
2506 2688  static int
2507 2689  zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
2508 2690  {
2509      -        xmlNodePtr newnode, cur = handle->zone_dh_cur;
     2691 +        xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
     2692 +        struct zone_res_attrtab *valptr;
2510 2693          int err;
2511 2694  
2512 2695          newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
2513 2696  
2514 2697          if ((err = newprop(newnode, DTD_ATTR_MATCH,
2515 2698              tabptr->zone_dev_match)) != Z_OK)
2516 2699                  return (err);
2517 2700  
     2701 +        for (valptr = tabptr->zone_dev_attrp; valptr != NULL;
     2702 +            valptr = valptr->zone_res_attr_next) {
     2703 +                valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR,
     2704 +                    NULL);
     2705 +                err = newprop(valnode, DTD_ATTR_NAME,
     2706 +                    valptr->zone_res_attr_name);
     2707 +                if (err != Z_OK)
     2708 +                        return (err);
     2709 +                err = newprop(valnode, DTD_ATTR_VALUE,
     2710 +                    valptr->zone_res_attr_value);
     2711 +                if (err != Z_OK)
     2712 +                        return (err);
     2713 +        }
     2714 +
     2715 +
2518 2716          return (Z_OK);
2519 2717  }
2520 2718  
2521 2719  int
2522 2720  zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2523 2721  {
2524 2722          int err;
2525 2723  
2526 2724          if (tabptr == NULL)
2527 2725                  return (Z_INVAL);
↓ open down ↓ 2177 lines elided ↑ open up ↑
4705 4903  
4706 4904  int
4707 4905  zonecfg_setnwifent(zone_dochandle_t handle)
4708 4906  {
4709 4907          return (zonecfg_setent(handle));
4710 4908  }
4711 4909  
4712 4910  int
4713 4911  zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
4714 4912  {
4715      -        xmlNodePtr cur;
     4913 +        xmlNodePtr cur, val;
     4914 +        struct zone_res_attrtab *valptr;
4716 4915          int err;
4717 4916  
4718 4917          if (handle == NULL)
4719 4918                  return (Z_INVAL);
4720 4919  
4721 4920          if ((cur = handle->zone_dh_cur) == NULL)
4722 4921                  return (Z_NO_ENTRY);
4723 4922  
4724 4923          for (; cur != NULL; cur = cur->next)
4725 4924                  if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
↓ open down ↓ 15 lines elided ↑ open up ↑
4741 4940                  handle->zone_dh_cur = handle->zone_dh_top;
4742 4941                  return (err);
4743 4942          }
4744 4943  
4745 4944          if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
4746 4945              sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
4747 4946                  handle->zone_dh_cur = handle->zone_dh_top;
4748 4947                  return (err);
4749 4948          }
4750 4949  
     4950 +        if ((err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac,
     4951 +            sizeof (tabptr->zone_nwif_mac))) != Z_OK) {
     4952 +                handle->zone_dh_cur = handle->zone_dh_top;
     4953 +                return (err);
     4954 +        }
     4955 +
     4956 +        if ((err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id,
     4957 +            sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK) {
     4958 +                handle->zone_dh_cur = handle->zone_dh_top;
     4959 +                return (err);
     4960 +        }
     4961 +
     4962 +        if ((err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic,
     4963 +            sizeof (tabptr->zone_nwif_gnic))) != Z_OK) {
     4964 +                handle->zone_dh_cur = handle->zone_dh_top;
     4965 +                return (err);
     4966 +        }
     4967 +
4751 4968          if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
4752 4969              tabptr->zone_nwif_defrouter,
4753 4970              sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) {
4754 4971                  handle->zone_dh_cur = handle->zone_dh_top;
4755 4972                  return (err);
4756 4973          }
4757 4974  
     4975 +        tabptr->zone_nwif_attrp = NULL;
     4976 +        for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
     4977 +                valptr = (struct zone_res_attrtab *)malloc(
     4978 +                    sizeof (struct zone_res_attrtab));
     4979 +                if (valptr == NULL)
     4980 +                        return (Z_NOMEM);
     4981 +
     4982 +                valptr->zone_res_attr_name[0] =
     4983 +                    valptr->zone_res_attr_value[0] = '\0';
     4984 +                if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr)
     4985 +                    != Z_OK) {
     4986 +                        free(valptr);
     4987 +                        break;
     4988 +                }
     4989 +
     4990 +                if (fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
     4991 +                    sizeof (valptr->zone_res_attr_name)) != Z_OK)
     4992 +                        break;
     4993 +                if (fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value,
     4994 +                    sizeof (valptr->zone_res_attr_value)) != Z_OK)
     4995 +                        break;
     4996 +        }
     4997 +
4758 4998          handle->zone_dh_cur = cur->next;
4759 4999          return (Z_OK);
4760 5000  }
4761 5001  
4762 5002  int
4763 5003  zonecfg_endnwifent(zone_dochandle_t handle)
4764 5004  {
4765 5005          return (zonecfg_endent(handle));
4766 5006  }
4767 5007  
4768 5008  int
4769 5009  zonecfg_setdevent(zone_dochandle_t handle)
4770 5010  {
4771 5011          return (zonecfg_setent(handle));
4772 5012  }
4773 5013  
4774 5014  int
4775 5015  zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
4776 5016  {
4777      -        xmlNodePtr cur;
     5017 +        xmlNodePtr cur, val;
4778 5018          int err;
4779 5019  
4780 5020          if (handle == NULL)
4781 5021                  return (Z_INVAL);
4782 5022  
4783 5023          if ((cur = handle->zone_dh_cur) == NULL)
4784 5024                  return (Z_NO_ENTRY);
4785 5025  
4786 5026          for (; cur != NULL; cur = cur->next)
4787 5027                  if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
↓ open down ↓ 2 lines elided ↑ open up ↑
4790 5030                  handle->zone_dh_cur = handle->zone_dh_top;
4791 5031                  return (Z_NO_ENTRY);
4792 5032          }
4793 5033  
4794 5034          if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
4795 5035              sizeof (tabptr->zone_dev_match))) != Z_OK) {
4796 5036                  handle->zone_dh_cur = handle->zone_dh_top;
4797 5037                  return (err);
4798 5038          }
4799 5039  
     5040 +        tabptr->zone_dev_attrp = NULL;
     5041 +        for (val = cur->xmlChildrenNode; val != NULL; val = val->next) {
     5042 +                struct zone_res_attrtab *valptr;
     5043 +
     5044 +                valptr = (struct zone_res_attrtab *)malloc(
     5045 +                    sizeof (struct zone_res_attrtab));
     5046 +                if (valptr == NULL)
     5047 +                        return (Z_NOMEM);
     5048 +
     5049 +                valptr->zone_res_attr_name[0] =
     5050 +                    valptr->zone_res_attr_value[0] = '\0';
     5051 +                if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr)
     5052 +                    != Z_OK) {
     5053 +                        free(valptr);
     5054 +                        break;
     5055 +                }
     5056 +
     5057 +                if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name,
     5058 +                    sizeof (valptr->zone_res_attr_name)) != Z_OK))
     5059 +                        break;
     5060 +                if ((fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value,
     5061 +                    sizeof (valptr->zone_res_attr_value)) != Z_OK))
     5062 +                        break;
     5063 +        }
     5064 +
4800 5065          handle->zone_dh_cur = cur->next;
4801 5066          return (Z_OK);
4802 5067  }
4803 5068  
4804 5069  int
4805 5070  zonecfg_enddevent(zone_dochandle_t handle)
4806 5071  {
4807 5072          return (zonecfg_endent(handle));
4808 5073  }
4809 5074  
↓ open down ↓ 708 lines elided ↑ open up ↑
5518 5783  
5519 5784          err = zonecfg_get_handle((char *)zone_name, handle);
5520 5785          if (err == Z_OK)
5521 5786                  err = zonecfg_get_brand(handle, brandname, rp_sz);
5522 5787  
5523 5788          zonecfg_fini_handle(handle);
5524 5789          return (err);
5525 5790  }
5526 5791  
5527 5792  /*
     5793 + * Atomically get a new zone_did value.  The currently allocated value
     5794 + * is stored in /etc/zones/did.txt.  Lock the file, read the current value,
     5795 + * increment, save the new value and unlock the file.  Return the new value
     5796 + * or -1 if there was an error.  The ID namespace is large enough that we
     5797 + * don't worry about recycling an ID when a zone is deleted.
     5798 + */
     5799 +static zoneid_t
     5800 +new_zone_did()
     5801 +{
     5802 +        int fd;
     5803 +        int len;
     5804 +        int val;
     5805 +        struct flock lck;
     5806 +        char buf[80];
     5807 +
     5808 +        if ((fd = open(DEBUGID_FILE, O_RDWR | O_CREAT,
     5809 +            S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
     5810 +                perror("new_zone_did open failed");
     5811 +                return (-1);
     5812 +        }
     5813 +
     5814 +        /* Initialize the lock. */
     5815 +        lck.l_whence = SEEK_SET;
     5816 +        lck.l_start = 0;
     5817 +        lck.l_len = 0;
     5818 +
     5819 +        /* Wait until we acquire an exclusive lock on the file. */
     5820 +        lck.l_type = F_WRLCK;
     5821 +        if (fcntl(fd, F_SETLKW, &lck) == -1) {
     5822 +                perror("new_zone_did lock failed");
     5823 +                (void) close(fd);
     5824 +                return (-1);
     5825 +        }
     5826 +
     5827 +        /* Get currently allocated value */
     5828 +        len = read(fd, buf, sizeof (buf));
     5829 +        if (len == -1) {
     5830 +                perror("new_zone_did read failed");
     5831 +                val = -1;
     5832 +        } else {
     5833 +                if (lseek(fd, 0L, SEEK_SET) == -1) {
     5834 +                        perror("new_zone_did seek failed");
     5835 +                        val = -1;
     5836 +                } else {
     5837 +                        if (len == 0) {
     5838 +                                /* Just created the file, initialize at 1 */
     5839 +                                val = 1;
     5840 +                        } else {
     5841 +                                val = atoi(buf);
     5842 +                                val++;
     5843 +                        }
     5844 +
     5845 +                        (void) snprintf(buf, sizeof (buf), "%d\n", val);
     5846 +                        len = strlen(buf);
     5847 +
     5848 +                        /* Save newly allocated value */
     5849 +                        if (write(fd, buf, len) == -1) {
     5850 +                                perror("new_zone_did write failed");
     5851 +                                val = -1;
     5852 +                        }
     5853 +                }
     5854 +        }
     5855 +
     5856 +        /* Release the file lock. */
     5857 +        lck.l_type = F_UNLCK;
     5858 +        if (fcntl(fd, F_SETLK, &lck) == -1) {
     5859 +                perror("new_zone_did unlock failed");
     5860 +                val = -1;
     5861 +        }
     5862 +
     5863 +        if (close(fd) != 0)
     5864 +                perror("new_zone_did close failed");
     5865 +
     5866 +        return (val);
     5867 +}
     5868 +
     5869 +/*
     5870 + * Called by zoneadmd to get the zone's debug ID.
     5871 + * If the zone doesn't already have an ID, a new one is generated and
     5872 + * persistently saved onto the zone.  Normally either zoneadm or zonecfg
     5873 + * will assign a new ID for the zone, so zoneadmd should never have to
     5874 + * generate one, but we also handle that here just to be paranoid.
     5875 + */
     5876 +zoneid_t
     5877 +zone_get_did(char *zone_name)
     5878 +{
     5879 +        int res;
     5880 +        zoneid_t new_did;
     5881 +        zone_dochandle_t handle;
     5882 +        char did_str[80];
     5883 +
     5884 +        if ((handle = zonecfg_init_handle()) == NULL)
     5885 +                return (getpid());
     5886 +
     5887 +        if (zonecfg_get_handle((char *)zone_name, handle) != Z_OK)
     5888 +                return (getpid());
     5889 +
     5890 +        res = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str));
     5891 +
     5892 +        /* If the zone already has an assigned debug ID, return it. */
     5893 +        if (res == Z_OK && did_str[0] != '\0') {
     5894 +                zonecfg_fini_handle(handle);
     5895 +                return (atoi(did_str));
     5896 +        }
     5897 +
     5898 +        /*
     5899 +         * The zone doesn't have an assigned debug ID yet, generate one and
     5900 +         * save it as part of the zone definition.
     5901 +         */
     5902 +        if ((new_did = new_zone_did()) == -1) {
     5903 +                /*
     5904 +                 * We should really never hit this block of code.
     5905 +                 * Generating a new ID failed for some reason.  Use the current
     5906 +                 * pid as a temporary ID so that the zone can continue to boot
     5907 +                 * but we don't persistently save this temporary ID on the zone.
     5908 +                 */
     5909 +                zonecfg_fini_handle(handle);
     5910 +                return (getpid());
     5911 +        }
     5912 +
     5913 +        /* Now persistently save this new ID onto the zone. */
     5914 +        (void) snprintf(did_str, sizeof (did_str), "%d", new_did);
     5915 +        (void) setrootattr(handle, DTD_ATTR_DID, did_str);
     5916 +        (void) zonecfg_save(handle);
     5917 +
     5918 +        zonecfg_fini_handle(handle);
     5919 +        return (new_did);
     5920 +}
     5921 +
     5922 +zoneid_t
     5923 +zonecfg_get_did(zone_dochandle_t handle)
     5924 +{
     5925 +        char did_str[80];
     5926 +        int err;
     5927 +        zoneid_t did;
     5928 +
     5929 +        err = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str));
     5930 +        if (err == Z_OK && did_str[0] != '\0')
     5931 +                did = atoi(did_str);
     5932 +        else
     5933 +                did = -1;
     5934 +
     5935 +        return (did);
     5936 +}
     5937 +
     5938 +void
     5939 +zonecfg_set_did(zone_dochandle_t handle)
     5940 +{
     5941 +        zoneid_t new_did;
     5942 +        char did_str[80];
     5943 +
     5944 +        if ((new_did = new_zone_did()) == -1)
     5945 +                return;
     5946 +        (void) snprintf(did_str, sizeof (did_str), "%d", new_did);
     5947 +        (void) setrootattr(handle, DTD_ATTR_DID, did_str);
     5948 +}
     5949 +
     5950 +/*
5528 5951   * Return the appropriate root for the active /dev.
5529 5952   * For normal zone, the path is $ZONEPATH/root;
5530 5953   * for scratch zone, the dev path is $ZONEPATH/lu.
5531 5954   */
5532 5955  int
5533 5956  zone_get_devroot(char *zone_name, char *devroot, size_t rp_sz)
5534 5957  {
5535 5958          int err;
5536 5959          char *suffix;
5537 5960          zone_state_t state;
↓ open down ↓ 1294 lines elided ↑ open up ↑
6832 7255          if ((err = zonecfg_setent(handle)) != Z_OK)
6833 7256                  return (err);
6834 7257  
6835 7258          err = zonecfg_lookup_pset(handle, tabptr);
6836 7259  
6837 7260          (void) zonecfg_endent(handle);
6838 7261  
6839 7262          return (err);
6840 7263  }
6841 7264  
6842      -static int
6843      -add_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
6844      -{
6845      -        xmlNodePtr newnode, cur = handle->zone_dh_cur;
6846      -        int err;
6847      -
6848      -        newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_MCAP, NULL);
6849      -        if ((err = newprop(newnode, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap))
6850      -            != Z_OK)
6851      -                return (err);
6852      -
6853      -        return (Z_OK);
6854      -}
6855      -
     7265 +/*
     7266 + * Cleanup obsolete constructs in the configuration.
     7267 + * Return true of the config has been updated and must be commited.
     7268 + */
6856 7269  int
6857      -zonecfg_delete_mcap(zone_dochandle_t handle)
     7270 +zonecfg_fix_obsolete(zone_dochandle_t handle)
6858 7271  {
6859      -        int err;
6860      -        xmlNodePtr cur = handle->zone_dh_cur;
6861      -
6862      -        if ((err = operation_prep(handle)) != Z_OK)
6863      -                return (err);
6864      -
6865      -        for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
6866      -                if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
6867      -                        continue;
6868      -
6869      -                xmlUnlinkNode(cur);
6870      -                xmlFreeNode(cur);
6871      -                return (Z_OK);
6872      -        }
6873      -        return (Z_NO_RESOURCE_ID);
6874      -}
6875      -
6876      -int
6877      -zonecfg_modify_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
6878      -{
6879      -        int err;
6880      -
6881      -        if (tabptr == NULL)
6882      -                return (Z_INVAL);
6883      -
6884      -        err = zonecfg_delete_mcap(handle);
6885      -        /* it is ok if there is no mcap entry */
6886      -        if (err != Z_OK && err != Z_NO_RESOURCE_ID)
6887      -                return (err);
6888      -
6889      -        if ((err = add_mcap(handle, tabptr)) != Z_OK)
6890      -                return (err);
6891      -
6892      -        return (Z_OK);
6893      -}
6894      -
6895      -int
6896      -zonecfg_lookup_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
6897      -{
     7272 +        int res = 0;
     7273 +        int add_physmem_rctl = 0;
6898 7274          xmlNodePtr cur;
6899      -        int err;
     7275 +        char    zone_physmem_cap[MAXNAMELEN];
6900 7276  
6901      -        if (tabptr == NULL)
6902      -                return (Z_INVAL);
     7277 +        if (operation_prep(handle) != Z_OK)
     7278 +                return (res);
6903 7279  
6904      -        if ((err = operation_prep(handle)) != Z_OK)
6905      -                return (err);
6906      -
     7280 +        /*
     7281 +         * If an obsolete mcap entry exists, convert it to the rctl.
     7282 +         */
6907 7283          cur = handle->zone_dh_cur;
6908 7284          for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
6909 7285                  if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0)
6910 7286                          continue;
6911      -                if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP,
6912      -                    tabptr->zone_physmem_cap,
6913      -                    sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
6914      -                        handle->zone_dh_cur = handle->zone_dh_top;
6915      -                        return (err);
     7287 +
     7288 +                if (fetchprop(cur, DTD_ATTR_PHYSCAP,
     7289 +                    zone_physmem_cap, sizeof (zone_physmem_cap)) == Z_OK) {
     7290 +                        res = 1;
     7291 +                        add_physmem_rctl = 1;
6916 7292                  }
6917 7293  
6918      -                return (Z_OK);
     7294 +                xmlUnlinkNode(cur);
     7295 +                xmlFreeNode(cur);
     7296 +                break;
6919 7297          }
6920 7298  
6921      -        return (Z_NO_ENTRY);
6922      -}
     7299 +        if (add_physmem_rctl) {
     7300 +                uint64_t cap;
     7301 +                char *endp;
6923 7302  
6924      -static int
6925      -getmcapent_core(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
6926      -{
6927      -        xmlNodePtr cur;
6928      -        int err;
6929      -
6930      -        if (handle == NULL)
6931      -                return (Z_INVAL);
6932      -
6933      -        if ((cur = handle->zone_dh_cur) == NULL)
6934      -                return (Z_NO_ENTRY);
6935      -
6936      -        for (; cur != NULL; cur = cur->next)
6937      -                if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) == 0)
6938      -                        break;
6939      -        if (cur == NULL) {
6940      -                handle->zone_dh_cur = handle->zone_dh_top;
6941      -                return (Z_NO_ENTRY);
     7303 +                cap = strtoull(zone_physmem_cap, &endp, 10);
     7304 +                (void) zonecfg_set_aliased_rctl(handle, ALIAS_MAXPHYSMEM, cap);
6942 7305          }
6943 7306  
6944      -        if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap,
6945      -            sizeof (tabptr->zone_physmem_cap))) != Z_OK) {
6946      -                handle->zone_dh_cur = handle->zone_dh_top;
6947      -                return (err);
6948      -        }
6949      -
6950      -        handle->zone_dh_cur = cur->next;
6951      -        return (Z_OK);
     7307 +        return (res);
6952 7308  }
6953 7309  
6954      -int
6955      -zonecfg_getmcapent(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
6956      -{
6957      -        int err;
6958      -
6959      -        if ((err = zonecfg_setent(handle)) != Z_OK)
6960      -                return (err);
6961      -
6962      -        err = getmcapent_core(handle, tabptr);
6963      -
6964      -        (void) zonecfg_endent(handle);
6965      -
6966      -        return (err);
6967      -}
6968      -
6969 7310  /*
6970 7311   * Get the full tree of pkg metadata in a set of nested AVL trees.
6971 7312   * pkgs_avl is an AVL tree of pkgs.
6972 7313   *
6973 7314   * The zone xml data contains DTD_ELEM_PACKAGE elements.
6974 7315   */
6975 7316  int
6976 7317  zonecfg_getpkgdata(zone_dochandle_t handle, uu_avl_pool_t *pkg_pool,
6977 7318      uu_avl_t *pkgs_avl)
6978 7319  {
↓ open down ↓ 645 lines elided ↑ open up ↑
7624 7965                  if (errno == ENOENT)
7625 7966                          return (Z_NO_ZONE);
7626 7967                  return (Z_MISC_FS);
7627 7968          }
7628 7969          if ((err = fstat(fileno(uaf), &ua_st)) != 0) {
7629 7970                  zerror(zonename, gettext("could not stat file %s: %s"),
7630 7971                      USERATTR_FILENAME, strerror(errno));
7631 7972                  (void) fclose(uaf);
7632 7973                  return (Z_MISC_FS);
7633 7974          }
7634      -        if (!config_file_path(zonename, config_file)) {
     7975 +        if (!config_file_path(zonename, config_file, sizeof (config_file))) {
7635 7976                  (void) fclose(uaf);
7636 7977                  return (Z_MISC_FS);
7637 7978          }
7638 7979  
7639 7980          if ((err = stat(config_file, &config_st)) != 0) {
7640 7981                  zerror(zonename, gettext("could not stat file %s: %s"),
7641 7982                      config_file, strerror(errno));
7642 7983                  (void) fclose(uaf);
7643 7984                  return (Z_MISC_FS);
7644 7985          }
↓ open down ↓ 421 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX