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)
|