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


  65 
  66 #include <arpa/inet.h>
  67 #include <netdb.h>
  68 
  69 #include <libxml/xmlmemory.h>
  70 #include <libxml/parser.h>
  71 
  72 #include <libdevinfo.h>
  73 #include <uuid/uuid.h>
  74 #include <dirent.h>
  75 #include <libbrand.h>
  76 
  77 #include <libzonecfg.h>
  78 #include "zonecfg_impl.h"
  79 
  80 #define _PATH_TMPFILE   "/zonecfg.XXXXXX"
  81 #define ZONE_CB_RETRY_COUNT             10
  82 #define ZONE_EVENT_PING_SUBCLASS        "ping"
  83 #define ZONE_EVENT_PING_PUBLISHER       "solaris"
  84 


  85 /* Hard-code the DTD element/attribute/entity names just once, here. */
  86 #define DTD_ELEM_ATTR           (const xmlChar *) "attr"
  87 #define DTD_ELEM_COMMENT        (const xmlChar *) "comment"
  88 #define DTD_ELEM_DEVICE         (const xmlChar *) "device"
  89 #define DTD_ELEM_FS             (const xmlChar *) "filesystem"
  90 #define DTD_ELEM_FSOPTION       (const xmlChar *) "fsoption"
  91 #define DTD_ELEM_NET            (const xmlChar *) "network"

  92 #define DTD_ELEM_RCTL           (const xmlChar *) "rctl"
  93 #define DTD_ELEM_RCTLVALUE      (const xmlChar *) "rctl-value"
  94 #define DTD_ELEM_ZONE           (const xmlChar *) "zone"
  95 #define DTD_ELEM_DATASET        (const xmlChar *) "dataset"
  96 #define DTD_ELEM_TMPPOOL        (const xmlChar *) "tmp_pool"
  97 #define DTD_ELEM_PSET           (const xmlChar *) "pset"
  98 #define DTD_ELEM_MCAP           (const xmlChar *) "mcap"
  99 #define DTD_ELEM_PACKAGE        (const xmlChar *) "package"
 100 #define DTD_ELEM_OBSOLETES      (const xmlChar *) "obsoletes"
 101 #define DTD_ELEM_DEV_PERM       (const xmlChar *) "dev-perm"
 102 #define DTD_ELEM_ADMIN          (const xmlChar *) "admin"
 103 
 104 #define DTD_ATTR_ACTION         (const xmlChar *) "action"
 105 #define DTD_ATTR_ADDRESS        (const xmlChar *) "address"
 106 #define DTD_ATTR_ALLOWED_ADDRESS        (const xmlChar *) "allowed-address"
 107 #define DTD_ATTR_AUTOBOOT       (const xmlChar *) "autoboot"
 108 #define DTD_ATTR_IPTYPE         (const xmlChar *) "ip-type"
 109 #define DTD_ATTR_DEFROUTER      (const xmlChar *) "defrouter"
 110 #define DTD_ATTR_DIR            (const xmlChar *) "directory"

 111 #define DTD_ATTR_LIMIT          (const xmlChar *) "limit"
 112 #define DTD_ATTR_LIMITPRIV      (const xmlChar *) "limitpriv"
 113 #define DTD_ATTR_BOOTARGS       (const xmlChar *) "bootargs"
 114 #define DTD_ATTR_SCHED          (const xmlChar *) "scheduling-class"

 115 #define DTD_ATTR_MATCH          (const xmlChar *) "match"
 116 #define DTD_ATTR_NAME           (const xmlChar *) "name"
 117 #define DTD_ATTR_PHYSICAL       (const xmlChar *) "physical"
 118 #define DTD_ATTR_POOL           (const xmlChar *) "pool"
 119 #define DTD_ATTR_PRIV           (const xmlChar *) "priv"
 120 #define DTD_ATTR_RAW            (const xmlChar *) "raw"
 121 #define DTD_ATTR_SPECIAL        (const xmlChar *) "special"
 122 #define DTD_ATTR_TYPE           (const xmlChar *) "type"
 123 #define DTD_ATTR_VALUE          (const xmlChar *) "value"

 124 #define DTD_ATTR_ZONEPATH       (const xmlChar *) "zonepath"
 125 #define DTD_ATTR_NCPU_MIN       (const xmlChar *) "ncpu_min"
 126 #define DTD_ATTR_NCPU_MAX       (const xmlChar *) "ncpu_max"
 127 #define DTD_ATTR_IMPORTANCE     (const xmlChar *) "importance"
 128 #define DTD_ATTR_PHYSCAP        (const xmlChar *) "physcap"
 129 #define DTD_ATTR_VERSION        (const xmlChar *) "version"
 130 #define DTD_ATTR_ID             (const xmlChar *) "id"
 131 #define DTD_ATTR_UID            (const xmlChar *) "uid"
 132 #define DTD_ATTR_GID            (const xmlChar *) "gid"
 133 #define DTD_ATTR_MODE           (const xmlChar *) "mode"
 134 #define DTD_ATTR_ACL            (const xmlChar *) "acl"
 135 #define DTD_ATTR_BRAND          (const xmlChar *) "brand"

 136 #define DTD_ATTR_HOSTID         (const xmlChar *) "hostid"
 137 #define DTD_ATTR_USER           (const xmlChar *) "user"
 138 #define DTD_ATTR_AUTHS          (const xmlChar *) "auths"
 139 #define DTD_ATTR_FS_ALLOWED     (const xmlChar *) "fs-allowed"
 140 
 141 #define DTD_ENTITY_BOOLEAN      "boolean"
 142 #define DTD_ENTITY_DEVPATH      "devpath"
 143 #define DTD_ENTITY_DRIVER       "driver"
 144 #define DTD_ENTITY_DRVMIN       "drv_min"
 145 #define DTD_ENTITY_FALSE        "false"
 146 #define DTD_ENTITY_INT          "int"
 147 #define DTD_ENTITY_STRING       "string"
 148 #define DTD_ENTITY_TRUE         "true"
 149 #define DTD_ENTITY_UINT         "uint"
 150 
 151 #define DTD_ENTITY_BOOL_LEN     6       /* "false" */
 152 
 153 #define ATTACH_FORCED   "SUNWattached.xml"
 154 
 155 #define TMP_POOL_NAME   "SUNWtmp_%s"


2073 
2074 /*
2075  * Determines whether there is a net resource with the physical interface, IP
2076  * address, and default router specified by 'tabptr' in the zone configuration
2077  * to which 'handle' refers.  'tabptr' must have an interface, an address, a
2078  * default router, or a combination of the three.  This function returns Z_OK
2079  * iff there is exactly one net resource matching the query specified by
2080  * 'tabptr'.  The function returns Z_INSUFFICIENT_SPEC if there are multiple
2081  * matches or 'tabptr' does not specify a physical interface, address, or
2082  * default router.  The function returns Z_NO_RESOURCE_ID if are no matches.
2083  *
2084  * Errors might also be returned if the entry that exactly matches the
2085  * query lacks critical network resource information.
2086  *
2087  * If there is a single match, then the matching entry's physical interface, IP
2088  * address, and default router information are stored in 'tabptr'.
2089  */
2090 int
2091 zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2092 {
2093         xmlNodePtr cur;
2094         xmlNodePtr firstmatch;
2095         int err;
2096         char address[INET6_ADDRSTRLEN];
2097         char physical[LIFNAMSIZ];


2098         size_t addrspec;                /* nonzero if tabptr has IP addr */
2099         size_t physspec;                /* nonzero if tabptr has interface */


2100         size_t defrouterspec;           /* nonzero if tabptr has def. router */
2101         size_t allowed_addrspec;
2102         zone_iptype_t iptype;
2103 
2104         if (tabptr == NULL)
2105                 return (Z_INVAL);
2106 
2107         /*
2108          * Determine the fields that will be searched.  There must be at least
2109          * one.
2110          *
2111          * zone_nwif_address, zone_nwif_physical, and zone_nwif_defrouter are

2112          * arrays, so no NULL checks are necessary.
2113          */
2114         addrspec = strlen(tabptr->zone_nwif_address);
2115         physspec = strlen(tabptr->zone_nwif_physical);


2116         defrouterspec = strlen(tabptr->zone_nwif_defrouter);
2117         allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address);
2118         if (addrspec != 0 && allowed_addrspec != 0)
2119                 return (Z_INVAL); /* can't specify both */
2120         if (addrspec == 0 && physspec == 0 && defrouterspec == 0 &&
2121             allowed_addrspec == 0)
2122                 return (Z_INSUFFICIENT_SPEC);
2123 
2124         if ((err = operation_prep(handle)) != Z_OK)
2125                 return (err);
2126 
2127         if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK)
2128                 return (err);
2129         /*
2130          * Iterate over the configuration's elements and look for net elements
2131          * that match the query.
2132          */
2133         firstmatch = NULL;
2134         cur = handle->zone_dh_cur;
2135         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2136                 /* Skip non-net elements */
2137                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2138                         continue;
2139 
2140                 /*
2141                  * If any relevant fields don't match the query, then skip
2142                  * the current net element.
2143                  */
2144                 if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
2145                     physical, sizeof (physical)) != Z_OK ||
2146                     strcmp(tabptr->zone_nwif_physical, physical) != 0))
2147                         continue;









2148                 if (iptype == ZS_SHARED && addrspec != 0 &&
2149                     (fetchprop(cur, DTD_ATTR_ADDRESS, address,
2150                     sizeof (address)) != Z_OK ||
2151                     !zonecfg_same_net_address(tabptr->zone_nwif_address,
2152                     address)))
2153                         continue;
2154                 if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2155                     (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2156                     sizeof (address)) != Z_OK ||
2157                     !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
2158                     address)))
2159                         continue;
2160                 if (defrouterspec != 0 && (fetchprop(cur, DTD_ATTR_DEFROUTER,
2161                     address, sizeof (address)) != Z_OK ||
2162                     !zonecfg_same_net_address(tabptr->zone_nwif_defrouter,
2163                     address)))
2164                         continue;
2165 
2166                 /*
2167                  * The current net element matches the query.  Select it if


2170                 if (firstmatch == NULL)
2171                         firstmatch = cur;
2172                 else
2173                         return (Z_INSUFFICIENT_SPEC);
2174         }
2175         if (firstmatch == NULL)
2176                 return (Z_NO_RESOURCE_ID);
2177 
2178         cur = firstmatch;
2179 
2180         if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
2181             sizeof (tabptr->zone_nwif_physical))) != Z_OK)
2182                 return (err);
2183 
2184         if (iptype == ZS_SHARED &&
2185             (err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
2186             sizeof (tabptr->zone_nwif_address))) != Z_OK)
2187                 return (err);
2188 
2189         if (iptype == ZS_EXCLUSIVE &&















2190             (err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2191             tabptr->zone_nwif_allowed_address,
2192             sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK)
2193                 return (err);
2194 
2195         if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
2196             tabptr->zone_nwif_defrouter,
2197             sizeof (tabptr->zone_nwif_defrouter))) != Z_OK)
2198                 return (err);
2199 


























2200         return (Z_OK);
2201 }
2202 
2203 static int
2204 zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2205 {
2206         xmlNodePtr newnode, cur = handle->zone_dh_cur;

2207         int err;
2208 
2209         newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
2210         if (strlen(tabptr->zone_nwif_address) > 0 &&
2211             (err = newprop(newnode, DTD_ATTR_ADDRESS,
2212             tabptr->zone_nwif_address)) != Z_OK)
2213                 return (err);
2214         if (strlen(tabptr->zone_nwif_allowed_address) > 0 &&
2215             (err = newprop(newnode, DTD_ATTR_ALLOWED_ADDRESS,
2216             tabptr->zone_nwif_allowed_address)) != Z_OK)
2217                 return (err);
2218         if ((err = newprop(newnode, DTD_ATTR_PHYSICAL,
2219             tabptr->zone_nwif_physical)) != Z_OK)
2220                 return (err);
2221         /*
2222          * Do not add this property when it is not set, for backwards
2223          * compatibility and because it is optional.
2224          */
2225         if ((strlen(tabptr->zone_nwif_defrouter) > 0) &&
2226             ((err = newprop(newnode, DTD_ATTR_DEFROUTER,
2227             tabptr->zone_nwif_defrouter)) != Z_OK))
2228                 return (err);



























2229         return (Z_OK);
2230 }
2231 
2232 int
2233 zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2234 {
2235         int err;
2236 
2237         if (tabptr == NULL)
2238                 return (Z_INVAL);
2239 
2240         if ((err = operation_prep(handle)) != Z_OK)
2241                 return (err);
2242 
2243         if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
2244                 return (err);
2245 
2246         return (Z_OK);
2247 }
2248 
2249 static int
2250 zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2251 {
2252         xmlNodePtr cur = handle->zone_dh_cur;
2253         boolean_t addr_match, phys_match, allowed_addr_match;

2254 
2255         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2256                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2257                         continue;
2258 
2259                 addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
2260                     tabptr->zone_nwif_address);
2261                 allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2262                     tabptr->zone_nwif_allowed_address);
2263                 phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
2264                     tabptr->zone_nwif_physical);




2265 
2266                 if (addr_match && allowed_addr_match && phys_match) {

2267                         xmlUnlinkNode(cur);
2268                         xmlFreeNode(cur);
2269                         return (Z_OK);
2270                 }
2271         }
2272         return (Z_NO_RESOURCE_ID);
2273 }
2274 
2275 int
2276 zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2277 {
2278         int err;
2279 
2280         if (tabptr == NULL)
2281                 return (Z_INVAL);
2282 
2283         if ((err = operation_prep(handle)) != Z_OK)
2284                 return (err);
2285 
2286         if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK)


2295         struct zone_nwiftab *oldtabptr,
2296         struct zone_nwiftab *newtabptr)
2297 {
2298         int err;
2299 
2300         if (oldtabptr == NULL || newtabptr == NULL)
2301                 return (Z_INVAL);
2302 
2303         if ((err = operation_prep(handle)) != Z_OK)
2304                 return (err);
2305 
2306         if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
2307                 return (err);
2308 
2309         if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
2310                 return (err);
2311 
2312         return (Z_OK);
2313 }
2314 




















































2315 /*
2316  * Must be a comma-separated list of alpha-numeric file system names.
2317  */
2318 static int
2319 zonecfg_valid_fs_allowed(const char *fsallowedp)
2320 {
2321         char tmp[ZONE_FS_ALLOWED_MAX];
2322         char *cp = tmp;
2323         char *p;
2324 
2325         if (strlen(fsallowedp) > ZONE_FS_ALLOWED_MAX)
2326                 return (Z_TOO_BIG);
2327 
2328         (void) strlcpy(tmp, fsallowedp, sizeof (tmp));
2329 
2330         while (*cp != '\0') {
2331                 p = cp;
2332                 while (*p != '\0' && *p != ',') {
2333                         if (!isalnum(*p) && *p != '-')
2334                                 return (Z_INVALID_PROPERTY);


2444  * attribute is cleared.  Non-NULL hostids are validated.  This function returns
2445  * Z_OK on success.  Any other return value indicates failure.
2446  */
2447 int
2448 zonecfg_set_hostid(zone_dochandle_t handle, const char *hostidp)
2449 {
2450         int err;
2451 
2452         /*
2453          * A NULL hostid string is interpreted as a request to clear the
2454          * hostid.
2455          */
2456         if (hostidp == NULL || (err = zonecfg_valid_hostid(hostidp)) == Z_OK)
2457                 return (setrootattr(handle, DTD_ATTR_HOSTID, hostidp));
2458         return (err);
2459 }
2460 
2461 int
2462 zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2463 {
2464         xmlNodePtr cur, firstmatch;
2465         int err;
2466         char match[MAXPATHLEN];
2467 
2468         if (tabptr == NULL)
2469                 return (Z_INVAL);
2470 
2471         if ((err = operation_prep(handle)) != Z_OK)
2472                 return (err);
2473 
2474         cur = handle->zone_dh_cur;
2475         firstmatch = NULL;
2476         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2477                 if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
2478                         continue;
2479                 if (strlen(tabptr->zone_dev_match) == 0)
2480                         continue;
2481 
2482                 if ((fetchprop(cur, DTD_ATTR_MATCH, match,
2483                     sizeof (match)) == Z_OK)) {
2484                         if (strcmp(tabptr->zone_dev_match,


2489                                         return (Z_INSUFFICIENT_SPEC);
2490                         } else {
2491                                 /*
2492                                  * If another property matched but this
2493                                  * one doesn't then reset firstmatch.
2494                                  */
2495                                 if (firstmatch == cur)
2496                                         firstmatch = NULL;
2497                         }
2498                 }
2499         }
2500         if (firstmatch == NULL)
2501                 return (Z_NO_RESOURCE_ID);
2502 
2503         cur = firstmatch;
2504 
2505         if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
2506             sizeof (tabptr->zone_dev_match))) != Z_OK)
2507                 return (err);
2508 


























2509         return (Z_OK);
2510 }
2511 
2512 static int
2513 zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
2514 {
2515         xmlNodePtr newnode, cur = handle->zone_dh_cur;

2516         int err;
2517 
2518         newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
2519 
2520         if ((err = newprop(newnode, DTD_ATTR_MATCH,
2521             tabptr->zone_dev_match)) != Z_OK)
2522                 return (err);
2523 















2524         return (Z_OK);
2525 }
2526 
2527 int
2528 zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2529 {
2530         int err;
2531 
2532         if (tabptr == NULL)
2533                 return (Z_INVAL);
2534 
2535         if ((err = operation_prep(handle)) != Z_OK)
2536                 return (err);
2537 
2538         if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK)
2539                 return (err);
2540 
2541         return (Z_OK);
2542 }
2543 


4701 
4702         handle->zone_dh_cur = cur->next;
4703         return (Z_OK);
4704 }
4705 
4706 int
4707 zonecfg_endfsent(zone_dochandle_t handle)
4708 {
4709         return (zonecfg_endent(handle));
4710 }
4711 
4712 int
4713 zonecfg_setnwifent(zone_dochandle_t handle)
4714 {
4715         return (zonecfg_setent(handle));
4716 }
4717 
4718 int
4719 zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
4720 {
4721         xmlNodePtr cur;

4722         int err;
4723 
4724         if (handle == NULL)
4725                 return (Z_INVAL);
4726 
4727         if ((cur = handle->zone_dh_cur) == NULL)
4728                 return (Z_NO_ENTRY);
4729 
4730         for (; cur != NULL; cur = cur->next)
4731                 if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
4732                         break;
4733         if (cur == NULL) {
4734                 handle->zone_dh_cur = handle->zone_dh_top;
4735                 return (Z_NO_ENTRY);
4736         }
4737 
4738         if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
4739             sizeof (tabptr->zone_nwif_address))) != Z_OK) {
4740                 handle->zone_dh_cur = handle->zone_dh_top;
4741                 return (err);
4742         }
4743 
4744         if ((err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
4745             tabptr->zone_nwif_allowed_address,
4746             sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK) {
4747                 handle->zone_dh_cur = handle->zone_dh_top;
4748                 return (err);
4749         }
4750 
4751         if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
4752             sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
4753                 handle->zone_dh_cur = handle->zone_dh_top;
4754                 return (err);
4755         }
4756 


















4757         if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
4758             tabptr->zone_nwif_defrouter,
4759             sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) {
4760                 handle->zone_dh_cur = handle->zone_dh_top;
4761                 return (err);
4762         }
4763 























4764         handle->zone_dh_cur = cur->next;
4765         return (Z_OK);
4766 }
4767 
4768 int
4769 zonecfg_endnwifent(zone_dochandle_t handle)
4770 {
4771         return (zonecfg_endent(handle));
4772 }
4773 
4774 int
4775 zonecfg_setdevent(zone_dochandle_t handle)
4776 {
4777         return (zonecfg_setent(handle));
4778 }
4779 
4780 int
4781 zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
4782 {
4783         xmlNodePtr cur;
4784         int err;
4785 
4786         if (handle == NULL)
4787                 return (Z_INVAL);
4788 
4789         if ((cur = handle->zone_dh_cur) == NULL)
4790                 return (Z_NO_ENTRY);
4791 
4792         for (; cur != NULL; cur = cur->next)
4793                 if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
4794                         break;
4795         if (cur == NULL) {
4796                 handle->zone_dh_cur = handle->zone_dh_top;
4797                 return (Z_NO_ENTRY);
4798         }
4799 
4800         if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
4801             sizeof (tabptr->zone_dev_match))) != Z_OK) {
4802                 handle->zone_dh_cur = handle->zone_dh_top;
4803                 return (err);
4804         }
4805 

























4806         handle->zone_dh_cur = cur->next;
4807         return (Z_OK);
4808 }
4809 
4810 int
4811 zonecfg_enddevent(zone_dochandle_t handle)
4812 {
4813         return (zonecfg_endent(handle));
4814 }
4815 
4816 int
4817 zonecfg_setrctlent(zone_dochandle_t handle)
4818 {
4819         return (zonecfg_setent(handle));
4820 }
4821 
4822 int
4823 zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr)
4824 {
4825         xmlNodePtr cur, val;


5513                 if (err < 0)
5514                         return ((errno == EFAULT) ? Z_TOO_BIG : Z_INVAL);
5515 
5516                 return (Z_OK);
5517         }
5518 
5519         if (strcmp(zone_name, "global") == 0)
5520                 return (zonecfg_default_brand(brandname, rp_sz));
5521 
5522         if ((handle = zonecfg_init_handle()) == NULL)
5523                 return (Z_NOMEM);
5524 
5525         err = zonecfg_get_handle((char *)zone_name, handle);
5526         if (err == Z_OK)
5527                 err = zonecfg_get_brand(handle, brandname, rp_sz);
5528 
5529         zonecfg_fini_handle(handle);
5530         return (err);
5531 }
5532 






























































































































































5533 /*
5534  * Return the appropriate root for the active /dev.
5535  * For normal zone, the path is $ZONEPATH/root;
5536  * for scratch zone, the dev path is $ZONEPATH/lu.
5537  */
5538 int
5539 zone_get_devroot(char *zone_name, char *devroot, size_t rp_sz)
5540 {
5541         int err;
5542         char *suffix;
5543         zone_state_t state;
5544 
5545         /* This function makes sense for non-global zones only. */
5546         if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
5547                 return (Z_BOGUS_ZONE_NAME);
5548         if ((err = zone_get_zonepath(zone_name, devroot, rp_sz)) != Z_OK)
5549                 return (err);
5550 
5551         if (zone_get_state(zone_name, &state) == Z_OK &&
5552             state == ZONE_STATE_MOUNTED)




  65 
  66 #include <arpa/inet.h>
  67 #include <netdb.h>
  68 
  69 #include <libxml/xmlmemory.h>
  70 #include <libxml/parser.h>
  71 
  72 #include <libdevinfo.h>
  73 #include <uuid/uuid.h>
  74 #include <dirent.h>
  75 #include <libbrand.h>
  76 
  77 #include <libzonecfg.h>
  78 #include "zonecfg_impl.h"
  79 
  80 #define _PATH_TMPFILE   "/zonecfg.XXXXXX"
  81 #define ZONE_CB_RETRY_COUNT             10
  82 #define ZONE_EVENT_PING_SUBCLASS        "ping"
  83 #define ZONE_EVENT_PING_PUBLISHER       "solaris"
  84 
  85 #define DEBUGID_FILE    "/etc/zones/did.txt"
  86 
  87 /* Hard-code the DTD element/attribute/entity names just once, here. */
  88 #define DTD_ELEM_ATTR           (const xmlChar *) "attr"
  89 #define DTD_ELEM_COMMENT        (const xmlChar *) "comment"
  90 #define DTD_ELEM_DEVICE         (const xmlChar *) "device"
  91 #define DTD_ELEM_FS             (const xmlChar *) "filesystem"
  92 #define DTD_ELEM_FSOPTION       (const xmlChar *) "fsoption"
  93 #define DTD_ELEM_NET            (const xmlChar *) "network"
  94 #define DTD_ELEM_NETATTR        (const xmlChar *) "net-attr"
  95 #define DTD_ELEM_RCTL           (const xmlChar *) "rctl"
  96 #define DTD_ELEM_RCTLVALUE      (const xmlChar *) "rctl-value"
  97 #define DTD_ELEM_ZONE           (const xmlChar *) "zone"
  98 #define DTD_ELEM_DATASET        (const xmlChar *) "dataset"
  99 #define DTD_ELEM_TMPPOOL        (const xmlChar *) "tmp_pool"
 100 #define DTD_ELEM_PSET           (const xmlChar *) "pset"
 101 #define DTD_ELEM_MCAP           (const xmlChar *) "mcap"
 102 #define DTD_ELEM_PACKAGE        (const xmlChar *) "package"
 103 #define DTD_ELEM_OBSOLETES      (const xmlChar *) "obsoletes"
 104 #define DTD_ELEM_DEV_PERM       (const xmlChar *) "dev-perm"
 105 #define DTD_ELEM_ADMIN          (const xmlChar *) "admin"
 106 
 107 #define DTD_ATTR_ACTION         (const xmlChar *) "action"
 108 #define DTD_ATTR_ADDRESS        (const xmlChar *) "address"
 109 #define DTD_ATTR_ALLOWED_ADDRESS        (const xmlChar *) "allowed-address"
 110 #define DTD_ATTR_AUTOBOOT       (const xmlChar *) "autoboot"
 111 #define DTD_ATTR_IPTYPE         (const xmlChar *) "ip-type"
 112 #define DTD_ATTR_DEFROUTER      (const xmlChar *) "defrouter"
 113 #define DTD_ATTR_DIR            (const xmlChar *) "directory"
 114 #define DTD_ATTR_GNIC           (const xmlChar *) "global-nic"
 115 #define DTD_ATTR_LIMIT          (const xmlChar *) "limit"
 116 #define DTD_ATTR_LIMITPRIV      (const xmlChar *) "limitpriv"
 117 #define DTD_ATTR_BOOTARGS       (const xmlChar *) "bootargs"
 118 #define DTD_ATTR_SCHED          (const xmlChar *) "scheduling-class"
 119 #define DTD_ATTR_MAC            (const xmlChar *) "mac-addr"
 120 #define DTD_ATTR_MATCH          (const xmlChar *) "match"
 121 #define DTD_ATTR_NAME           (const xmlChar *) "name"
 122 #define DTD_ATTR_PHYSICAL       (const xmlChar *) "physical"
 123 #define DTD_ATTR_POOL           (const xmlChar *) "pool"
 124 #define DTD_ATTR_PRIV           (const xmlChar *) "priv"
 125 #define DTD_ATTR_RAW            (const xmlChar *) "raw"
 126 #define DTD_ATTR_SPECIAL        (const xmlChar *) "special"
 127 #define DTD_ATTR_TYPE           (const xmlChar *) "type"
 128 #define DTD_ATTR_VALUE          (const xmlChar *) "value"
 129 #define DTD_ATTR_VLANID         (const xmlChar *) "vlan-id"
 130 #define DTD_ATTR_ZONEPATH       (const xmlChar *) "zonepath"
 131 #define DTD_ATTR_NCPU_MIN       (const xmlChar *) "ncpu_min"
 132 #define DTD_ATTR_NCPU_MAX       (const xmlChar *) "ncpu_max"
 133 #define DTD_ATTR_IMPORTANCE     (const xmlChar *) "importance"
 134 #define DTD_ATTR_PHYSCAP        (const xmlChar *) "physcap"
 135 #define DTD_ATTR_VERSION        (const xmlChar *) "version"
 136 #define DTD_ATTR_ID             (const xmlChar *) "id"
 137 #define DTD_ATTR_UID            (const xmlChar *) "uid"
 138 #define DTD_ATTR_GID            (const xmlChar *) "gid"
 139 #define DTD_ATTR_MODE           (const xmlChar *) "mode"
 140 #define DTD_ATTR_ACL            (const xmlChar *) "acl"
 141 #define DTD_ATTR_BRAND          (const xmlChar *) "brand"
 142 #define DTD_ATTR_DID            (const xmlChar *) "debugid"
 143 #define DTD_ATTR_HOSTID         (const xmlChar *) "hostid"
 144 #define DTD_ATTR_USER           (const xmlChar *) "user"
 145 #define DTD_ATTR_AUTHS          (const xmlChar *) "auths"
 146 #define DTD_ATTR_FS_ALLOWED     (const xmlChar *) "fs-allowed"
 147 
 148 #define DTD_ENTITY_BOOLEAN      "boolean"
 149 #define DTD_ENTITY_DEVPATH      "devpath"
 150 #define DTD_ENTITY_DRIVER       "driver"
 151 #define DTD_ENTITY_DRVMIN       "drv_min"
 152 #define DTD_ENTITY_FALSE        "false"
 153 #define DTD_ENTITY_INT          "int"
 154 #define DTD_ENTITY_STRING       "string"
 155 #define DTD_ENTITY_TRUE         "true"
 156 #define DTD_ENTITY_UINT         "uint"
 157 
 158 #define DTD_ENTITY_BOOL_LEN     6       /* "false" */
 159 
 160 #define ATTACH_FORCED   "SUNWattached.xml"
 161 
 162 #define TMP_POOL_NAME   "SUNWtmp_%s"


2080 
2081 /*
2082  * Determines whether there is a net resource with the physical interface, IP
2083  * address, and default router specified by 'tabptr' in the zone configuration
2084  * to which 'handle' refers.  'tabptr' must have an interface, an address, a
2085  * default router, or a combination of the three.  This function returns Z_OK
2086  * iff there is exactly one net resource matching the query specified by
2087  * 'tabptr'.  The function returns Z_INSUFFICIENT_SPEC if there are multiple
2088  * matches or 'tabptr' does not specify a physical interface, address, or
2089  * default router.  The function returns Z_NO_RESOURCE_ID if are no matches.
2090  *
2091  * Errors might also be returned if the entry that exactly matches the
2092  * query lacks critical network resource information.
2093  *
2094  * If there is a single match, then the matching entry's physical interface, IP
2095  * address, and default router information are stored in 'tabptr'.
2096  */
2097 int
2098 zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2099 {
2100         xmlNodePtr cur, val;
2101         xmlNodePtr firstmatch;
2102         int err;
2103         char address[INET6_ADDRSTRLEN];
2104         char physical[LIFNAMSIZ];
2105         char mac[MAXMACADDRLEN];
2106         char gnic[LIFNAMSIZ];
2107         size_t addrspec;                /* nonzero if tabptr has IP addr */
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 */
2111         size_t defrouterspec;           /* nonzero if tabptr has def. router */
2112         size_t allowed_addrspec;
2113         zone_iptype_t iptype;
2114 
2115         if (tabptr == NULL)
2116                 return (Z_INVAL);
2117 
2118         /*
2119          * Determine the fields that will be searched.  There must be at least
2120          * one.
2121          *
2122          * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter,
2123          * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic  are
2124          * arrays, so no NULL checks are necessary.
2125          */
2126         addrspec = strlen(tabptr->zone_nwif_address);
2127         physspec = strlen(tabptr->zone_nwif_physical);
2128         macspec = strlen(tabptr->zone_nwif_mac);
2129         gnicspec = strlen(tabptr->zone_nwif_gnic);
2130         defrouterspec = strlen(tabptr->zone_nwif_defrouter);
2131         allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address);
2132         if (addrspec != 0 && allowed_addrspec != 0)
2133                 return (Z_INVAL); /* can't specify both */
2134         if (addrspec == 0 && physspec == 0 && defrouterspec == 0 &&
2135             allowed_addrspec == 0 && macspec == 0 && gnicspec == 0)
2136                 return (Z_INSUFFICIENT_SPEC);
2137 
2138         if ((err = operation_prep(handle)) != Z_OK)
2139                 return (err);
2140 
2141         if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK)
2142                 return (err);
2143         /*
2144          * Iterate over the configuration's elements and look for net elements
2145          * that match the query.
2146          */
2147         firstmatch = NULL;
2148         cur = handle->zone_dh_cur;
2149         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2150                 /* Skip non-net elements */
2151                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2152                         continue;
2153 
2154                 /*
2155                  * If any relevant fields don't match the query, then skip
2156                  * the current net element.
2157                  */
2158                 if (physspec != 0 && (fetchprop(cur, DTD_ATTR_PHYSICAL,
2159                     physical, sizeof (physical)) != Z_OK ||
2160                     strcmp(tabptr->zone_nwif_physical, physical) != 0))
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;
2171                 if (iptype == ZS_SHARED && addrspec != 0 &&
2172                     (fetchprop(cur, DTD_ATTR_ADDRESS, address,
2173                     sizeof (address)) != Z_OK ||
2174                     !zonecfg_same_net_address(tabptr->zone_nwif_address,
2175                     address)))
2176                         continue;
2177                 if (iptype == ZS_EXCLUSIVE && allowed_addrspec != 0 &&
2178                     (fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, address,
2179                     sizeof (address)) != Z_OK ||
2180                     !zonecfg_same_net_address(tabptr->zone_nwif_allowed_address,
2181                     address)))
2182                         continue;
2183                 if (defrouterspec != 0 && (fetchprop(cur, DTD_ATTR_DEFROUTER,
2184                     address, sizeof (address)) != Z_OK ||
2185                     !zonecfg_same_net_address(tabptr->zone_nwif_defrouter,
2186                     address)))
2187                         continue;
2188 
2189                 /*
2190                  * The current net element matches the query.  Select it if


2193                 if (firstmatch == NULL)
2194                         firstmatch = cur;
2195                 else
2196                         return (Z_INSUFFICIENT_SPEC);
2197         }
2198         if (firstmatch == NULL)
2199                 return (Z_NO_RESOURCE_ID);
2200 
2201         cur = firstmatch;
2202 
2203         if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
2204             sizeof (tabptr->zone_nwif_physical))) != Z_OK)
2205                 return (err);
2206 
2207         if (iptype == ZS_SHARED &&
2208             (err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
2209             sizeof (tabptr->zone_nwif_address))) != Z_OK)
2210                 return (err);
2211 
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 &&
2228             (err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2229             tabptr->zone_nwif_allowed_address,
2230             sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK)
2231                 return (err);
2232 
2233         if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
2234             tabptr->zone_nwif_defrouter,
2235             sizeof (tabptr->zone_nwif_defrouter))) != Z_OK)
2236                 return (err);
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 
2264         return (Z_OK);
2265 }
2266 
2267 static int
2268 zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2269 {
2270         xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
2271         struct zone_res_attrtab *valptr;
2272         int err;
2273 
2274         newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL);
2275         if (strlen(tabptr->zone_nwif_address) > 0 &&
2276             (err = newprop(newnode, DTD_ATTR_ADDRESS,
2277             tabptr->zone_nwif_address)) != Z_OK)
2278                 return (err);
2279         if (strlen(tabptr->zone_nwif_allowed_address) > 0 &&
2280             (err = newprop(newnode, DTD_ATTR_ALLOWED_ADDRESS,
2281             tabptr->zone_nwif_allowed_address)) != Z_OK)
2282                 return (err);
2283         if ((err = newprop(newnode, DTD_ATTR_PHYSICAL,
2284             tabptr->zone_nwif_physical)) != Z_OK)
2285                 return (err);
2286         /*
2287          * Do not add these properties when they are not set, for backwards
2288          * compatibility and because they are optional.
2289          */
2290         if ((strlen(tabptr->zone_nwif_defrouter) > 0) &&
2291             ((err = newprop(newnode, DTD_ATTR_DEFROUTER,
2292             tabptr->zone_nwif_defrouter)) != Z_OK))
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 
2321         return (Z_OK);
2322 }
2323 
2324 int
2325 zonecfg_add_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2326 {
2327         int err;
2328 
2329         if (tabptr == NULL)
2330                 return (Z_INVAL);
2331 
2332         if ((err = operation_prep(handle)) != Z_OK)
2333                 return (err);
2334 
2335         if ((err = zonecfg_add_nwif_core(handle, tabptr)) != Z_OK)
2336                 return (err);
2337 
2338         return (Z_OK);
2339 }
2340 
2341 static int
2342 zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2343 {
2344         xmlNodePtr cur = handle->zone_dh_cur;
2345         boolean_t addr_match, phys_match, allowed_addr_match, mac_match,
2346             gnic_match;
2347 
2348         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2349                 if (xmlStrcmp(cur->name, DTD_ELEM_NET))
2350                         continue;
2351 
2352                 addr_match = match_prop(cur, DTD_ATTR_ADDRESS,
2353                     tabptr->zone_nwif_address);
2354                 allowed_addr_match = match_prop(cur, DTD_ATTR_ALLOWED_ADDRESS,
2355                     tabptr->zone_nwif_allowed_address);
2356                 phys_match = match_prop(cur, DTD_ATTR_PHYSICAL,
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);
2362 
2363                 if ((addr_match || allowed_addr_match || mac_match ||
2364                     gnic_match) && phys_match) {
2365                         xmlUnlinkNode(cur);
2366                         xmlFreeNode(cur);
2367                         return (Z_OK);
2368                 }
2369         }
2370         return (Z_NO_RESOURCE_ID);
2371 }
2372 
2373 int
2374 zonecfg_delete_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
2375 {
2376         int err;
2377 
2378         if (tabptr == NULL)
2379                 return (Z_INVAL);
2380 
2381         if ((err = operation_prep(handle)) != Z_OK)
2382                 return (err);
2383 
2384         if ((err = zonecfg_delete_nwif_core(handle, tabptr)) != Z_OK)


2393         struct zone_nwiftab *oldtabptr,
2394         struct zone_nwiftab *newtabptr)
2395 {
2396         int err;
2397 
2398         if (oldtabptr == NULL || newtabptr == NULL)
2399                 return (Z_INVAL);
2400 
2401         if ((err = operation_prep(handle)) != Z_OK)
2402                 return (err);
2403 
2404         if ((err = zonecfg_delete_nwif_core(handle, oldtabptr)) != Z_OK)
2405                 return (err);
2406 
2407         if ((err = zonecfg_add_nwif_core(handle, newtabptr)) != Z_OK)
2408                 return (err);
2409 
2410         return (Z_OK);
2411 }
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 
2465 /*
2466  * Must be a comma-separated list of alpha-numeric file system names.
2467  */
2468 static int
2469 zonecfg_valid_fs_allowed(const char *fsallowedp)
2470 {
2471         char tmp[ZONE_FS_ALLOWED_MAX];
2472         char *cp = tmp;
2473         char *p;
2474 
2475         if (strlen(fsallowedp) > ZONE_FS_ALLOWED_MAX)
2476                 return (Z_TOO_BIG);
2477 
2478         (void) strlcpy(tmp, fsallowedp, sizeof (tmp));
2479 
2480         while (*cp != '\0') {
2481                 p = cp;
2482                 while (*p != '\0' && *p != ',') {
2483                         if (!isalnum(*p) && *p != '-')
2484                                 return (Z_INVALID_PROPERTY);


2594  * attribute is cleared.  Non-NULL hostids are validated.  This function returns
2595  * Z_OK on success.  Any other return value indicates failure.
2596  */
2597 int
2598 zonecfg_set_hostid(zone_dochandle_t handle, const char *hostidp)
2599 {
2600         int err;
2601 
2602         /*
2603          * A NULL hostid string is interpreted as a request to clear the
2604          * hostid.
2605          */
2606         if (hostidp == NULL || (err = zonecfg_valid_hostid(hostidp)) == Z_OK)
2607                 return (setrootattr(handle, DTD_ATTR_HOSTID, hostidp));
2608         return (err);
2609 }
2610 
2611 int
2612 zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2613 {
2614         xmlNodePtr cur, val, firstmatch;
2615         int err;
2616         char match[MAXPATHLEN];
2617 
2618         if (tabptr == NULL)
2619                 return (Z_INVAL);
2620 
2621         if ((err = operation_prep(handle)) != Z_OK)
2622                 return (err);
2623 
2624         cur = handle->zone_dh_cur;
2625         firstmatch = NULL;
2626         for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
2627                 if (xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
2628                         continue;
2629                 if (strlen(tabptr->zone_dev_match) == 0)
2630                         continue;
2631 
2632                 if ((fetchprop(cur, DTD_ATTR_MATCH, match,
2633                     sizeof (match)) == Z_OK)) {
2634                         if (strcmp(tabptr->zone_dev_match,


2639                                         return (Z_INSUFFICIENT_SPEC);
2640                         } else {
2641                                 /*
2642                                  * If another property matched but this
2643                                  * one doesn't then reset firstmatch.
2644                                  */
2645                                 if (firstmatch == cur)
2646                                         firstmatch = NULL;
2647                         }
2648                 }
2649         }
2650         if (firstmatch == NULL)
2651                 return (Z_NO_RESOURCE_ID);
2652 
2653         cur = firstmatch;
2654 
2655         if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
2656             sizeof (tabptr->zone_dev_match))) != Z_OK)
2657                 return (err);
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 
2685         return (Z_OK);
2686 }
2687 
2688 static int
2689 zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr)
2690 {
2691         xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode;
2692         struct zone_res_attrtab *valptr;
2693         int err;
2694 
2695         newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL);
2696 
2697         if ((err = newprop(newnode, DTD_ATTR_MATCH,
2698             tabptr->zone_dev_match)) != Z_OK)
2699                 return (err);
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 
2716         return (Z_OK);
2717 }
2718 
2719 int
2720 zonecfg_add_dev(zone_dochandle_t handle, struct zone_devtab *tabptr)
2721 {
2722         int err;
2723 
2724         if (tabptr == NULL)
2725                 return (Z_INVAL);
2726 
2727         if ((err = operation_prep(handle)) != Z_OK)
2728                 return (err);
2729 
2730         if ((err = zonecfg_add_dev_core(handle, tabptr)) != Z_OK)
2731                 return (err);
2732 
2733         return (Z_OK);
2734 }
2735 


4893 
4894         handle->zone_dh_cur = cur->next;
4895         return (Z_OK);
4896 }
4897 
4898 int
4899 zonecfg_endfsent(zone_dochandle_t handle)
4900 {
4901         return (zonecfg_endent(handle));
4902 }
4903 
4904 int
4905 zonecfg_setnwifent(zone_dochandle_t handle)
4906 {
4907         return (zonecfg_setent(handle));
4908 }
4909 
4910 int
4911 zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr)
4912 {
4913         xmlNodePtr cur, val;
4914         struct zone_res_attrtab *valptr;
4915         int err;
4916 
4917         if (handle == NULL)
4918                 return (Z_INVAL);
4919 
4920         if ((cur = handle->zone_dh_cur) == NULL)
4921                 return (Z_NO_ENTRY);
4922 
4923         for (; cur != NULL; cur = cur->next)
4924                 if (!xmlStrcmp(cur->name, DTD_ELEM_NET))
4925                         break;
4926         if (cur == NULL) {
4927                 handle->zone_dh_cur = handle->zone_dh_top;
4928                 return (Z_NO_ENTRY);
4929         }
4930 
4931         if ((err = fetchprop(cur, DTD_ATTR_ADDRESS, tabptr->zone_nwif_address,
4932             sizeof (tabptr->zone_nwif_address))) != Z_OK) {
4933                 handle->zone_dh_cur = handle->zone_dh_top;
4934                 return (err);
4935         }
4936 
4937         if ((err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS,
4938             tabptr->zone_nwif_allowed_address,
4939             sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK) {
4940                 handle->zone_dh_cur = handle->zone_dh_top;
4941                 return (err);
4942         }
4943 
4944         if ((err = fetchprop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical,
4945             sizeof (tabptr->zone_nwif_physical))) != Z_OK) {
4946                 handle->zone_dh_cur = handle->zone_dh_top;
4947                 return (err);
4948         }
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 
4968         if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER,
4969             tabptr->zone_nwif_defrouter,
4970             sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) {
4971                 handle->zone_dh_cur = handle->zone_dh_top;
4972                 return (err);
4973         }
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 
4998         handle->zone_dh_cur = cur->next;
4999         return (Z_OK);
5000 }
5001 
5002 int
5003 zonecfg_endnwifent(zone_dochandle_t handle)
5004 {
5005         return (zonecfg_endent(handle));
5006 }
5007 
5008 int
5009 zonecfg_setdevent(zone_dochandle_t handle)
5010 {
5011         return (zonecfg_setent(handle));
5012 }
5013 
5014 int
5015 zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr)
5016 {
5017         xmlNodePtr cur, val;
5018         int err;
5019 
5020         if (handle == NULL)
5021                 return (Z_INVAL);
5022 
5023         if ((cur = handle->zone_dh_cur) == NULL)
5024                 return (Z_NO_ENTRY);
5025 
5026         for (; cur != NULL; cur = cur->next)
5027                 if (!xmlStrcmp(cur->name, DTD_ELEM_DEVICE))
5028                         break;
5029         if (cur == NULL) {
5030                 handle->zone_dh_cur = handle->zone_dh_top;
5031                 return (Z_NO_ENTRY);
5032         }
5033 
5034         if ((err = fetchprop(cur, DTD_ATTR_MATCH, tabptr->zone_dev_match,
5035             sizeof (tabptr->zone_dev_match))) != Z_OK) {
5036                 handle->zone_dh_cur = handle->zone_dh_top;
5037                 return (err);
5038         }
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 
5065         handle->zone_dh_cur = cur->next;
5066         return (Z_OK);
5067 }
5068 
5069 int
5070 zonecfg_enddevent(zone_dochandle_t handle)
5071 {
5072         return (zonecfg_endent(handle));
5073 }
5074 
5075 int
5076 zonecfg_setrctlent(zone_dochandle_t handle)
5077 {
5078         return (zonecfg_setent(handle));
5079 }
5080 
5081 int
5082 zonecfg_getrctlent(zone_dochandle_t handle, struct zone_rctltab *tabptr)
5083 {
5084         xmlNodePtr cur, val;


5772                 if (err < 0)
5773                         return ((errno == EFAULT) ? Z_TOO_BIG : Z_INVAL);
5774 
5775                 return (Z_OK);
5776         }
5777 
5778         if (strcmp(zone_name, "global") == 0)
5779                 return (zonecfg_default_brand(brandname, rp_sz));
5780 
5781         if ((handle = zonecfg_init_handle()) == NULL)
5782                 return (Z_NOMEM);
5783 
5784         err = zonecfg_get_handle((char *)zone_name, handle);
5785         if (err == Z_OK)
5786                 err = zonecfg_get_brand(handle, brandname, rp_sz);
5787 
5788         zonecfg_fini_handle(handle);
5789         return (err);
5790 }
5791 
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 /*
5951  * Return the appropriate root for the active /dev.
5952  * For normal zone, the path is $ZONEPATH/root;
5953  * for scratch zone, the dev path is $ZONEPATH/lu.
5954  */
5955 int
5956 zone_get_devroot(char *zone_name, char *devroot, size_t rp_sz)
5957 {
5958         int err;
5959         char *suffix;
5960         zone_state_t state;
5961 
5962         /* This function makes sense for non-global zones only. */
5963         if (strcmp(zone_name, GLOBAL_ZONENAME) == 0)
5964                 return (Z_BOGUS_ZONE_NAME);
5965         if ((err = zone_get_zonepath(zone_name, devroot, rp_sz)) != Z_OK)
5966                 return (err);
5967 
5968         if (zone_get_state(zone_name, &state) == Z_OK &&
5969             state == ZONE_STATE_MOUNTED)