6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2014 Gary Mills
26 */
27
28 /*
29 * zonecfg is a lex/yacc based command interpreter used to manage zone
30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
32 * which takes resources and/or properties as arguments. See the block
33 * comments near the end of zonecfg_grammar.y for how the data structures
34 * which keep track of these resources and properties are built up.
35 *
36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
45 *
217 "importance",
218 "swap",
219 "locked",
220 ALIAS_SHARES,
221 ALIAS_MAXLWPS,
222 ALIAS_MAXSHMMEM,
223 ALIAS_MAXSHMIDS,
224 ALIAS_MAXMSGIDS,
225 ALIAS_MAXSEMIDS,
226 ALIAS_MAXLOCKEDMEM,
227 ALIAS_MAXSWAP,
228 "scheduling-class",
229 "ip-type",
230 "defrouter",
231 "hostid",
232 "user",
233 "auths",
234 "fs-allowed",
235 ALIAS_MAXPROCS,
236 "allowed-address",
237 NULL
238 };
239
240 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
241 static char *prop_val_types[] = {
242 "simple",
243 "complex",
244 "list",
245 };
246
247 /*
248 * The various _cmds[] lists below are for command tab-completion.
249 */
250
251 /*
252 * remove has a space afterwards because it has qualifiers; the other commands
253 * that have qualifiers (add, select, etc.) don't need a space here because
254 * they have their own _cmds[] lists below.
255 */
256 static const char *global_scope_cmds[] = {
389 "cancel",
390 "end",
391 "exit",
392 "help",
393 "info",
394 "remove options ",
395 "set dir=",
396 "set raw=",
397 "set special=",
398 "set type=",
399 "clear raw",
400 NULL
401 };
402
403 static const char *net_res_scope_cmds[] = {
404 "cancel",
405 "end",
406 "exit",
407 "help",
408 "info",
409 "set address=",
410 "set physical=",
411 "set defrouter=",
412 NULL
413 };
414
415 static const char *device_res_scope_cmds[] = {
416 "cancel",
417 "end",
418 "exit",
419 "help",
420 "info",
421 "set match=",
422 NULL
423 };
424
425 static const char *attr_res_scope_cmds[] = {
426 "cancel",
427 "end",
428 "exit",
429 "help",
430 "info",
431 "set name=",
432 "set type=",
433 "set value=",
434 NULL
435 };
436
437 static const char *rctl_res_scope_cmds[] = {
438 "add value ",
439 "cancel",
440 "end",
562
563 /* scope is outer/global or inner/resource */
564 static boolean_t global_scope = B_TRUE;
565 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
566 static int end_op = -1; /* operation on end is either add or modify */
567
568 int num_prop_vals; /* for grammar */
569
570 /*
571 * These are for keeping track of resources as they are specified as part of
572 * the multi-step process. They should be initialized by add_resource() or
573 * select_func() and filled in by add_property() or set_func().
574 */
575 static struct zone_fstab old_fstab, in_progress_fstab;
576 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
577 static struct zone_devtab old_devtab, in_progress_devtab;
578 static struct zone_rctltab old_rctltab, in_progress_rctltab;
579 static struct zone_attrtab old_attrtab, in_progress_attrtab;
580 static struct zone_dstab old_dstab, in_progress_dstab;
581 static struct zone_psettab old_psettab, in_progress_psettab;
582 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
583 static struct zone_admintab old_admintab, in_progress_admintab;
584
585 static GetLine *gl; /* The gl_get_line() resource object */
586
587 static void bytes_to_units(char *str, char *buf, int bufsize);
588
589 /* Functions begin here */
590
591 static boolean_t
592 initial_match(const char *line1, const char *line2, int word_end)
593 {
594 if (word_end <= 0)
595 return (B_TRUE);
596 return (strncmp(line1, line2, word_end) == 0);
597 }
598
599 static int
600 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
601 int word_end)
602 {
1061 pt_to_str(PT_OPTIONS),
1062 gettext("<file-system options>"));
1063 (void) fprintf(fp, "\t%s %s %s\n",
1064 cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
1065 gettext("<file-system options>"));
1066 (void) fprintf(fp, gettext("Consult the file-system "
1067 "specific manual page, such as mount_ufs(1M), "
1068 "for\ndetails about file-system options. Note "
1069 "that any file-system options with an\nembedded "
1070 "'=' character must be enclosed in double quotes, "
1071 /*CSTYLED*/
1072 "such as \"%s=5\".\n"), MNTOPT_RETRY);
1073 break;
1074 case RT_NET:
1075 (void) fprintf(fp, gettext("The '%s' resource scope is "
1076 "used to configure a network interface.\n"),
1077 rt_to_str(resource_scope));
1078 (void) fprintf(fp, gettext("Valid commands:\n"));
1079 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1080 pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
1081 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1082 pt_to_str(PT_ALLOWED_ADDRESS),
1083 gettext("<IP-address>"));
1084 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1085 pt_to_str(PT_PHYSICAL), gettext("<interface>"));
1086 (void) fprintf(fp, gettext("See ifconfig(1M) for "
1087 "details of the <interface> string.\n"));
1088 (void) fprintf(fp, gettext("%s %s is valid "
1089 "if the %s property is set to %s, otherwise it "
1090 "must not be set.\n"),
1091 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
1092 pt_to_str(PT_IPTYPE), gettext("shared"));
1093 (void) fprintf(fp, gettext("%s %s is valid "
1094 "if the %s property is set to %s, otherwise it "
1095 "must not be set.\n"),
1096 cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
1097 pt_to_str(PT_IPTYPE), gettext("exclusive"));
1098 (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
1099 "is valid if the %s or %s property is set, "
1100 "otherwise it must not be set\n"),
1101 cmd_to_str(CMD_SET),
1102 pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
1103 cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
1104 gettext(pt_to_str(PT_ADDRESS)),
1105 gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
1106 break;
1107 case RT_DEVICE:
1108 (void) fprintf(fp, gettext("The '%s' resource scope is "
1109 "used to configure a device node.\n"),
1110 rt_to_str(resource_scope));
1111 (void) fprintf(fp, gettext("Valid commands:\n"));
1112 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1113 pt_to_str(PT_MATCH), gettext("<device-path>"));
1114 break;
1115 case RT_RCTL:
1116 (void) fprintf(fp, gettext("The '%s' resource scope is "
1117 "used to configure a resource control.\n"),
1118 rt_to_str(resource_scope));
1119 (void) fprintf(fp, gettext("Valid commands:\n"));
1120 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1121 pt_to_str(PT_NAME), gettext("<string>"));
1122 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1123 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
1124 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1125 pt_to_str(PT_LIMIT), gettext("<number>"),
1126 pt_to_str(PT_ACTION), gettext("<action-value>"));
1127 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1128 cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
1129 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1130 pt_to_str(PT_LIMIT), gettext("<number>"),
1131 pt_to_str(PT_ACTION), gettext("<action-value>"));
1319 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1320 pt_to_str(PT_FS_ALLOWED));
1321 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1322 pt_to_str(PT_MAXLWPS));
1323 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1324 pt_to_str(PT_MAXPROCS));
1325 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1326 pt_to_str(PT_MAXSHMMEM));
1327 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1328 pt_to_str(PT_MAXSHMIDS));
1329 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1330 pt_to_str(PT_MAXMSGIDS));
1331 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1332 pt_to_str(PT_MAXSEMIDS));
1333 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1334 pt_to_str(PT_SHARES));
1335 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1336 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1337 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1338 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1339 (void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
1340 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1341 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1342 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1343 pt_to_str(PT_MATCH));
1344 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1345 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1346 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1347 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1348 pt_to_str(PT_VALUE));
1349 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1350 pt_to_str(PT_NAME));
1351 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1352 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1353 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1354 pt_to_str(PT_NCPUS));
1355 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1356 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1357 pt_to_str(PT_LOCKED));
1358 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1359 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1360 }
1361 if (need_to_close)
1362 (void) pager_close(fp);
1363 }
1378
1379 static void
1380 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1381 {
1382 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
1383 zonecfg_strerror(err));
1384 if (set_saw)
1385 saw_error = B_TRUE;
1386 }
1387
1388 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1389 static int
1390 initialize(boolean_t handle_expected)
1391 {
1392 int err;
1393 char brandname[MAXNAMELEN];
1394
1395 if (zonecfg_check_handle(handle) != Z_OK) {
1396 if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
1397 got_handle = B_TRUE;
1398 if (zonecfg_get_brand(handle, brandname,
1399 sizeof (brandname)) != Z_OK) {
1400 zerr("Zone %s is inconsistent: missing "
1401 "brand attribute", zone);
1402 exit(Z_ERR);
1403 }
1404 if ((brand = brand_open(brandname)) == NULL) {
1405 zerr("Zone %s uses non-existent brand \"%s\"."
1406 " Unable to continue", zone, brandname);
1407 exit(Z_ERR);
1408 }
1409 /*
1410 * If the user_attr file is newer than
1411 * the zone config file, the admins
1412 * may need to be updated since the
1413 * RBAC files are authoritative for
1414 * authorization checks.
1415 */
1416 err = zonecfg_update_userauths(handle, zone);
1417 if (err == Z_OK) {
1678 else
1679 short_usage(CMD_CREATE);
1680 arg_err = B_TRUE;
1681 break;
1682 case 'a':
1683 (void) strlcpy(attach_path, optarg,
1684 sizeof (attach_path));
1685 attach = B_TRUE;
1686 break;
1687 case 'b':
1688 (void) strlcpy(zone_template, "SUNWblank",
1689 sizeof (zone_template));
1690 break;
1691 case 'F':
1692 force = B_TRUE;
1693 break;
1694 case 't':
1695 (void) strlcpy(zone_template, optarg,
1696 sizeof (zone_template));
1697 break;
1698 default:
1699 short_usage(CMD_CREATE);
1700 arg_err = B_TRUE;
1701 break;
1702 }
1703 }
1704 if (arg_err)
1705 return;
1706
1707 if (optind != cmd->cmd_argc) {
1708 short_usage(CMD_CREATE);
1709 return;
1710 }
1711
1712 if (zone_is_read_only(CMD_CREATE))
1713 return;
1714
1715 if (check_if_zone_already_exists(force) != Z_OK)
1716 return;
1717
1780 char *quote_str;
1781
1782 if (strlen(prop_id) == 0)
1783 return;
1784 quote_str = quoteit(prop_id);
1785 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1786 pt_to_str(prop_num), quote_str);
1787 free(quote_str);
1788 }
1789
1790 void
1791 export_func(cmd_t *cmd)
1792 {
1793 struct zone_nwiftab nwiftab;
1794 struct zone_fstab fstab;
1795 struct zone_devtab devtab;
1796 struct zone_attrtab attrtab;
1797 struct zone_rctltab rctltab;
1798 struct zone_dstab dstab;
1799 struct zone_psettab psettab;
1800 struct zone_mcaptab mcaptab;
1801 struct zone_rctlvaltab *valptr;
1802 struct zone_admintab admintab;
1803 int err, arg;
1804 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1805 char bootargs[BOOTARGS_MAX];
1806 char sched[MAXNAMELEN];
1807 char brand[MAXNAMELEN];
1808 char hostidp[HW_HOSTID_LEN];
1809 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1810 char *limitpriv;
1811 FILE *of;
1812 boolean_t autoboot;
1813 zone_iptype_t iptype;
1814 boolean_t need_to_close = B_FALSE;
1815 boolean_t arg_err = B_FALSE;
1816
1817 assert(cmd != NULL);
1818
1819 outfile[0] = '\0';
1820 optind = 0;
1821 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1951 cmd_to_str(CMD_ADD),
1952 pt_to_str(PT_OPTIONS),
1953 optptr->zone_fsopt_opt);
1954 }
1955 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1956 zonecfg_free_fs_option_list(fstab.zone_fs_options);
1957 }
1958 (void) zonecfg_endfsent(handle);
1959
1960 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
1961 zone_perror(zone, err, B_FALSE);
1962 goto done;
1963 }
1964 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
1965 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1966 rt_to_str(RT_NET));
1967 export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
1968 export_prop(of, PT_ALLOWED_ADDRESS,
1969 nwiftab.zone_nwif_allowed_address);
1970 export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
1971 export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
1972 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1973 }
1974 (void) zonecfg_endnwifent(handle);
1975
1976 if ((err = zonecfg_setdevent(handle)) != Z_OK) {
1977 zone_perror(zone, err, B_FALSE);
1978 goto done;
1979 }
1980 while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
1981 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1982 rt_to_str(RT_DEVICE));
1983 export_prop(of, PT_MATCH, devtab.zone_dev_match);
1984 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1985 }
1986 (void) zonecfg_enddevent(handle);
1987
1988 if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
1989 char buf[128];
1990
1991 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1992 rt_to_str(RT_MCAP));
1993 bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
1994 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1995 pt_to_str(PT_PHYSICAL), buf);
1996 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1997 }
1998
1999 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
2000 zone_perror(zone, err, B_FALSE);
2001 goto done;
2002 }
2003 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2004 (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
2005 export_prop(of, PT_NAME, rctltab.zone_rctl_name);
2006 for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
2007 valptr = valptr->zone_rctlval_next) {
2008 fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2009 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
2010 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
2011 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
2012 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
2013 }
2014 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2015 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2016 }
2017 (void) zonecfg_endrctlent(handle);
2018
2132 validate_zonepath_syntax(char *path)
2133 {
2134 if (path[0] != '/') {
2135 zerr(gettext("%s is not an absolute path."), path);
2136 return (Z_ERR);
2137 }
2138 /* If path is all slashes, then fail */
2139 if (strspn(path, "/") == strlen(path)) {
2140 zerr(gettext("/ is not allowed as a %s."),
2141 pt_to_str(PT_ZONEPATH));
2142 return (Z_ERR);
2143 }
2144 return (Z_OK);
2145 }
2146
2147 static void
2148 add_resource(cmd_t *cmd)
2149 {
2150 int type;
2151 struct zone_psettab tmp_psettab;
2152 struct zone_mcaptab tmp_mcaptab;
2153 uint64_t tmp;
2154 uint64_t tmp_mcap;
2155 char pool[MAXNAMELEN];
2156
2157 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2158 long_usage(CMD_ADD, B_TRUE);
2159 goto bad;
2160 }
2161
2162 switch (type) {
2163 case RT_FS:
2164 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2165 return;
2166 case RT_NET:
2167 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2168 return;
2169 case RT_DEVICE:
2170 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2171 return;
2172 case RT_RCTL:
2224 switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
2225 case Z_ALIAS_DISALLOW:
2226 zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
2227 B_FALSE);
2228 goto bad;
2229
2230 case Z_OK:
2231 zerr(gettext("The %s resource already exists."),
2232 rt_to_str(RT_PCAP));
2233 goto bad;
2234
2235 default:
2236 break;
2237 }
2238 return;
2239 case RT_MCAP:
2240 /*
2241 * Make sure there isn't already a mem-cap entry or max-swap
2242 * or max-locked rctl.
2243 */
2244 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2245 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2246 == Z_OK ||
2247 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2248 &tmp_mcap) == Z_OK) {
2249 zerr(gettext("The %s resource or a related resource "
2250 "control already exists."), rt_to_str(RT_MCAP));
2251 goto bad;
2252 }
2253 if (global_zone)
2254 zerr(gettext("WARNING: Setting a global zone memory "
2255 "cap too low could deny\nservice "
2256 "to even the root user; "
2257 "this could render the system impossible\n"
2258 "to administer. Please use caution."));
2259 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2260 return;
2261 case RT_ADMIN:
2262 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2263 return;
2264 default:
2265 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2266 long_usage(CMD_ADD, B_TRUE);
2267 usage(B_FALSE, HELP_RESOURCES);
2268 }
2269 bad:
2270 global_scope = B_TRUE;
2271 end_op = -1;
2272 }
2273
2274 static void
2275 do_complex_rctl_val(complex_property_ptr_t cp)
2276 {
2277 struct zone_rctlvaltab *rctlvaltab;
2278 complex_property_ptr_t cx;
2279 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2342 /*
2343 * Make sure the rctl value looks roughly correct; we won't know if
2344 * it's truly OK until we verify the configuration on the target
2345 * system.
2346 */
2347 if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
2348 !zonecfg_valid_rctlblk(rctlblk)) {
2349 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
2350 pt_to_str(PT_VALUE));
2351 goto bad;
2352 }
2353 err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
2354 if (err != Z_OK)
2355 zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
2356 return;
2357
2358 bad:
2359 zonecfg_free_rctl_value_list(rctlvaltab);
2360 }
2361
2362 static void
2363 add_property(cmd_t *cmd)
2364 {
2365 char *prop_id;
2366 int err, res_type, prop_type;
2367 property_value_ptr_t pp;
2368 list_property_ptr_t l;
2369
2370 res_type = resource_scope;
2371 prop_type = cmd->cmd_prop_name[0];
2372 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
2373 long_usage(CMD_ADD, B_TRUE);
2374 return;
2375 }
2376
2377 if (cmd->cmd_prop_nv_pairs != 1) {
2378 long_usage(CMD_ADD, B_TRUE);
2379 return;
2380 }
2381
2382 if (initialize(B_TRUE) != Z_OK)
2409 err = zonecfg_add_fs_option(&in_progress_fstab,
2410 prop_id);
2411 if (err != Z_OK)
2412 zone_perror(pt_to_str(prop_type), err, B_TRUE);
2413 } else {
2414 list_property_ptr_t list;
2415
2416 for (list = pp->pv_list; list != NULL;
2417 list = list->lp_next) {
2418 prop_id = list->lp_simple;
2419 if (prop_id == NULL)
2420 break;
2421 err = zonecfg_add_fs_option(
2422 &in_progress_fstab, prop_id);
2423 if (err != Z_OK)
2424 zone_perror(pt_to_str(prop_type), err,
2425 B_TRUE);
2426 }
2427 }
2428 return;
2429 case RT_RCTL:
2430 if (prop_type != PT_VALUE) {
2431 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2432 B_TRUE);
2433 long_usage(CMD_ADD, B_TRUE);
2434 usage(B_FALSE, HELP_PROPS);
2435 return;
2436 }
2437 pp = cmd->cmd_property_ptr[0];
2438 if (pp->pv_type != PROP_VAL_COMPLEX &&
2439 pp->pv_type != PROP_VAL_LIST) {
2440 zerr(gettext("A %s or %s value was expected here."),
2441 pvt_to_str(PROP_VAL_COMPLEX),
2442 pvt_to_str(PROP_VAL_LIST));
2443 saw_error = B_TRUE;
2444 return;
2445 }
2446 if (pp->pv_type == PROP_VAL_COMPLEX) {
2447 do_complex_rctl_val(pp->pv_complex);
2448 return;
2513 return;
2514 }
2515
2516 if (zone_is_read_only(CMD_ADD))
2517 return;
2518
2519 if (initialize(B_TRUE) != Z_OK)
2520 return;
2521 if (global_scope) {
2522 if (gz_invalid_resource(cmd->cmd_res_type)) {
2523 zerr(gettext("Cannot add a %s resource to the "
2524 "global zone."), rt_to_str(cmd->cmd_res_type));
2525 saw_error = B_TRUE;
2526 return;
2527 }
2528
2529 global_scope = B_FALSE;
2530 resource_scope = cmd->cmd_res_type;
2531 end_op = CMD_ADD;
2532 add_resource(cmd);
2533 } else
2534 add_property(cmd);
2535 }
2536
2537 /*
2538 * This routine has an unusual implementation, because it tries very
2539 * hard to succeed in the face of a variety of failure modes.
2540 * The most common and most vexing occurs when the index file and
2541 * the /etc/zones/<zonename.xml> file are not both present. In
2542 * this case, delete must eradicate as much of the zone state as is left
2543 * so that the user can later create a new zone with the same name.
2544 */
2545 void
2546 delete_func(cmd_t *cmd)
2547 {
2548 int err, arg, answer;
2549 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
2550 boolean_t force = B_FALSE;
2551 boolean_t arg_err = B_FALSE;
2552
2553 optind = 0;
2554 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2712 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2713 zerr(gettext("A simple value was expected here."));
2714 saw_error = B_TRUE;
2715 return (Z_INSUFFICIENT_SPEC);
2716 }
2717 switch (cmd->cmd_prop_name[i]) {
2718 case PT_ADDRESS:
2719 (void) strlcpy(nwiftab->zone_nwif_address,
2720 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2721 break;
2722 case PT_ALLOWED_ADDRESS:
2723 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2724 pp->pv_simple,
2725 sizeof (nwiftab->zone_nwif_allowed_address));
2726 break;
2727 case PT_PHYSICAL:
2728 (void) strlcpy(nwiftab->zone_nwif_physical,
2729 pp->pv_simple,
2730 sizeof (nwiftab->zone_nwif_physical));
2731 break;
2732 case PT_DEFROUTER:
2733 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2734 pp->pv_simple,
2735 sizeof (nwiftab->zone_nwif_defrouter));
2736 break;
2737 default:
2738 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2739 Z_NO_PROPERTY_TYPE, B_TRUE);
2740 return (Z_INSUFFICIENT_SPEC);
2741 }
2742 }
2743 if (fill_in_only)
2744 return (Z_OK);
2745 err = zonecfg_lookup_nwif(handle, nwiftab);
2746 return (err);
2747 }
2748
2749 static int
2750 fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
2751 {
3229 uint64_t tmp;
3230
3231 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3232 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
3233 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3234 saw_error = B_TRUE;
3235 return;
3236 }
3237
3238 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
3239 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3240 else
3241 need_to_commit = B_TRUE;
3242 }
3243
3244 static void
3245 remove_mcap()
3246 {
3247 int err, res1, res2, res3;
3248 uint64_t tmp;
3249 struct zone_mcaptab mcaptab;
3250 boolean_t revert = B_FALSE;
3251
3252 res1 = zonecfg_lookup_mcap(handle, &mcaptab);
3253 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3254 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3255
3256 /* if none of these exist, there is no resource to remove */
3257 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3258 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
3259 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3260 saw_error = B_TRUE;
3261 return;
3262 }
3263 if (res1 == Z_OK) {
3264 if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
3265 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3266 revert = B_TRUE;
3267 } else {
3268 need_to_commit = B_TRUE;
3269 }
3270 }
3271 if (res2 == Z_OK) {
3272 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3273 != Z_OK) {
3274 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3275 revert = B_TRUE;
3276 } else {
3277 need_to_commit = B_TRUE;
3278 }
3279 }
3280 if (res3 == Z_OK) {
3281 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3282 != Z_OK) {
3283 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3284 revert = B_TRUE;
3285 } else {
3286 need_to_commit = B_TRUE;
3287 }
3288 }
3289
3290 if (revert)
3393 remove_mcap();
3394 return;
3395 case RT_ADMIN:
3396 remove_admin(cmd);
3397 return;
3398 default:
3399 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3400 long_usage(CMD_REMOVE, B_TRUE);
3401 usage(B_FALSE, HELP_RESOURCES);
3402 return;
3403 }
3404 }
3405
3406 static void
3407 remove_property(cmd_t *cmd)
3408 {
3409 char *prop_id;
3410 int err, res_type, prop_type;
3411 property_value_ptr_t pp;
3412 struct zone_rctlvaltab *rctlvaltab;
3413 complex_property_ptr_t cx;
3414
3415 res_type = resource_scope;
3416 prop_type = cmd->cmd_prop_name[0];
3417 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3418 long_usage(CMD_REMOVE, B_TRUE);
3419 return;
3420 }
3421
3422 if (cmd->cmd_prop_nv_pairs != 1) {
3423 long_usage(CMD_ADD, B_TRUE);
3424 return;
3425 }
3426
3427 if (initialize(B_TRUE) != Z_OK)
3428 return;
3429
3430 switch (res_type) {
3431 case RT_FS:
3432 if (prop_type != PT_OPTIONS) {
3453 err = zonecfg_remove_fs_option(&in_progress_fstab,
3454 prop_id);
3455 if (err != Z_OK)
3456 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3457 } else {
3458 list_property_ptr_t list;
3459
3460 for (list = pp->pv_list; list != NULL;
3461 list = list->lp_next) {
3462 prop_id = list->lp_simple;
3463 if (prop_id == NULL)
3464 break;
3465 err = zonecfg_remove_fs_option(
3466 &in_progress_fstab, prop_id);
3467 if (err != Z_OK)
3468 zone_perror(pt_to_str(prop_type), err,
3469 B_TRUE);
3470 }
3471 }
3472 return;
3473 case RT_RCTL:
3474 if (prop_type != PT_VALUE) {
3475 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3476 B_TRUE);
3477 long_usage(CMD_REMOVE, B_TRUE);
3478 usage(B_FALSE, HELP_PROPS);
3479 return;
3480 }
3481 pp = cmd->cmd_property_ptr[0];
3482 if (pp->pv_type != PROP_VAL_COMPLEX) {
3483 zerr(gettext("A %s value was expected here."),
3484 pvt_to_str(PROP_VAL_COMPLEX));
3485 saw_error = B_TRUE;
3486 return;
3487 }
3488 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3489 zone_perror(zone, Z_NOMEM, B_TRUE);
3490 exit(Z_ERR);
3491 }
3492 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
3505 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3506 cx->cp_value,
3507 sizeof (rctlvaltab->zone_rctlval_action));
3508 break;
3509 default:
3510 zone_perror(pt_to_str(prop_type),
3511 Z_NO_PROPERTY_TYPE, B_TRUE);
3512 long_usage(CMD_ADD, B_TRUE);
3513 usage(B_FALSE, HELP_PROPS);
3514 zonecfg_free_rctl_value_list(rctlvaltab);
3515 return;
3516 }
3517 }
3518 rctlvaltab->zone_rctlval_next = NULL;
3519 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3520 rctlvaltab);
3521 if (err != Z_OK)
3522 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3523 zonecfg_free_rctl_value_list(rctlvaltab);
3524 return;
3525 case RT_NET:
3526 if (prop_type != PT_DEFROUTER) {
3527 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3528 B_TRUE);
3529 long_usage(CMD_REMOVE, B_TRUE);
3530 usage(B_FALSE, HELP_PROPS);
3531 return;
3532 } else {
3533 bzero(&in_progress_nwiftab.zone_nwif_defrouter,
3534 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
3535 return;
3536 }
3537 default:
3538 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3539 long_usage(CMD_REMOVE, B_TRUE);
3540 usage(B_FALSE, HELP_RESOURCES);
3541 return;
3542 }
3543 }
3544
3545 void
3546 remove_func(cmd_t *cmd)
3547 {
3548 if (zone_is_read_only(CMD_REMOVE))
3549 return;
3550
3551 assert(cmd != NULL);
3552
3553 if (global_scope) {
3554 if (gz_invalid_resource(cmd->cmd_res_type)) {
3555 zerr(gettext("%s is not a valid resource for the "
3556 "global zone."), rt_to_str(cmd->cmd_res_type));
3579 return;
3580
3581 switch (res_type) {
3582 case RT_FS:
3583 if (prop_type == PT_RAW) {
3584 in_progress_fstab.zone_fs_raw[0] = '\0';
3585 need_to_commit = B_TRUE;
3586 return;
3587 }
3588 break;
3589 case RT_DCPU:
3590 if (prop_type == PT_IMPORTANCE) {
3591 in_progress_psettab.zone_importance[0] = '\0';
3592 need_to_commit = B_TRUE;
3593 return;
3594 }
3595 break;
3596 case RT_MCAP:
3597 switch (prop_type) {
3598 case PT_PHYSICAL:
3599 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3600 need_to_commit = B_TRUE;
3601 return;
3602 case PT_SWAP:
3603 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3604 return;
3605 case PT_LOCKED:
3606 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3607 return;
3608 }
3609 break;
3610 default:
3611 break;
3612 }
3613
3614 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3615 }
3616
3617 static void
3618 clear_global(cmd_t *cmd)
3619 {
3620 int err, type;
3621
3622 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3623 long_usage(CMD_CLEAR, B_TRUE);
3624 return;
3625 }
3626
3627 if (initialize(B_TRUE) != Z_OK)
3628 return;
3629
3722
3723 assert(cmd != NULL);
3724
3725 if (global_scope) {
3726 if (gz_invalid_property(cmd->cmd_res_type)) {
3727 zerr(gettext("%s is not a valid property for the "
3728 "global zone."), pt_to_str(cmd->cmd_res_type));
3729 saw_error = B_TRUE;
3730 return;
3731 }
3732
3733 clear_global(cmd);
3734 } else {
3735 clear_property(cmd);
3736 }
3737 }
3738
3739 void
3740 select_func(cmd_t *cmd)
3741 {
3742 int type, err, res;
3743 uint64_t limit;
3744 uint64_t tmp;
3745
3746 if (zone_is_read_only(CMD_SELECT))
3747 return;
3748
3749 assert(cmd != NULL);
3750
3751 if (global_scope) {
3752 global_scope = B_FALSE;
3753 resource_scope = cmd->cmd_res_type;
3754 end_op = CMD_SELECT;
3755 } else {
3756 scope_usage(CMD_SELECT);
3757 return;
3758 }
3759
3760 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3761 long_usage(CMD_SELECT, B_TRUE);
3762 return;
3817 bcopy(&old_dstab, &in_progress_dstab,
3818 sizeof (struct zone_dstab));
3819 return;
3820 case RT_DCPU:
3821 if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
3822 z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
3823 global_scope = B_TRUE;
3824 }
3825 bcopy(&old_psettab, &in_progress_psettab,
3826 sizeof (struct zone_psettab));
3827 return;
3828 case RT_PCAP:
3829 if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
3830 != Z_OK) {
3831 z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
3832 global_scope = B_TRUE;
3833 }
3834 return;
3835 case RT_MCAP:
3836 /* if none of these exist, there is no resource to select */
3837 if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
3838 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
3839 != Z_OK &&
3840 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
3841 != Z_OK) {
3842 z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
3843 B_TRUE);
3844 global_scope = B_TRUE;
3845 }
3846 if (res == Z_OK)
3847 bcopy(&old_mcaptab, &in_progress_mcaptab,
3848 sizeof (struct zone_mcaptab));
3849 else
3850 bzero(&in_progress_mcaptab,
3851 sizeof (in_progress_mcaptab));
3852 return;
3853 case RT_ADMIN:
3854 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
3855 != Z_OK) {
3856 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
3857 B_TRUE);
3858 global_scope = B_TRUE;
3859 }
3860 bcopy(&old_admintab, &in_progress_admintab,
3861 sizeof (struct zone_admintab));
3862 return;
3863 default:
3864 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3865 long_usage(CMD_SELECT, B_TRUE);
3866 usage(B_FALSE, HELP_RESOURCES);
3867 return;
3868 }
3869 }
3870
3871 /*
4098 if (prop_type == PT_ADDRESS) {
4099 (void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
4100 sizeof (in_progress_nwiftab.zone_nwif_address));
4101 } else {
4102 assert(prop_type == PT_ALLOWED_ADDRESS);
4103 (void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
4104 prop_id,
4105 sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
4106 }
4107 }
4108
4109 void
4110 set_func(cmd_t *cmd)
4111 {
4112 char *prop_id;
4113 int arg, err, res_type, prop_type;
4114 property_value_ptr_t pp;
4115 boolean_t autoboot;
4116 zone_iptype_t iptype;
4117 boolean_t force_set = B_FALSE;
4118 size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
4119 uint64_t mem_cap, mem_limit;
4120 float cap;
4121 char *unitp;
4122 struct zone_psettab tmp_psettab;
4123 boolean_t arg_err = B_FALSE;
4124
4125 if (zone_is_read_only(CMD_SET))
4126 return;
4127
4128 assert(cmd != NULL);
4129
4130 optind = opterr = 0;
4131 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
4132 switch (arg) {
4133 case 'F':
4134 force_set = B_TRUE;
4135 break;
4136 default:
4137 if (optopt == '?')
4138 longer_usage(CMD_SET);
4139 else
4140 short_usage(CMD_SET);
4202
4203 if (force_set) {
4204 if (res_type != RT_ZONEPATH) {
4205 zerr(gettext("Only zonepath setting can be forced."));
4206 saw_error = B_TRUE;
4207 return;
4208 }
4209 if (!zonecfg_in_alt_root()) {
4210 zerr(gettext("Zonepath is changeable only in an "
4211 "alternate root."));
4212 saw_error = B_TRUE;
4213 return;
4214 }
4215 }
4216
4217 pp = cmd->cmd_property_ptr[0];
4218 /*
4219 * A nasty expression but not that complicated:
4220 * 1. fs options are simple or list (tested below)
4221 * 2. rctl value's are complex or list (tested below)
4222 * Anything else should be simple.
4223 */
4224 if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
4225 !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
4226 (pp->pv_type != PROP_VAL_SIMPLE ||
4227 (prop_id = pp->pv_simple) == NULL)) {
4228 zerr(gettext("A %s value was expected here."),
4229 pvt_to_str(PROP_VAL_SIMPLE));
4230 saw_error = B_TRUE;
4231 return;
4232 }
4233 if (prop_type == PT_UNKNOWN) {
4234 long_usage(CMD_SET, B_TRUE);
4235 return;
4236 }
4237
4238 /*
4239 * Special case: the user can change the zone name prior to 'create';
4240 * if the zone already exists, we fall through letting initialize()
4241 * and the rest of the logic run.
4242 */
4243 if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4244 !state_atleast(ZONE_STATE_CONFIGURED)) {
4245 if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
4465 case RT_NET:
4466 switch (prop_type) {
4467 case PT_ADDRESS:
4468 case PT_ALLOWED_ADDRESS:
4469 if (validate_net_address_syntax(prop_id, B_FALSE)
4470 != Z_OK) {
4471 saw_error = B_TRUE;
4472 return;
4473 }
4474 set_in_progress_nwiftab_address(prop_id, prop_type);
4475 break;
4476 case PT_PHYSICAL:
4477 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4478 saw_error = B_TRUE;
4479 return;
4480 }
4481 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4482 prop_id,
4483 sizeof (in_progress_nwiftab.zone_nwif_physical));
4484 break;
4485 case PT_DEFROUTER:
4486 if (validate_net_address_syntax(prop_id, B_TRUE)
4487 != Z_OK) {
4488 saw_error = B_TRUE;
4489 return;
4490 }
4491 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
4492 prop_id,
4493 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
4494 break;
4495 default:
4496 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4497 B_TRUE);
4498 long_usage(CMD_SET, B_TRUE);
4499 usage(B_FALSE, HELP_PROPS);
4500 return;
4501 }
4502 return;
4503 case RT_DEVICE:
4504 switch (prop_type) {
4505 case PT_MATCH:
4506 (void) strlcpy(in_progress_devtab.zone_dev_match,
4507 prop_id,
4508 sizeof (in_progress_devtab.zone_dev_match));
4509 break;
4510 default:
4511 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4512 B_TRUE);
4513 long_usage(CMD_SET, B_TRUE);
4514 usage(B_FALSE, HELP_PROPS);
4515 return;
4516 }
4517 return;
4518 case RT_RCTL:
4519 switch (prop_type) {
4520 case PT_NAME:
4521 if (!zonecfg_valid_rctlname(prop_id)) {
4522 zerr(gettext("'%s' is not a valid zone %s "
4523 "name."), prop_id, rt_to_str(RT_RCTL));
4524 return;
4525 }
4526 (void) strlcpy(in_progress_rctltab.zone_rctl_name,
4527 prop_id,
4528 sizeof (in_progress_rctltab.zone_rctl_name));
4529 break;
4633 break;
4634 }
4635 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4636 long_usage(CMD_SET, B_TRUE);
4637 usage(B_FALSE, HELP_PROPS);
4638 return;
4639 case RT_PCAP:
4640 if (prop_type != PT_NCPUS) {
4641 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4642 B_TRUE);
4643 long_usage(CMD_SET, B_TRUE);
4644 usage(B_FALSE, HELP_PROPS);
4645 return;
4646 }
4647
4648 /*
4649 * We already checked that an rctl alias is allowed in
4650 * the add_resource() function.
4651 */
4652
4653 if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
4654 (int)(cap * 100) < 1) {
4655 zerr(gettext("%s property is out of range."),
4656 pt_to_str(PT_NCPUS));
4657 saw_error = B_TRUE;
4658 return;
4659 }
4660
4661 if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
4662 (int)(cap * 100))) != Z_OK)
4663 zone_perror(zone, err, B_TRUE);
4664 else
4665 need_to_commit = B_TRUE;
4666 return;
4667 case RT_MCAP:
4668 switch (prop_type) {
4669 case PT_PHYSICAL:
4670 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4671 zerr(gettext("A positive number with a "
4672 "required scale suffix (K, M, G or T) was "
4673 "expected here."));
4674 saw_error = B_TRUE;
4675 } else if (mem_cap < ONE_MB) {
4676 zerr(gettext("%s value is too small. It must "
4677 "be at least 1M."), pt_to_str(PT_PHYSICAL));
4678 saw_error = B_TRUE;
4679 } else {
4680 snprintf(in_progress_mcaptab.zone_physmem_cap,
4681 physmem_size, "%llu", mem_cap);
4682 }
4683 break;
4684 case PT_SWAP:
4685 /*
4686 * We have to check if an rctl is allowed here since
4687 * there might already be a rctl defined that blocks
4688 * the alias.
4689 */
4690 if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
4691 zone_perror(pt_to_str(PT_MAXSWAP),
4692 Z_ALIAS_DISALLOW, B_FALSE);
4693 saw_error = B_TRUE;
4694 return;
4695 }
4696
4697 if (global_zone)
4698 mem_limit = ONE_MB * 100;
4699 else
4700 mem_limit = ONE_MB * 50;
4701
5014 strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
5015 goto loopend; /* no match */
5016 output_fs(fp, &lookup);
5017 output = B_TRUE;
5018 loopend:
5019 zonecfg_free_fs_option_list(lookup.zone_fs_options);
5020 }
5021 (void) zonecfg_endfsent(handle);
5022 /*
5023 * If a property n/v pair was specified, warn the user if there was
5024 * nothing to output.
5025 */
5026 if (!output && cmd->cmd_prop_nv_pairs > 0)
5027 (void) printf(gettext("No such %s resource.\n"),
5028 rt_to_str(RT_FS));
5029 }
5030
5031 static void
5032 output_net(FILE *fp, struct zone_nwiftab *nwiftab)
5033 {
5034 (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
5035 output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
5036 output_prop(fp, PT_ALLOWED_ADDRESS,
5037 nwiftab->zone_nwif_allowed_address, B_TRUE);
5038 output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
5039 output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
5040 }
5041
5042 static void
5043 info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5044 {
5045 struct zone_nwiftab lookup, user;
5046 boolean_t output = B_FALSE;
5047
5048 if (zonecfg_setnwifent(handle) != Z_OK)
5049 return;
5050 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
5051 if (cmd->cmd_prop_nv_pairs == 0) {
5052 output_net(fp, &lookup);
5053 continue;
5054 }
5055 if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
5056 continue;
5057 if (strlen(user.zone_nwif_physical) > 0 &&
5058 strcmp(user.zone_nwif_physical,
5059 lookup.zone_nwif_physical) != 0)
5062 if (strlen(user.zone_nwif_address) > 0 &&
5063 !zonecfg_same_net_address(user.zone_nwif_address,
5064 lookup.zone_nwif_address))
5065 continue; /* no match */
5066 output_net(fp, &lookup);
5067 output = B_TRUE;
5068 }
5069 (void) zonecfg_endnwifent(handle);
5070 /*
5071 * If a property n/v pair was specified, warn the user if there was
5072 * nothing to output.
5073 */
5074 if (!output && cmd->cmd_prop_nv_pairs > 0)
5075 (void) printf(gettext("No such %s resource.\n"),
5076 rt_to_str(RT_NET));
5077 }
5078
5079 static void
5080 output_dev(FILE *fp, struct zone_devtab *devtab)
5081 {
5082 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
5083 output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
5084 }
5085
5086 static void
5087 info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5088 {
5089 struct zone_devtab lookup, user;
5090 boolean_t output = B_FALSE;
5091
5092 if (zonecfg_setdevent(handle) != Z_OK)
5093 return;
5094 while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
5095 if (cmd->cmd_prop_nv_pairs == 0) {
5096 output_dev(fp, &lookup);
5097 continue;
5098 }
5099 if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
5100 continue;
5101 if (strlen(user.zone_dev_match) > 0 &&
5102 strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
5103 continue; /* no match */
5322 if (num < 1024) {
5323 (void) snprintf(buf, bufsize, "%llu", num);
5324 return;
5325 }
5326
5327 while ((num >= 1024) && (*up != 'T')) {
5328 up++; /* next unit of measurement */
5329 save = num;
5330 num = (num + 512) >> 10;
5331 }
5332
5333 /* check if we should output a fraction. snprintf will round for us */
5334 if (save % 1024 != 0 && ((save >> 10) < 10))
5335 (void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
5336 *up);
5337 else
5338 (void) snprintf(buf, bufsize, "%llu%c", num, *up);
5339 }
5340
5341 static void
5342 output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
5343 uint64_t maxswap, int showlocked, uint64_t maxlocked)
5344 {
5345 char buf[128];
5346
5347 (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
5348 if (mcaptab->zone_physmem_cap[0] != '\0') {
5349 bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
5350 output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
5351 }
5352
5353 if (showswap == Z_OK) {
5354 (void) snprintf(buf, sizeof (buf), "%llu", maxswap);
5355 bytes_to_units(buf, buf, sizeof (buf));
5356 output_prop(fp, PT_SWAP, buf, B_TRUE);
5357 }
5358
5359 if (showlocked == Z_OK) {
5360 (void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
5361 bytes_to_units(buf, buf, sizeof (buf));
5362 output_prop(fp, PT_LOCKED, buf, B_TRUE);
5363 }
5364 }
5365
5366 static void
5367 info_mcap(zone_dochandle_t handle, FILE *fp)
5368 {
5369 int res1, res2, res3;
5370 uint64_t swap_limit;
5371 uint64_t locked_limit;
5372 struct zone_mcaptab lookup;
5373
5374 bzero(&lookup, sizeof (lookup));
5375 res1 = zonecfg_getmcapent(handle, &lookup);
5376 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5377 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5378 &locked_limit);
5379
5380 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5381 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5382 }
5383
5384 static void
5385 output_auth(FILE *fp, struct zone_admintab *admintab)
5386 {
5387 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5388 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5389 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5390 }
5391
5392 static void
5393 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5394 {
5395 struct zone_admintab lookup, user;
5396 boolean_t output = B_FALSE;
5397 int err;
5398
5399 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5400 zone_perror(zone, err, B_TRUE);
5401 return;
5412 continue; /* no match */
5413 output_auth(fp, &lookup);
5414 output = B_TRUE;
5415 }
5416 (void) zonecfg_endadminent(handle);
5417 /*
5418 * If a property n/v pair was specified, warn the user if there was
5419 * nothing to output.
5420 */
5421 if (!output && cmd->cmd_prop_nv_pairs > 0)
5422 (void) printf(gettext("No such %s resource.\n"),
5423 rt_to_str(RT_ADMIN));
5424 }
5425
5426 void
5427 info_func(cmd_t *cmd)
5428 {
5429 FILE *fp = stdout;
5430 boolean_t need_to_close = B_FALSE;
5431 int type;
5432 int res1, res2;
5433 uint64_t swap_limit;
5434 uint64_t locked_limit;
5435
5436 assert(cmd != NULL);
5437
5438 if (initialize(B_TRUE) != Z_OK)
5439 return;
5440
5441 /* don't page error output */
5442 if (interactive_mode) {
5443 if ((fp = pager_open()) != NULL)
5444 need_to_close = B_TRUE;
5445 else
5446 fp = stdout;
5447
5448 setbuf(fp, NULL);
5449 }
5450
5451 if (!global_scope) {
5452 switch (resource_scope) {
5453 case RT_FS:
5454 output_fs(fp, &in_progress_fstab);
5462 case RT_RCTL:
5463 output_rctl(fp, &in_progress_rctltab);
5464 break;
5465 case RT_ATTR:
5466 output_attr(fp, &in_progress_attrtab);
5467 break;
5468 case RT_DATASET:
5469 output_ds(fp, &in_progress_dstab);
5470 break;
5471 case RT_DCPU:
5472 output_pset(fp, &in_progress_psettab);
5473 break;
5474 case RT_PCAP:
5475 output_pcap(fp);
5476 break;
5477 case RT_MCAP:
5478 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5479 &swap_limit);
5480 res2 = zonecfg_get_aliased_rctl(handle,
5481 ALIAS_MAXLOCKEDMEM, &locked_limit);
5482 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5483 res2, locked_limit);
5484 break;
5485 case RT_ADMIN:
5486 output_auth(fp, &in_progress_admintab);
5487 break;
5488 }
5489 goto cleanup;
5490 }
5491
5492 type = cmd->cmd_res_type;
5493
5494 if (gz_invalid_rt_property(type)) {
5495 zerr(gettext("%s is not a valid property for the global zone."),
5496 rt_to_str(type));
5497 goto cleanup;
5498 }
5499
5500 if (gz_invalid_resource(type)) {
5501 zerr(gettext("%s is not a valid resource for the global zone."),
5502 rt_to_str(type));
6084 pt_to_str(PT_USER),
6085 admintab.zone_admin_user);
6086 ret_val = Z_BAD_PROPERTY;
6087 }
6088 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6089 admintab.zone_admin_auths, zone))) {
6090 ret_val = Z_BAD_PROPERTY;
6091 }
6092 }
6093 (void) zonecfg_endadminent(handle);
6094
6095 if (!global_scope) {
6096 zerr(gettext("resource specification incomplete"));
6097 saw_error = B_TRUE;
6098 if (ret_val == Z_OK)
6099 ret_val = Z_INSUFFICIENT_SPEC;
6100 }
6101
6102 if (save) {
6103 if (ret_val == Z_OK) {
6104 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6105 need_to_commit = B_FALSE;
6106 (void) strlcpy(revert_zone, zone,
6107 sizeof (revert_zone));
6108 }
6109 } else {
6110 zerr(gettext("Zone %s failed to verify"), zone);
6111 }
6112 }
6113 if (ret_val != Z_OK)
6114 zone_perror(zone, ret_val, B_TRUE);
6115 }
6116
6117 void
6118 cancel_func(cmd_t *cmd)
6119 {
6120 int arg;
6121 boolean_t arg_err = B_FALSE;
6122
6123 assert(cmd != NULL);
6258 pt_to_str(PT_ALLOWED_ADDRESS),
6259 nwif.zone_nwif_allowed_address);
6260 }
6261 }
6262
6263 void
6264 end_func(cmd_t *cmd)
6265 {
6266 boolean_t validation_failed = B_FALSE;
6267 boolean_t arg_err = B_FALSE;
6268 struct zone_fstab tmp_fstab;
6269 struct zone_nwiftab tmp_nwiftab;
6270 struct zone_devtab tmp_devtab;
6271 struct zone_rctltab tmp_rctltab;
6272 struct zone_attrtab tmp_attrtab;
6273 struct zone_dstab tmp_dstab;
6274 struct zone_admintab tmp_admintab;
6275 int err, arg, res1, res2, res3;
6276 uint64_t swap_limit;
6277 uint64_t locked_limit;
6278 uint64_t proc_cap;
6279
6280 assert(cmd != NULL);
6281
6282 optind = 0;
6283 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6284 switch (arg) {
6285 case '?':
6286 longer_usage(CMD_END);
6287 arg_err = B_TRUE;
6288 break;
6289 default:
6290 short_usage(CMD_END);
6291 arg_err = B_TRUE;
6292 break;
6293 }
6294 }
6295 if (arg_err)
6296 return;
6297
6561
6562 if (end_op == CMD_ADD) {
6563 err = zonecfg_add_pset(handle, &in_progress_psettab);
6564 } else {
6565 err = zonecfg_modify_pset(handle, &in_progress_psettab);
6566 }
6567 break;
6568 case RT_PCAP:
6569 /* Make sure everything was filled in. */
6570 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
6571 != Z_OK) {
6572 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
6573 saw_error = B_TRUE;
6574 validation_failed = B_TRUE;
6575 return;
6576 }
6577 err = Z_OK;
6578 break;
6579 case RT_MCAP:
6580 /* Make sure everything was filled in. */
6581 res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
6582 Z_ERR : Z_OK;
6583 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
6584 &swap_limit);
6585 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
6586 &locked_limit);
6587
6588 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
6589 zerr(gettext("No property was specified. One of %s, "
6590 "%s or %s is required."), pt_to_str(PT_PHYSICAL),
6591 pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
6592 saw_error = B_TRUE;
6593 return;
6594 }
6595
6596 /* if phys & locked are both set, verify locked <= phys */
6597 if (res1 == Z_OK && res3 == Z_OK) {
6598 uint64_t phys_limit;
6599 char *endp;
6600
6601 phys_limit = strtoull(
6602 in_progress_mcaptab.zone_physmem_cap, &endp, 10);
6603 if (phys_limit < locked_limit) {
6604 zerr(gettext("The %s cap must be less than or "
6605 "equal to the %s cap."),
6606 pt_to_str(PT_LOCKED),
6607 pt_to_str(PT_PHYSICAL));
6608 saw_error = B_TRUE;
6609 return;
6610 }
6611 }
6612
6613 err = Z_OK;
6614 if (res1 == Z_OK) {
6615 /*
6616 * We could be ending from either an add operation
6617 * or a select operation. Since all of the properties
6618 * within this resource are optional, we always use
6619 * modify on the mcap entry. zonecfg_modify_mcap()
6620 * will handle both adding and modifying a memory cap.
6621 */
6622 err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
6623 } else if (end_op == CMD_SELECT) {
6624 /*
6625 * If we're ending from a select and the physical
6626 * memory cap is empty then the user could have cleared
6627 * the physical cap value, so try to delete the entry.
6628 */
6629 (void) zonecfg_delete_mcap(handle);
6630 }
6631 break;
6632 case RT_ADMIN:
6633 /* First make sure everything was filled in. */
6634 if (end_check_reqd(in_progress_admintab.zone_admin_user,
6635 PT_USER, &validation_failed) == Z_OK) {
6636 if (getpwnam(in_progress_admintab.zone_admin_user)
6637 == NULL) {
6638 zerr(gettext("%s %s is not a valid username"),
6639 pt_to_str(PT_USER),
6640 in_progress_admintab.zone_admin_user);
6641 validation_failed = B_TRUE;
6642 }
6643 }
6644
6645 if (end_check_reqd(in_progress_admintab.zone_admin_auths,
6646 PT_AUTHS, &validation_failed) == Z_OK) {
6647 if (!zonecfg_valid_auths(
6648 in_progress_admintab.zone_admin_auths,
6649 zone)) {
6650 validation_failed = B_TRUE;
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2014 Gary Mills
26 * Copyright 2016, Joyent Inc.
27 */
28
29 /*
30 * zonecfg is a lex/yacc based command interpreter used to manage zone
31 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
32 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
33 * which takes resources and/or properties as arguments. See the block
34 * comments near the end of zonecfg_grammar.y for how the data structures
35 * which keep track of these resources and properties are built up.
36 *
37 * The resource/property data structures are inserted into a command
38 * structure (see zonecfg.h), which also keeps track of command names,
39 * miscellaneous arguments, and function handlers. The grammar selects
40 * the appropriate function handler, each of which takes a pointer to a
41 * command structure as its sole argument, and invokes it. The grammar
42 * itself is "entered" (a la the Matrix) by yyparse(), which is called
43 * from read_input(), our main driving function. That in turn is called
44 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
45 * of which is called from main() depending on how the program was invoked.
46 *
218 "importance",
219 "swap",
220 "locked",
221 ALIAS_SHARES,
222 ALIAS_MAXLWPS,
223 ALIAS_MAXSHMMEM,
224 ALIAS_MAXSHMIDS,
225 ALIAS_MAXMSGIDS,
226 ALIAS_MAXSEMIDS,
227 ALIAS_MAXLOCKEDMEM,
228 ALIAS_MAXSWAP,
229 "scheduling-class",
230 "ip-type",
231 "defrouter",
232 "hostid",
233 "user",
234 "auths",
235 "fs-allowed",
236 ALIAS_MAXPROCS,
237 "allowed-address",
238 ALIAS_ZFSPRI,
239 "mac-addr",
240 "vlan-id",
241 "global-nic",
242 "property",
243 NULL
244 };
245
246 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
247 static char *prop_val_types[] = {
248 "simple",
249 "complex",
250 "list",
251 };
252
253 /*
254 * The various _cmds[] lists below are for command tab-completion.
255 */
256
257 /*
258 * remove has a space afterwards because it has qualifiers; the other commands
259 * that have qualifiers (add, select, etc.) don't need a space here because
260 * they have their own _cmds[] lists below.
261 */
262 static const char *global_scope_cmds[] = {
395 "cancel",
396 "end",
397 "exit",
398 "help",
399 "info",
400 "remove options ",
401 "set dir=",
402 "set raw=",
403 "set special=",
404 "set type=",
405 "clear raw",
406 NULL
407 };
408
409 static const char *net_res_scope_cmds[] = {
410 "cancel",
411 "end",
412 "exit",
413 "help",
414 "info",
415 "add property ",
416 "clear allowed-address",
417 "clear defrouter",
418 "clear global-nic",
419 "clear mac-addr",
420 "clear vlan-id",
421 "remove property ",
422 "set address=",
423 "set allowed-address=",
424 "set defrouter=",
425 "set global-nic=",
426 "set mac-addr=",
427 "set physical=",
428 "set vlan-id=",
429 NULL
430 };
431
432 static const char *device_res_scope_cmds[] = {
433 "cancel",
434 "end",
435 "exit",
436 "help",
437 "info",
438 "add property ",
439 "set match=",
440 NULL
441 };
442
443 static const char *attr_res_scope_cmds[] = {
444 "cancel",
445 "end",
446 "exit",
447 "help",
448 "info",
449 "set name=",
450 "set type=",
451 "set value=",
452 NULL
453 };
454
455 static const char *rctl_res_scope_cmds[] = {
456 "add value ",
457 "cancel",
458 "end",
580
581 /* scope is outer/global or inner/resource */
582 static boolean_t global_scope = B_TRUE;
583 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
584 static int end_op = -1; /* operation on end is either add or modify */
585
586 int num_prop_vals; /* for grammar */
587
588 /*
589 * These are for keeping track of resources as they are specified as part of
590 * the multi-step process. They should be initialized by add_resource() or
591 * select_func() and filled in by add_property() or set_func().
592 */
593 static struct zone_fstab old_fstab, in_progress_fstab;
594 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
595 static struct zone_devtab old_devtab, in_progress_devtab;
596 static struct zone_rctltab old_rctltab, in_progress_rctltab;
597 static struct zone_attrtab old_attrtab, in_progress_attrtab;
598 static struct zone_dstab old_dstab, in_progress_dstab;
599 static struct zone_psettab old_psettab, in_progress_psettab;
600 static struct zone_admintab old_admintab, in_progress_admintab;
601
602 static GetLine *gl; /* The gl_get_line() resource object */
603
604 static void bytes_to_units(char *str, char *buf, int bufsize);
605
606 /* Functions begin here */
607
608 static boolean_t
609 initial_match(const char *line1, const char *line2, int word_end)
610 {
611 if (word_end <= 0)
612 return (B_TRUE);
613 return (strncmp(line1, line2, word_end) == 0);
614 }
615
616 static int
617 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
618 int word_end)
619 {
1078 pt_to_str(PT_OPTIONS),
1079 gettext("<file-system options>"));
1080 (void) fprintf(fp, "\t%s %s %s\n",
1081 cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
1082 gettext("<file-system options>"));
1083 (void) fprintf(fp, gettext("Consult the file-system "
1084 "specific manual page, such as mount_ufs(1M), "
1085 "for\ndetails about file-system options. Note "
1086 "that any file-system options with an\nembedded "
1087 "'=' character must be enclosed in double quotes, "
1088 /*CSTYLED*/
1089 "such as \"%s=5\".\n"), MNTOPT_RETRY);
1090 break;
1091 case RT_NET:
1092 (void) fprintf(fp, gettext("The '%s' resource scope is "
1093 "used to configure a network interface.\n"),
1094 rt_to_str(resource_scope));
1095 (void) fprintf(fp, gettext("Valid commands:\n"));
1096 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1097 pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
1098 (void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n",
1099 cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
1100 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1101 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1102 pt_to_str(PT_ALLOWED_ADDRESS),
1103 gettext("<IP-address>"));
1104 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1105 pt_to_str(PT_PHYSICAL), gettext("<interface>"));
1106 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1107 pt_to_str(PT_MAC), gettext("<mac-address>"));
1108 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1109 pt_to_str(PT_GNIC), gettext("<global zone NIC>"));
1110 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1111 pt_to_str(PT_VLANID), gettext("<vlan ID>"));
1112 (void) fprintf(fp, gettext("See ifconfig(1M) for "
1113 "details of the <interface> string.\n"));
1114 (void) fprintf(fp, gettext("%s %s is valid "
1115 "if the %s property is set to %s, otherwise it "
1116 "must not be set.\n"),
1117 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
1118 pt_to_str(PT_IPTYPE), gettext("shared"));
1119 (void) fprintf(fp, gettext("%s (%s, %s, %s, %s) are "
1120 "valid if the %s property is set to %s, otherwise "
1121 "they must not be set.\n"),
1122 cmd_to_str(CMD_SET),
1123 pt_to_str(PT_ALLOWED_ADDRESS), pt_to_str(PT_MAC),
1124 pt_to_str(PT_VLANID), pt_to_str(PT_GNIC),
1125 pt_to_str(PT_IPTYPE), gettext("exclusive"));
1126 (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
1127 "is valid if the %s or %s property is set, "
1128 "otherwise it must not be set\n"),
1129 cmd_to_str(CMD_SET),
1130 pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
1131 cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
1132 gettext(pt_to_str(PT_ADDRESS)),
1133 gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
1134 break;
1135 case RT_DEVICE:
1136 (void) fprintf(fp, gettext("The '%s' resource scope is "
1137 "used to configure a device node.\n"),
1138 rt_to_str(resource_scope));
1139 (void) fprintf(fp, gettext("Valid commands:\n"));
1140 (void) fprintf(fp, "\t%s %s (%s=<value>,%s=<value>)\n",
1141 cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
1142 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1143 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1144 pt_to_str(PT_MATCH), gettext("<device-path>"));
1145 break;
1146 case RT_RCTL:
1147 (void) fprintf(fp, gettext("The '%s' resource scope is "
1148 "used to configure a resource control.\n"),
1149 rt_to_str(resource_scope));
1150 (void) fprintf(fp, gettext("Valid commands:\n"));
1151 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1152 pt_to_str(PT_NAME), gettext("<string>"));
1153 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1154 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
1155 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1156 pt_to_str(PT_LIMIT), gettext("<number>"),
1157 pt_to_str(PT_ACTION), gettext("<action-value>"));
1158 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1159 cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
1160 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1161 pt_to_str(PT_LIMIT), gettext("<number>"),
1162 pt_to_str(PT_ACTION), gettext("<action-value>"));
1350 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1351 pt_to_str(PT_FS_ALLOWED));
1352 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1353 pt_to_str(PT_MAXLWPS));
1354 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1355 pt_to_str(PT_MAXPROCS));
1356 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1357 pt_to_str(PT_MAXSHMMEM));
1358 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1359 pt_to_str(PT_MAXSHMIDS));
1360 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1361 pt_to_str(PT_MAXMSGIDS));
1362 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1363 pt_to_str(PT_MAXSEMIDS));
1364 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1365 pt_to_str(PT_SHARES));
1366 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1367 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1368 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1369 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1370 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n",
1371 rt_to_str(RT_NET),
1372 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1373 pt_to_str(PT_GNIC), pt_to_str(PT_MAC),
1374 pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP),
1375 pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER));
1376 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE),
1377 pt_to_str(PT_MATCH), pt_to_str(PT_NPROP));
1378 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1379 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1380 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1381 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1382 pt_to_str(PT_VALUE));
1383 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1384 pt_to_str(PT_NAME));
1385 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1386 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1387 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1388 pt_to_str(PT_NCPUS));
1389 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1390 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1391 pt_to_str(PT_LOCKED));
1392 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1393 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1394 }
1395 if (need_to_close)
1396 (void) pager_close(fp);
1397 }
1412
1413 static void
1414 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1415 {
1416 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
1417 zonecfg_strerror(err));
1418 if (set_saw)
1419 saw_error = B_TRUE;
1420 }
1421
1422 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1423 static int
1424 initialize(boolean_t handle_expected)
1425 {
1426 int err;
1427 char brandname[MAXNAMELEN];
1428
1429 if (zonecfg_check_handle(handle) != Z_OK) {
1430 if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
1431 got_handle = B_TRUE;
1432
1433 (void) zonecfg_fix_obsolete(handle);
1434
1435 if (zonecfg_get_brand(handle, brandname,
1436 sizeof (brandname)) != Z_OK) {
1437 zerr("Zone %s is inconsistent: missing "
1438 "brand attribute", zone);
1439 exit(Z_ERR);
1440 }
1441 if ((brand = brand_open(brandname)) == NULL) {
1442 zerr("Zone %s uses non-existent brand \"%s\"."
1443 " Unable to continue", zone, brandname);
1444 exit(Z_ERR);
1445 }
1446 /*
1447 * If the user_attr file is newer than
1448 * the zone config file, the admins
1449 * may need to be updated since the
1450 * RBAC files are authoritative for
1451 * authorization checks.
1452 */
1453 err = zonecfg_update_userauths(handle, zone);
1454 if (err == Z_OK) {
1715 else
1716 short_usage(CMD_CREATE);
1717 arg_err = B_TRUE;
1718 break;
1719 case 'a':
1720 (void) strlcpy(attach_path, optarg,
1721 sizeof (attach_path));
1722 attach = B_TRUE;
1723 break;
1724 case 'b':
1725 (void) strlcpy(zone_template, "SUNWblank",
1726 sizeof (zone_template));
1727 break;
1728 case 'F':
1729 force = B_TRUE;
1730 break;
1731 case 't':
1732 (void) strlcpy(zone_template, optarg,
1733 sizeof (zone_template));
1734 break;
1735 case 'X':
1736 (void) snprintf(zone_template, sizeof (zone_template),
1737 "%s/%s.xml", ZONE_CONFIG_ROOT, zone);
1738 err = zonecfg_get_xml_handle(zone_template, handle);
1739 if (err != Z_OK) {
1740 zone_perror(execname, err, B_TRUE);
1741 exit(Z_ERR);
1742 }
1743 got_handle = B_TRUE;
1744 need_to_commit = B_TRUE;
1745 return;
1746 default:
1747 short_usage(CMD_CREATE);
1748 arg_err = B_TRUE;
1749 break;
1750 }
1751 }
1752 if (arg_err)
1753 return;
1754
1755 if (optind != cmd->cmd_argc) {
1756 short_usage(CMD_CREATE);
1757 return;
1758 }
1759
1760 if (zone_is_read_only(CMD_CREATE))
1761 return;
1762
1763 if (check_if_zone_already_exists(force) != Z_OK)
1764 return;
1765
1828 char *quote_str;
1829
1830 if (strlen(prop_id) == 0)
1831 return;
1832 quote_str = quoteit(prop_id);
1833 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1834 pt_to_str(prop_num), quote_str);
1835 free(quote_str);
1836 }
1837
1838 void
1839 export_func(cmd_t *cmd)
1840 {
1841 struct zone_nwiftab nwiftab;
1842 struct zone_fstab fstab;
1843 struct zone_devtab devtab;
1844 struct zone_attrtab attrtab;
1845 struct zone_rctltab rctltab;
1846 struct zone_dstab dstab;
1847 struct zone_psettab psettab;
1848 struct zone_rctlvaltab *valptr;
1849 struct zone_res_attrtab *rap;
1850 struct zone_admintab admintab;
1851 int err, arg;
1852 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1853 char bootargs[BOOTARGS_MAX];
1854 char sched[MAXNAMELEN];
1855 char brand[MAXNAMELEN];
1856 char hostidp[HW_HOSTID_LEN];
1857 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1858 char *limitpriv;
1859 FILE *of;
1860 boolean_t autoboot;
1861 zone_iptype_t iptype;
1862 boolean_t need_to_close = B_FALSE;
1863 boolean_t arg_err = B_FALSE;
1864
1865 assert(cmd != NULL);
1866
1867 outfile[0] = '\0';
1868 optind = 0;
1869 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1999 cmd_to_str(CMD_ADD),
2000 pt_to_str(PT_OPTIONS),
2001 optptr->zone_fsopt_opt);
2002 }
2003 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2004 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2005 }
2006 (void) zonecfg_endfsent(handle);
2007
2008 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2009 zone_perror(zone, err, B_FALSE);
2010 goto done;
2011 }
2012 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2013 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2014 rt_to_str(RT_NET));
2015 export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
2016 export_prop(of, PT_ALLOWED_ADDRESS,
2017 nwiftab.zone_nwif_allowed_address);
2018 export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
2019 export_prop(of, PT_MAC, nwiftab.zone_nwif_mac);
2020 export_prop(of, PT_VLANID, nwiftab.zone_nwif_vlan_id);
2021 export_prop(of, PT_GNIC, nwiftab.zone_nwif_gnic);
2022 export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
2023 for (rap = nwiftab.zone_nwif_attrp; rap != NULL;
2024 rap = rap->zone_res_attr_next) {
2025 fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n",
2026 cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
2027 pt_to_str(PT_NAME), rap->zone_res_attr_name,
2028 pt_to_str(PT_VALUE), rap->zone_res_attr_value);
2029 }
2030 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2031 }
2032 (void) zonecfg_endnwifent(handle);
2033
2034 if ((err = zonecfg_setdevent(handle)) != Z_OK) {
2035 zone_perror(zone, err, B_FALSE);
2036 goto done;
2037 }
2038 while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
2039 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2040 rt_to_str(RT_DEVICE));
2041 export_prop(of, PT_MATCH, devtab.zone_dev_match);
2042 for (rap = devtab.zone_dev_attrp; rap != NULL;
2043 rap = rap->zone_res_attr_next) {
2044 fprintf(of, "%s %s (%s=%s,%s=\"%s\")\n",
2045 cmd_to_str(CMD_ADD), pt_to_str(PT_NPROP),
2046 pt_to_str(PT_NAME), rap->zone_res_attr_name,
2047 pt_to_str(PT_VALUE), rap->zone_res_attr_value);
2048 }
2049 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2050 }
2051 (void) zonecfg_enddevent(handle);
2052
2053 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
2054 zone_perror(zone, err, B_FALSE);
2055 goto done;
2056 }
2057 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2058 (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
2059 export_prop(of, PT_NAME, rctltab.zone_rctl_name);
2060 for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
2061 valptr = valptr->zone_rctlval_next) {
2062 fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2063 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
2064 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
2065 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
2066 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
2067 }
2068 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2069 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2070 }
2071 (void) zonecfg_endrctlent(handle);
2072
2186 validate_zonepath_syntax(char *path)
2187 {
2188 if (path[0] != '/') {
2189 zerr(gettext("%s is not an absolute path."), path);
2190 return (Z_ERR);
2191 }
2192 /* If path is all slashes, then fail */
2193 if (strspn(path, "/") == strlen(path)) {
2194 zerr(gettext("/ is not allowed as a %s."),
2195 pt_to_str(PT_ZONEPATH));
2196 return (Z_ERR);
2197 }
2198 return (Z_OK);
2199 }
2200
2201 static void
2202 add_resource(cmd_t *cmd)
2203 {
2204 int type;
2205 struct zone_psettab tmp_psettab;
2206 uint64_t tmp;
2207 uint64_t tmp_mcap;
2208 char pool[MAXNAMELEN];
2209
2210 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2211 long_usage(CMD_ADD, B_TRUE);
2212 goto bad;
2213 }
2214
2215 switch (type) {
2216 case RT_FS:
2217 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2218 return;
2219 case RT_NET:
2220 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2221 return;
2222 case RT_DEVICE:
2223 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2224 return;
2225 case RT_RCTL:
2277 switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
2278 case Z_ALIAS_DISALLOW:
2279 zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
2280 B_FALSE);
2281 goto bad;
2282
2283 case Z_OK:
2284 zerr(gettext("The %s resource already exists."),
2285 rt_to_str(RT_PCAP));
2286 goto bad;
2287
2288 default:
2289 break;
2290 }
2291 return;
2292 case RT_MCAP:
2293 /*
2294 * Make sure there isn't already a mem-cap entry or max-swap
2295 * or max-locked rctl.
2296 */
2297 if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
2298 &tmp_mcap) == Z_OK ||
2299 zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM,
2300 &tmp_mcap) == Z_OK ||
2301 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2302 &tmp_mcap) == Z_OK) {
2303 zerr(gettext("The %s resource or a related resource "
2304 "control already exists."), rt_to_str(RT_MCAP));
2305 goto bad;
2306 }
2307 if (global_zone)
2308 zerr(gettext("WARNING: Setting a global zone memory "
2309 "cap too low could deny\nservice "
2310 "to even the root user; "
2311 "this could render the system impossible\n"
2312 "to administer. Please use caution."));
2313 return;
2314 case RT_ADMIN:
2315 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2316 return;
2317 default:
2318 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2319 long_usage(CMD_ADD, B_TRUE);
2320 usage(B_FALSE, HELP_RESOURCES);
2321 }
2322 bad:
2323 global_scope = B_TRUE;
2324 end_op = -1;
2325 }
2326
2327 static void
2328 do_complex_rctl_val(complex_property_ptr_t cp)
2329 {
2330 struct zone_rctlvaltab *rctlvaltab;
2331 complex_property_ptr_t cx;
2332 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2395 /*
2396 * Make sure the rctl value looks roughly correct; we won't know if
2397 * it's truly OK until we verify the configuration on the target
2398 * system.
2399 */
2400 if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
2401 !zonecfg_valid_rctlblk(rctlblk)) {
2402 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
2403 pt_to_str(PT_VALUE));
2404 goto bad;
2405 }
2406 err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
2407 if (err != Z_OK)
2408 zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
2409 return;
2410
2411 bad:
2412 zonecfg_free_rctl_value_list(rctlvaltab);
2413 }
2414
2415 /*
2416 * Resource attribute ("property" resource embedded on net or dev resource)
2417 */
2418 static void
2419 do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp)
2420 {
2421 complex_property_ptr_t cp;
2422 struct zone_res_attrtab *np;
2423 int err;
2424 boolean_t seen_name = B_FALSE, seen_value = B_FALSE;
2425
2426 if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) {
2427 zone_perror(zone, Z_NOMEM, B_TRUE);
2428 exit(Z_ERR);
2429 }
2430
2431 for (cp = cpp; cp != NULL; cp = cp->cp_next) {
2432 switch (cp->cp_type) {
2433 case PT_NAME:
2434 if (seen_name) {
2435 zerr(gettext("%s already specified"),
2436 pt_to_str(PT_NAME));
2437 goto bad;
2438 }
2439 (void) strlcpy(np->zone_res_attr_name, cp->cp_value,
2440 sizeof (np->zone_res_attr_name));
2441 seen_name = B_TRUE;
2442 break;
2443 case PT_VALUE:
2444 if (seen_value) {
2445 zerr(gettext("%s already specified"),
2446 pt_to_str(PT_VALUE));
2447 goto bad;
2448 }
2449 (void) strlcpy(np->zone_res_attr_value, cp->cp_value,
2450 sizeof (np->zone_res_attr_value));
2451 seen_value = B_TRUE;
2452 break;
2453 default:
2454 zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE,
2455 B_TRUE);
2456 long_usage(CMD_ADD, B_TRUE);
2457 usage(B_FALSE, HELP_PROPS);
2458 zonecfg_free_res_attr_list(np);
2459 return;
2460 }
2461 }
2462
2463 if (!seen_name)
2464 zerr(gettext("%s not specified"), pt_to_str(PT_NAME));
2465 if (!seen_value)
2466 zerr(gettext("%s not specified"), pt_to_str(PT_VALUE));
2467
2468 err = zonecfg_add_res_attr(headp, np);
2469 if (err != Z_OK)
2470 zone_perror(pt_to_str(PT_NPROP), err, B_TRUE);
2471 return;
2472
2473 bad:
2474 zonecfg_free_res_attr_list(np);
2475 }
2476
2477 static void
2478 add_property(cmd_t *cmd)
2479 {
2480 char *prop_id;
2481 int err, res_type, prop_type;
2482 property_value_ptr_t pp;
2483 list_property_ptr_t l;
2484
2485 res_type = resource_scope;
2486 prop_type = cmd->cmd_prop_name[0];
2487 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
2488 long_usage(CMD_ADD, B_TRUE);
2489 return;
2490 }
2491
2492 if (cmd->cmd_prop_nv_pairs != 1) {
2493 long_usage(CMD_ADD, B_TRUE);
2494 return;
2495 }
2496
2497 if (initialize(B_TRUE) != Z_OK)
2524 err = zonecfg_add_fs_option(&in_progress_fstab,
2525 prop_id);
2526 if (err != Z_OK)
2527 zone_perror(pt_to_str(prop_type), err, B_TRUE);
2528 } else {
2529 list_property_ptr_t list;
2530
2531 for (list = pp->pv_list; list != NULL;
2532 list = list->lp_next) {
2533 prop_id = list->lp_simple;
2534 if (prop_id == NULL)
2535 break;
2536 err = zonecfg_add_fs_option(
2537 &in_progress_fstab, prop_id);
2538 if (err != Z_OK)
2539 zone_perror(pt_to_str(prop_type), err,
2540 B_TRUE);
2541 }
2542 }
2543 return;
2544 case RT_NET:
2545 if (prop_type != PT_NPROP) {
2546 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2547 B_TRUE);
2548 long_usage(CMD_ADD, B_TRUE);
2549 usage(B_FALSE, HELP_PROPS);
2550 return;
2551 }
2552 pp = cmd->cmd_property_ptr[0];
2553 if (pp->pv_type != PROP_VAL_COMPLEX) {
2554 zerr(gettext("A %s value was expected here."),
2555 pvt_to_str(PROP_VAL_COMPLEX));
2556 saw_error = B_TRUE;
2557 return;
2558 }
2559
2560 do_res_attr(&(in_progress_nwiftab.zone_nwif_attrp),
2561 pp->pv_complex);
2562 return;
2563 case RT_DEVICE:
2564 if (prop_type != PT_NPROP) {
2565 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2566 B_TRUE);
2567 long_usage(CMD_ADD, B_TRUE);
2568 usage(B_FALSE, HELP_PROPS);
2569 return;
2570 }
2571 pp = cmd->cmd_property_ptr[0];
2572 if (pp->pv_type != PROP_VAL_COMPLEX) {
2573 zerr(gettext("A %s value was expected here."),
2574 pvt_to_str(PROP_VAL_COMPLEX));
2575 saw_error = B_TRUE;
2576 return;
2577 }
2578
2579 do_res_attr(&(in_progress_devtab.zone_dev_attrp),
2580 pp->pv_complex);
2581 return;
2582 case RT_RCTL:
2583 if (prop_type != PT_VALUE) {
2584 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2585 B_TRUE);
2586 long_usage(CMD_ADD, B_TRUE);
2587 usage(B_FALSE, HELP_PROPS);
2588 return;
2589 }
2590 pp = cmd->cmd_property_ptr[0];
2591 if (pp->pv_type != PROP_VAL_COMPLEX &&
2592 pp->pv_type != PROP_VAL_LIST) {
2593 zerr(gettext("A %s or %s value was expected here."),
2594 pvt_to_str(PROP_VAL_COMPLEX),
2595 pvt_to_str(PROP_VAL_LIST));
2596 saw_error = B_TRUE;
2597 return;
2598 }
2599 if (pp->pv_type == PROP_VAL_COMPLEX) {
2600 do_complex_rctl_val(pp->pv_complex);
2601 return;
2666 return;
2667 }
2668
2669 if (zone_is_read_only(CMD_ADD))
2670 return;
2671
2672 if (initialize(B_TRUE) != Z_OK)
2673 return;
2674 if (global_scope) {
2675 if (gz_invalid_resource(cmd->cmd_res_type)) {
2676 zerr(gettext("Cannot add a %s resource to the "
2677 "global zone."), rt_to_str(cmd->cmd_res_type));
2678 saw_error = B_TRUE;
2679 return;
2680 }
2681
2682 global_scope = B_FALSE;
2683 resource_scope = cmd->cmd_res_type;
2684 end_op = CMD_ADD;
2685 add_resource(cmd);
2686 } else {
2687 add_property(cmd);
2688 }
2689 }
2690
2691 /*
2692 * This routine has an unusual implementation, because it tries very
2693 * hard to succeed in the face of a variety of failure modes.
2694 * The most common and most vexing occurs when the index file and
2695 * the /etc/zones/<zonename.xml> file are not both present. In
2696 * this case, delete must eradicate as much of the zone state as is left
2697 * so that the user can later create a new zone with the same name.
2698 */
2699 void
2700 delete_func(cmd_t *cmd)
2701 {
2702 int err, arg, answer;
2703 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
2704 boolean_t force = B_FALSE;
2705 boolean_t arg_err = B_FALSE;
2706
2707 optind = 0;
2708 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2866 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2867 zerr(gettext("A simple value was expected here."));
2868 saw_error = B_TRUE;
2869 return (Z_INSUFFICIENT_SPEC);
2870 }
2871 switch (cmd->cmd_prop_name[i]) {
2872 case PT_ADDRESS:
2873 (void) strlcpy(nwiftab->zone_nwif_address,
2874 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2875 break;
2876 case PT_ALLOWED_ADDRESS:
2877 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2878 pp->pv_simple,
2879 sizeof (nwiftab->zone_nwif_allowed_address));
2880 break;
2881 case PT_PHYSICAL:
2882 (void) strlcpy(nwiftab->zone_nwif_physical,
2883 pp->pv_simple,
2884 sizeof (nwiftab->zone_nwif_physical));
2885 break;
2886 case PT_MAC:
2887 (void) strlcpy(nwiftab->zone_nwif_mac,
2888 pp->pv_simple,
2889 sizeof (nwiftab->zone_nwif_mac));
2890 break;
2891 case PT_VLANID:
2892 (void) strlcpy(nwiftab->zone_nwif_vlan_id,
2893 pp->pv_simple,
2894 sizeof (nwiftab->zone_nwif_vlan_id));
2895 break;
2896 case PT_GNIC:
2897 (void) strlcpy(nwiftab->zone_nwif_gnic,
2898 pp->pv_simple,
2899 sizeof (nwiftab->zone_nwif_gnic));
2900 break;
2901 case PT_DEFROUTER:
2902 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2903 pp->pv_simple,
2904 sizeof (nwiftab->zone_nwif_defrouter));
2905 break;
2906 default:
2907 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2908 Z_NO_PROPERTY_TYPE, B_TRUE);
2909 return (Z_INSUFFICIENT_SPEC);
2910 }
2911 }
2912 if (fill_in_only)
2913 return (Z_OK);
2914 err = zonecfg_lookup_nwif(handle, nwiftab);
2915 return (err);
2916 }
2917
2918 static int
2919 fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
2920 {
3398 uint64_t tmp;
3399
3400 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3401 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
3402 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3403 saw_error = B_TRUE;
3404 return;
3405 }
3406
3407 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
3408 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3409 else
3410 need_to_commit = B_TRUE;
3411 }
3412
3413 static void
3414 remove_mcap()
3415 {
3416 int err, res1, res2, res3;
3417 uint64_t tmp;
3418 boolean_t revert = B_FALSE;
3419
3420 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp);
3421 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3422 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3423
3424 /* if none of these exist, there is no resource to remove */
3425 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3426 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
3427 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3428 saw_error = B_TRUE;
3429 return;
3430 }
3431 if (res1 == Z_OK) {
3432 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM))
3433 != Z_OK) {
3434 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3435 revert = B_TRUE;
3436 } else {
3437 need_to_commit = B_TRUE;
3438 }
3439 }
3440
3441 if (res2 == Z_OK) {
3442 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3443 != Z_OK) {
3444 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3445 revert = B_TRUE;
3446 } else {
3447 need_to_commit = B_TRUE;
3448 }
3449 }
3450 if (res3 == Z_OK) {
3451 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3452 != Z_OK) {
3453 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3454 revert = B_TRUE;
3455 } else {
3456 need_to_commit = B_TRUE;
3457 }
3458 }
3459
3460 if (revert)
3563 remove_mcap();
3564 return;
3565 case RT_ADMIN:
3566 remove_admin(cmd);
3567 return;
3568 default:
3569 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3570 long_usage(CMD_REMOVE, B_TRUE);
3571 usage(B_FALSE, HELP_RESOURCES);
3572 return;
3573 }
3574 }
3575
3576 static void
3577 remove_property(cmd_t *cmd)
3578 {
3579 char *prop_id;
3580 int err, res_type, prop_type;
3581 property_value_ptr_t pp;
3582 struct zone_rctlvaltab *rctlvaltab;
3583 struct zone_res_attrtab *np;
3584 complex_property_ptr_t cx;
3585
3586 res_type = resource_scope;
3587 prop_type = cmd->cmd_prop_name[0];
3588 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3589 long_usage(CMD_REMOVE, B_TRUE);
3590 return;
3591 }
3592
3593 if (cmd->cmd_prop_nv_pairs != 1) {
3594 long_usage(CMD_ADD, B_TRUE);
3595 return;
3596 }
3597
3598 if (initialize(B_TRUE) != Z_OK)
3599 return;
3600
3601 switch (res_type) {
3602 case RT_FS:
3603 if (prop_type != PT_OPTIONS) {
3624 err = zonecfg_remove_fs_option(&in_progress_fstab,
3625 prop_id);
3626 if (err != Z_OK)
3627 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3628 } else {
3629 list_property_ptr_t list;
3630
3631 for (list = pp->pv_list; list != NULL;
3632 list = list->lp_next) {
3633 prop_id = list->lp_simple;
3634 if (prop_id == NULL)
3635 break;
3636 err = zonecfg_remove_fs_option(
3637 &in_progress_fstab, prop_id);
3638 if (err != Z_OK)
3639 zone_perror(pt_to_str(prop_type), err,
3640 B_TRUE);
3641 }
3642 }
3643 return;
3644 case RT_NET: /* FALLTHRU */
3645 case RT_DEVICE:
3646 if (prop_type != PT_NPROP) {
3647 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3648 B_TRUE);
3649 long_usage(CMD_REMOVE, B_TRUE);
3650 usage(B_FALSE, HELP_PROPS);
3651 return;
3652 }
3653 pp = cmd->cmd_property_ptr[0];
3654 if (pp->pv_type != PROP_VAL_COMPLEX) {
3655 zerr(gettext("A %s value was expected here."),
3656 pvt_to_str(PROP_VAL_COMPLEX));
3657 saw_error = B_TRUE;
3658 return;
3659 }
3660
3661 np = alloca(sizeof (struct zone_res_attrtab));
3662 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
3663 switch (cx->cp_type) {
3664 case PT_NAME:
3665 (void) strlcpy(np->zone_res_attr_name,
3666 cx->cp_value,
3667 sizeof (np->zone_res_attr_name));
3668 break;
3669 case PT_VALUE:
3670 (void) strlcpy(np->zone_res_attr_value,
3671 cx->cp_value,
3672 sizeof (np->zone_res_attr_value));
3673 break;
3674 default:
3675 zone_perror(pt_to_str(prop_type),
3676 Z_NO_PROPERTY_TYPE, B_TRUE);
3677 long_usage(CMD_REMOVE, B_TRUE);
3678 usage(B_FALSE, HELP_PROPS);
3679 return;
3680 }
3681 }
3682 np->zone_res_attr_next = NULL;
3683
3684 if (res_type == RT_NET) {
3685 err = zonecfg_remove_res_attr(
3686 &(in_progress_nwiftab.zone_nwif_attrp), np);
3687 } else { /* RT_DEVICE */
3688 err = zonecfg_remove_res_attr(
3689 &(in_progress_devtab.zone_dev_attrp), np);
3690 }
3691 if (err != Z_OK)
3692 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3693 return;
3694 case RT_RCTL:
3695 if (prop_type != PT_VALUE) {
3696 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3697 B_TRUE);
3698 long_usage(CMD_REMOVE, B_TRUE);
3699 usage(B_FALSE, HELP_PROPS);
3700 return;
3701 }
3702 pp = cmd->cmd_property_ptr[0];
3703 if (pp->pv_type != PROP_VAL_COMPLEX) {
3704 zerr(gettext("A %s value was expected here."),
3705 pvt_to_str(PROP_VAL_COMPLEX));
3706 saw_error = B_TRUE;
3707 return;
3708 }
3709 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3710 zone_perror(zone, Z_NOMEM, B_TRUE);
3711 exit(Z_ERR);
3712 }
3713 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
3726 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3727 cx->cp_value,
3728 sizeof (rctlvaltab->zone_rctlval_action));
3729 break;
3730 default:
3731 zone_perror(pt_to_str(prop_type),
3732 Z_NO_PROPERTY_TYPE, B_TRUE);
3733 long_usage(CMD_ADD, B_TRUE);
3734 usage(B_FALSE, HELP_PROPS);
3735 zonecfg_free_rctl_value_list(rctlvaltab);
3736 return;
3737 }
3738 }
3739 rctlvaltab->zone_rctlval_next = NULL;
3740 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3741 rctlvaltab);
3742 if (err != Z_OK)
3743 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3744 zonecfg_free_rctl_value_list(rctlvaltab);
3745 return;
3746 default:
3747 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3748 long_usage(CMD_REMOVE, B_TRUE);
3749 usage(B_FALSE, HELP_RESOURCES);
3750 return;
3751 }
3752 }
3753
3754 void
3755 remove_func(cmd_t *cmd)
3756 {
3757 if (zone_is_read_only(CMD_REMOVE))
3758 return;
3759
3760 assert(cmd != NULL);
3761
3762 if (global_scope) {
3763 if (gz_invalid_resource(cmd->cmd_res_type)) {
3764 zerr(gettext("%s is not a valid resource for the "
3765 "global zone."), rt_to_str(cmd->cmd_res_type));
3788 return;
3789
3790 switch (res_type) {
3791 case RT_FS:
3792 if (prop_type == PT_RAW) {
3793 in_progress_fstab.zone_fs_raw[0] = '\0';
3794 need_to_commit = B_TRUE;
3795 return;
3796 }
3797 break;
3798 case RT_DCPU:
3799 if (prop_type == PT_IMPORTANCE) {
3800 in_progress_psettab.zone_importance[0] = '\0';
3801 need_to_commit = B_TRUE;
3802 return;
3803 }
3804 break;
3805 case RT_MCAP:
3806 switch (prop_type) {
3807 case PT_PHYSICAL:
3808 remove_aliased_rctl(PT_PHYSICAL, ALIAS_MAXPHYSMEM);
3809 return;
3810 case PT_SWAP:
3811 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3812 return;
3813 case PT_LOCKED:
3814 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3815 return;
3816 }
3817 break;
3818 case RT_NET:
3819 switch (prop_type) {
3820 case PT_ALLOWED_ADDRESS:
3821 in_progress_nwiftab.zone_nwif_allowed_address[0] = '\0';
3822 need_to_commit = B_TRUE;
3823 return;
3824 case PT_DEFROUTER:
3825 in_progress_nwiftab.zone_nwif_defrouter[0] = '\0';
3826 need_to_commit = B_TRUE;
3827 return;
3828 case PT_GNIC:
3829 in_progress_nwiftab.zone_nwif_gnic[0] = '\0';
3830 need_to_commit = B_TRUE;
3831 return;
3832 case PT_MAC:
3833 in_progress_nwiftab.zone_nwif_mac[0] = '\0';
3834 need_to_commit = B_TRUE;
3835 return;
3836 case PT_VLANID:
3837 in_progress_nwiftab.zone_nwif_vlan_id[0] = '\0';
3838 need_to_commit = B_TRUE;
3839 return;
3840 }
3841 break;
3842 default:
3843 break;
3844 }
3845
3846 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3847 }
3848
3849 static void
3850 clear_global(cmd_t *cmd)
3851 {
3852 int err, type;
3853
3854 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3855 long_usage(CMD_CLEAR, B_TRUE);
3856 return;
3857 }
3858
3859 if (initialize(B_TRUE) != Z_OK)
3860 return;
3861
3954
3955 assert(cmd != NULL);
3956
3957 if (global_scope) {
3958 if (gz_invalid_property(cmd->cmd_res_type)) {
3959 zerr(gettext("%s is not a valid property for the "
3960 "global zone."), pt_to_str(cmd->cmd_res_type));
3961 saw_error = B_TRUE;
3962 return;
3963 }
3964
3965 clear_global(cmd);
3966 } else {
3967 clear_property(cmd);
3968 }
3969 }
3970
3971 void
3972 select_func(cmd_t *cmd)
3973 {
3974 int type, err;
3975 uint64_t limit;
3976 uint64_t tmp;
3977
3978 if (zone_is_read_only(CMD_SELECT))
3979 return;
3980
3981 assert(cmd != NULL);
3982
3983 if (global_scope) {
3984 global_scope = B_FALSE;
3985 resource_scope = cmd->cmd_res_type;
3986 end_op = CMD_SELECT;
3987 } else {
3988 scope_usage(CMD_SELECT);
3989 return;
3990 }
3991
3992 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3993 long_usage(CMD_SELECT, B_TRUE);
3994 return;
4049 bcopy(&old_dstab, &in_progress_dstab,
4050 sizeof (struct zone_dstab));
4051 return;
4052 case RT_DCPU:
4053 if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
4054 z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
4055 global_scope = B_TRUE;
4056 }
4057 bcopy(&old_psettab, &in_progress_psettab,
4058 sizeof (struct zone_psettab));
4059 return;
4060 case RT_PCAP:
4061 if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
4062 != Z_OK) {
4063 z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
4064 global_scope = B_TRUE;
4065 }
4066 return;
4067 case RT_MCAP:
4068 /* if none of these exist, there is no resource to select */
4069 if (zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &limit)
4070 != Z_OK &&
4071 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
4072 != Z_OK &&
4073 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
4074 != Z_OK) {
4075 z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
4076 B_TRUE);
4077 global_scope = B_TRUE;
4078 }
4079 return;
4080 case RT_ADMIN:
4081 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
4082 != Z_OK) {
4083 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
4084 B_TRUE);
4085 global_scope = B_TRUE;
4086 }
4087 bcopy(&old_admintab, &in_progress_admintab,
4088 sizeof (struct zone_admintab));
4089 return;
4090 default:
4091 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
4092 long_usage(CMD_SELECT, B_TRUE);
4093 usage(B_FALSE, HELP_RESOURCES);
4094 return;
4095 }
4096 }
4097
4098 /*
4325 if (prop_type == PT_ADDRESS) {
4326 (void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
4327 sizeof (in_progress_nwiftab.zone_nwif_address));
4328 } else {
4329 assert(prop_type == PT_ALLOWED_ADDRESS);
4330 (void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
4331 prop_id,
4332 sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
4333 }
4334 }
4335
4336 void
4337 set_func(cmd_t *cmd)
4338 {
4339 char *prop_id;
4340 int arg, err, res_type, prop_type;
4341 property_value_ptr_t pp;
4342 boolean_t autoboot;
4343 zone_iptype_t iptype;
4344 boolean_t force_set = B_FALSE;
4345 uint64_t mem_cap, mem_limit;
4346 double cap;
4347 char *unitp;
4348 struct zone_psettab tmp_psettab;
4349 boolean_t arg_err = B_FALSE;
4350
4351 if (zone_is_read_only(CMD_SET))
4352 return;
4353
4354 assert(cmd != NULL);
4355
4356 optind = opterr = 0;
4357 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
4358 switch (arg) {
4359 case 'F':
4360 force_set = B_TRUE;
4361 break;
4362 default:
4363 if (optopt == '?')
4364 longer_usage(CMD_SET);
4365 else
4366 short_usage(CMD_SET);
4428
4429 if (force_set) {
4430 if (res_type != RT_ZONEPATH) {
4431 zerr(gettext("Only zonepath setting can be forced."));
4432 saw_error = B_TRUE;
4433 return;
4434 }
4435 if (!zonecfg_in_alt_root()) {
4436 zerr(gettext("Zonepath is changeable only in an "
4437 "alternate root."));
4438 saw_error = B_TRUE;
4439 return;
4440 }
4441 }
4442
4443 pp = cmd->cmd_property_ptr[0];
4444 /*
4445 * A nasty expression but not that complicated:
4446 * 1. fs options are simple or list (tested below)
4447 * 2. rctl value's are complex or list (tested below)
4448 * 3. net attr's are complex (tested below)
4449 * Anything else should be simple.
4450 */
4451 if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
4452 !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
4453 !(res_type == RT_NET && prop_type == PT_NPROP) &&
4454 (pp->pv_type != PROP_VAL_SIMPLE ||
4455 (prop_id = pp->pv_simple) == NULL)) {
4456 zerr(gettext("A %s value was expected here."),
4457 pvt_to_str(PROP_VAL_SIMPLE));
4458 saw_error = B_TRUE;
4459 return;
4460 }
4461 if (prop_type == PT_UNKNOWN) {
4462 long_usage(CMD_SET, B_TRUE);
4463 return;
4464 }
4465
4466 /*
4467 * Special case: the user can change the zone name prior to 'create';
4468 * if the zone already exists, we fall through letting initialize()
4469 * and the rest of the logic run.
4470 */
4471 if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4472 !state_atleast(ZONE_STATE_CONFIGURED)) {
4473 if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
4693 case RT_NET:
4694 switch (prop_type) {
4695 case PT_ADDRESS:
4696 case PT_ALLOWED_ADDRESS:
4697 if (validate_net_address_syntax(prop_id, B_FALSE)
4698 != Z_OK) {
4699 saw_error = B_TRUE;
4700 return;
4701 }
4702 set_in_progress_nwiftab_address(prop_id, prop_type);
4703 break;
4704 case PT_PHYSICAL:
4705 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4706 saw_error = B_TRUE;
4707 return;
4708 }
4709 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4710 prop_id,
4711 sizeof (in_progress_nwiftab.zone_nwif_physical));
4712 break;
4713 case PT_MAC:
4714 (void) strlcpy(in_progress_nwiftab.zone_nwif_mac,
4715 prop_id,
4716 sizeof (in_progress_nwiftab.zone_nwif_mac));
4717 break;
4718 case PT_VLANID:
4719 (void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id,
4720 prop_id,
4721 sizeof (in_progress_nwiftab.zone_nwif_vlan_id));
4722 break;
4723 case PT_GNIC:
4724 (void) strlcpy(in_progress_nwiftab.zone_nwif_gnic,
4725 prop_id,
4726 sizeof (in_progress_nwiftab.zone_nwif_gnic));
4727 break;
4728 case PT_DEFROUTER:
4729 if (validate_net_address_syntax(prop_id, B_TRUE)
4730 != Z_OK) {
4731 saw_error = B_TRUE;
4732 return;
4733 }
4734 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
4735 prop_id,
4736 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
4737 break;
4738 case PT_NPROP:
4739 if (pp->pv_type != PROP_VAL_COMPLEX) {
4740 zerr(gettext("A %s value was expected here."),
4741 pvt_to_str(PROP_VAL_COMPLEX));
4742 saw_error = B_TRUE;
4743 return;
4744 }
4745 zonecfg_free_res_attr_list(
4746 in_progress_nwiftab.zone_nwif_attrp);
4747 in_progress_nwiftab.zone_nwif_attrp = NULL;
4748 if (!(pp->pv_type == PROP_VAL_LIST &&
4749 pp->pv_list == NULL))
4750 add_property(cmd);
4751 break;
4752 default:
4753 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4754 B_TRUE);
4755 long_usage(CMD_SET, B_TRUE);
4756 usage(B_FALSE, HELP_PROPS);
4757 return;
4758 }
4759 return;
4760 case RT_DEVICE:
4761 switch (prop_type) {
4762 case PT_MATCH:
4763 (void) strlcpy(in_progress_devtab.zone_dev_match,
4764 prop_id,
4765 sizeof (in_progress_devtab.zone_dev_match));
4766 break;
4767 case PT_NPROP:
4768 if (pp->pv_type != PROP_VAL_COMPLEX) {
4769 zerr(gettext("A %s value was expected here."),
4770 pvt_to_str(PROP_VAL_COMPLEX));
4771 saw_error = B_TRUE;
4772 return;
4773 }
4774 zonecfg_free_res_attr_list(
4775 in_progress_devtab.zone_dev_attrp);
4776 in_progress_devtab.zone_dev_attrp = NULL;
4777 if (!(pp->pv_type == PROP_VAL_LIST &&
4778 pp->pv_list == NULL))
4779 add_property(cmd);
4780 break;
4781 default:
4782 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4783 B_TRUE);
4784 long_usage(CMD_SET, B_TRUE);
4785 usage(B_FALSE, HELP_PROPS);
4786 return;
4787 }
4788 return;
4789 case RT_RCTL:
4790 switch (prop_type) {
4791 case PT_NAME:
4792 if (!zonecfg_valid_rctlname(prop_id)) {
4793 zerr(gettext("'%s' is not a valid zone %s "
4794 "name."), prop_id, rt_to_str(RT_RCTL));
4795 return;
4796 }
4797 (void) strlcpy(in_progress_rctltab.zone_rctl_name,
4798 prop_id,
4799 sizeof (in_progress_rctltab.zone_rctl_name));
4800 break;
4904 break;
4905 }
4906 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4907 long_usage(CMD_SET, B_TRUE);
4908 usage(B_FALSE, HELP_PROPS);
4909 return;
4910 case RT_PCAP:
4911 if (prop_type != PT_NCPUS) {
4912 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4913 B_TRUE);
4914 long_usage(CMD_SET, B_TRUE);
4915 usage(B_FALSE, HELP_PROPS);
4916 return;
4917 }
4918
4919 /*
4920 * We already checked that an rctl alias is allowed in
4921 * the add_resource() function.
4922 */
4923
4924 if ((cap = strtod(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
4925 (cap * 100.0) < 1) {
4926 zerr(gettext("%s property is out of range."),
4927 pt_to_str(PT_NCPUS));
4928 saw_error = B_TRUE;
4929 return;
4930 }
4931 cap *= 100.0;
4932
4933 /* To avoid rounding issues add .5 to force correct value. */
4934 if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
4935 (uint_t)(cap + 0.5))) != Z_OK) {
4936 zone_perror(zone, err, B_TRUE);
4937 } else {
4938 need_to_commit = B_TRUE;
4939 }
4940 return;
4941 case RT_MCAP:
4942 switch (prop_type) {
4943 case PT_PHYSICAL:
4944 /*
4945 * We have to check if an rctl is allowed here since
4946 * there might already be a rctl defined that blocks
4947 * the alias.
4948 */
4949 if (!zonecfg_aliased_rctl_ok(handle,
4950 ALIAS_MAXPHYSMEM)) {
4951 zone_perror(pt_to_str(PT_LOCKED),
4952 Z_ALIAS_DISALLOW, B_FALSE);
4953 saw_error = B_TRUE;
4954 return;
4955 }
4956
4957 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4958 zerr(gettext("A non-negative number with a "
4959 "required scale suffix (K, M, G or T) was "
4960 "expected\nhere."));
4961 saw_error = B_TRUE;
4962 } else {
4963 if ((err = zonecfg_set_aliased_rctl(handle,
4964 ALIAS_MAXPHYSMEM, mem_cap)) != Z_OK)
4965 zone_perror(zone, err, B_TRUE);
4966 else
4967 need_to_commit = B_TRUE;
4968 }
4969 break;
4970 case PT_SWAP:
4971 /*
4972 * We have to check if an rctl is allowed here since
4973 * there might already be a rctl defined that blocks
4974 * the alias.
4975 */
4976 if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
4977 zone_perror(pt_to_str(PT_MAXSWAP),
4978 Z_ALIAS_DISALLOW, B_FALSE);
4979 saw_error = B_TRUE;
4980 return;
4981 }
4982
4983 if (global_zone)
4984 mem_limit = ONE_MB * 100;
4985 else
4986 mem_limit = ONE_MB * 50;
4987
5300 strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
5301 goto loopend; /* no match */
5302 output_fs(fp, &lookup);
5303 output = B_TRUE;
5304 loopend:
5305 zonecfg_free_fs_option_list(lookup.zone_fs_options);
5306 }
5307 (void) zonecfg_endfsent(handle);
5308 /*
5309 * If a property n/v pair was specified, warn the user if there was
5310 * nothing to output.
5311 */
5312 if (!output && cmd->cmd_prop_nv_pairs > 0)
5313 (void) printf(gettext("No such %s resource.\n"),
5314 rt_to_str(RT_FS));
5315 }
5316
5317 static void
5318 output_net(FILE *fp, struct zone_nwiftab *nwiftab)
5319 {
5320 struct zone_res_attrtab *np;
5321
5322 (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
5323 output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
5324 output_prop(fp, PT_ALLOWED_ADDRESS,
5325 nwiftab->zone_nwif_allowed_address, B_TRUE);
5326 output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
5327 output_prop(fp, PT_GNIC, nwiftab->zone_nwif_gnic, B_TRUE);
5328 output_prop(fp, PT_MAC, nwiftab->zone_nwif_mac, B_TRUE);
5329 output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
5330 output_prop(fp, PT_VLANID, nwiftab->zone_nwif_vlan_id, B_TRUE);
5331
5332 for (np = nwiftab->zone_nwif_attrp; np != NULL;
5333 np = np->zone_res_attr_next) {
5334 fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n",
5335 pt_to_str(PT_NPROP),
5336 pt_to_str(PT_NAME), np->zone_res_attr_name,
5337 pt_to_str(PT_VALUE), np->zone_res_attr_value);
5338 }
5339 }
5340
5341 static void
5342 info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5343 {
5344 struct zone_nwiftab lookup, user;
5345 boolean_t output = B_FALSE;
5346
5347 if (zonecfg_setnwifent(handle) != Z_OK)
5348 return;
5349 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
5350 if (cmd->cmd_prop_nv_pairs == 0) {
5351 output_net(fp, &lookup);
5352 continue;
5353 }
5354 if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
5355 continue;
5356 if (strlen(user.zone_nwif_physical) > 0 &&
5357 strcmp(user.zone_nwif_physical,
5358 lookup.zone_nwif_physical) != 0)
5361 if (strlen(user.zone_nwif_address) > 0 &&
5362 !zonecfg_same_net_address(user.zone_nwif_address,
5363 lookup.zone_nwif_address))
5364 continue; /* no match */
5365 output_net(fp, &lookup);
5366 output = B_TRUE;
5367 }
5368 (void) zonecfg_endnwifent(handle);
5369 /*
5370 * If a property n/v pair was specified, warn the user if there was
5371 * nothing to output.
5372 */
5373 if (!output && cmd->cmd_prop_nv_pairs > 0)
5374 (void) printf(gettext("No such %s resource.\n"),
5375 rt_to_str(RT_NET));
5376 }
5377
5378 static void
5379 output_dev(FILE *fp, struct zone_devtab *devtab)
5380 {
5381 struct zone_res_attrtab *np;
5382
5383 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
5384 output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
5385
5386 for (np = devtab->zone_dev_attrp; np != NULL;
5387 np = np->zone_res_attr_next) {
5388 fprintf(fp, "\t%s: (%s=%s,%s=\"%s\")\n",
5389 pt_to_str(PT_NPROP),
5390 pt_to_str(PT_NAME), np->zone_res_attr_name,
5391 pt_to_str(PT_VALUE), np->zone_res_attr_value);
5392 }
5393 }
5394
5395 static void
5396 info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5397 {
5398 struct zone_devtab lookup, user;
5399 boolean_t output = B_FALSE;
5400
5401 if (zonecfg_setdevent(handle) != Z_OK)
5402 return;
5403 while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
5404 if (cmd->cmd_prop_nv_pairs == 0) {
5405 output_dev(fp, &lookup);
5406 continue;
5407 }
5408 if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
5409 continue;
5410 if (strlen(user.zone_dev_match) > 0 &&
5411 strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
5412 continue; /* no match */
5631 if (num < 1024) {
5632 (void) snprintf(buf, bufsize, "%llu", num);
5633 return;
5634 }
5635
5636 while ((num >= 1024) && (*up != 'T')) {
5637 up++; /* next unit of measurement */
5638 save = num;
5639 num = (num + 512) >> 10;
5640 }
5641
5642 /* check if we should output a fraction. snprintf will round for us */
5643 if (save % 1024 != 0 && ((save >> 10) < 10))
5644 (void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
5645 *up);
5646 else
5647 (void) snprintf(buf, bufsize, "%llu%c", num, *up);
5648 }
5649
5650 static void
5651 output_mcap(FILE *fp, int showphys, uint64_t maxphys, int showswap,
5652 uint64_t maxswap, int showlocked, uint64_t maxlocked)
5653 {
5654 char buf[128];
5655
5656 (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
5657
5658 if (showphys == Z_OK) {
5659 (void) snprintf(buf, sizeof (buf), "%llu", maxphys);
5660 bytes_to_units(buf, buf, sizeof (buf));
5661 /* Print directly since "physical" also is a net property. */
5662 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(PT_PHYSICAL), buf);
5663 }
5664
5665 if (showswap == Z_OK) {
5666 (void) snprintf(buf, sizeof (buf), "%llu", maxswap);
5667 bytes_to_units(buf, buf, sizeof (buf));
5668 output_prop(fp, PT_SWAP, buf, B_TRUE);
5669 }
5670
5671 if (showlocked == Z_OK) {
5672 (void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
5673 bytes_to_units(buf, buf, sizeof (buf));
5674 output_prop(fp, PT_LOCKED, buf, B_TRUE);
5675 }
5676 }
5677
5678 static void
5679 info_mcap(zone_dochandle_t handle, FILE *fp)
5680 {
5681 int res1, res2, res3;
5682 uint64_t swap_limit;
5683 uint64_t locked_limit;
5684 uint64_t phys_limit;
5685
5686 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &phys_limit);
5687 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5688 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5689 &locked_limit);
5690
5691 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5692 output_mcap(fp, res1, phys_limit, res2, swap_limit,
5693 res3, locked_limit);
5694 }
5695
5696 static void
5697 output_auth(FILE *fp, struct zone_admintab *admintab)
5698 {
5699 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5700 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5701 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5702 }
5703
5704 static void
5705 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5706 {
5707 struct zone_admintab lookup, user;
5708 boolean_t output = B_FALSE;
5709 int err;
5710
5711 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5712 zone_perror(zone, err, B_TRUE);
5713 return;
5724 continue; /* no match */
5725 output_auth(fp, &lookup);
5726 output = B_TRUE;
5727 }
5728 (void) zonecfg_endadminent(handle);
5729 /*
5730 * If a property n/v pair was specified, warn the user if there was
5731 * nothing to output.
5732 */
5733 if (!output && cmd->cmd_prop_nv_pairs > 0)
5734 (void) printf(gettext("No such %s resource.\n"),
5735 rt_to_str(RT_ADMIN));
5736 }
5737
5738 void
5739 info_func(cmd_t *cmd)
5740 {
5741 FILE *fp = stdout;
5742 boolean_t need_to_close = B_FALSE;
5743 int type;
5744 int res1, res2, res3;
5745 uint64_t swap_limit;
5746 uint64_t locked_limit;
5747 uint64_t phys_limit;
5748
5749 assert(cmd != NULL);
5750
5751 if (initialize(B_TRUE) != Z_OK)
5752 return;
5753
5754 /* don't page error output */
5755 if (interactive_mode) {
5756 if ((fp = pager_open()) != NULL)
5757 need_to_close = B_TRUE;
5758 else
5759 fp = stdout;
5760
5761 setbuf(fp, NULL);
5762 }
5763
5764 if (!global_scope) {
5765 switch (resource_scope) {
5766 case RT_FS:
5767 output_fs(fp, &in_progress_fstab);
5775 case RT_RCTL:
5776 output_rctl(fp, &in_progress_rctltab);
5777 break;
5778 case RT_ATTR:
5779 output_attr(fp, &in_progress_attrtab);
5780 break;
5781 case RT_DATASET:
5782 output_ds(fp, &in_progress_dstab);
5783 break;
5784 case RT_DCPU:
5785 output_pset(fp, &in_progress_psettab);
5786 break;
5787 case RT_PCAP:
5788 output_pcap(fp);
5789 break;
5790 case RT_MCAP:
5791 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5792 &swap_limit);
5793 res2 = zonecfg_get_aliased_rctl(handle,
5794 ALIAS_MAXLOCKEDMEM, &locked_limit);
5795 res3 = zonecfg_get_aliased_rctl(handle,
5796 ALIAS_MAXPHYSMEM, &phys_limit);
5797 output_mcap(fp, res3, phys_limit, res1, swap_limit,
5798 res2, locked_limit);
5799 break;
5800 case RT_ADMIN:
5801 output_auth(fp, &in_progress_admintab);
5802 break;
5803 }
5804 goto cleanup;
5805 }
5806
5807 type = cmd->cmd_res_type;
5808
5809 if (gz_invalid_rt_property(type)) {
5810 zerr(gettext("%s is not a valid property for the global zone."),
5811 rt_to_str(type));
5812 goto cleanup;
5813 }
5814
5815 if (gz_invalid_resource(type)) {
5816 zerr(gettext("%s is not a valid resource for the global zone."),
5817 rt_to_str(type));
6399 pt_to_str(PT_USER),
6400 admintab.zone_admin_user);
6401 ret_val = Z_BAD_PROPERTY;
6402 }
6403 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6404 admintab.zone_admin_auths, zone))) {
6405 ret_val = Z_BAD_PROPERTY;
6406 }
6407 }
6408 (void) zonecfg_endadminent(handle);
6409
6410 if (!global_scope) {
6411 zerr(gettext("resource specification incomplete"));
6412 saw_error = B_TRUE;
6413 if (ret_val == Z_OK)
6414 ret_val = Z_INSUFFICIENT_SPEC;
6415 }
6416
6417 if (save) {
6418 if (ret_val == Z_OK) {
6419 /*
6420 * If the zone doesn't yet have a debug ID, set one now.
6421 */
6422 if (zonecfg_get_did(handle) == -1)
6423 zonecfg_set_did(handle);
6424
6425 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6426 need_to_commit = B_FALSE;
6427 (void) strlcpy(revert_zone, zone,
6428 sizeof (revert_zone));
6429 }
6430 } else {
6431 zerr(gettext("Zone %s failed to verify"), zone);
6432 }
6433 }
6434 if (ret_val != Z_OK)
6435 zone_perror(zone, ret_val, B_TRUE);
6436 }
6437
6438 void
6439 cancel_func(cmd_t *cmd)
6440 {
6441 int arg;
6442 boolean_t arg_err = B_FALSE;
6443
6444 assert(cmd != NULL);
6579 pt_to_str(PT_ALLOWED_ADDRESS),
6580 nwif.zone_nwif_allowed_address);
6581 }
6582 }
6583
6584 void
6585 end_func(cmd_t *cmd)
6586 {
6587 boolean_t validation_failed = B_FALSE;
6588 boolean_t arg_err = B_FALSE;
6589 struct zone_fstab tmp_fstab;
6590 struct zone_nwiftab tmp_nwiftab;
6591 struct zone_devtab tmp_devtab;
6592 struct zone_rctltab tmp_rctltab;
6593 struct zone_attrtab tmp_attrtab;
6594 struct zone_dstab tmp_dstab;
6595 struct zone_admintab tmp_admintab;
6596 int err, arg, res1, res2, res3;
6597 uint64_t swap_limit;
6598 uint64_t locked_limit;
6599 uint64_t phys_limit;
6600 uint64_t proc_cap;
6601
6602 assert(cmd != NULL);
6603
6604 optind = 0;
6605 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6606 switch (arg) {
6607 case '?':
6608 longer_usage(CMD_END);
6609 arg_err = B_TRUE;
6610 break;
6611 default:
6612 short_usage(CMD_END);
6613 arg_err = B_TRUE;
6614 break;
6615 }
6616 }
6617 if (arg_err)
6618 return;
6619
6883
6884 if (end_op == CMD_ADD) {
6885 err = zonecfg_add_pset(handle, &in_progress_psettab);
6886 } else {
6887 err = zonecfg_modify_pset(handle, &in_progress_psettab);
6888 }
6889 break;
6890 case RT_PCAP:
6891 /* Make sure everything was filled in. */
6892 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
6893 != Z_OK) {
6894 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
6895 saw_error = B_TRUE;
6896 validation_failed = B_TRUE;
6897 return;
6898 }
6899 err = Z_OK;
6900 break;
6901 case RT_MCAP:
6902 /* Make sure everything was filled in. */
6903 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM,
6904 &phys_limit);
6905 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
6906 &swap_limit);
6907 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
6908 &locked_limit);
6909
6910 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
6911 zerr(gettext("No property was specified. One of %s, "
6912 "%s or %s is required."), pt_to_str(PT_PHYSICAL),
6913 pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
6914 saw_error = B_TRUE;
6915 return;
6916 }
6917
6918 /* if phys & locked are both set, verify locked <= phys */
6919 if (res1 == Z_OK && res3 == Z_OK) {
6920 if (phys_limit < locked_limit) {
6921 zerr(gettext("The %s cap must be less than or "
6922 "equal to the %s cap."),
6923 pt_to_str(PT_LOCKED),
6924 pt_to_str(PT_PHYSICAL));
6925 saw_error = B_TRUE;
6926 return;
6927 }
6928 }
6929
6930 err = Z_OK;
6931 break;
6932 case RT_ADMIN:
6933 /* First make sure everything was filled in. */
6934 if (end_check_reqd(in_progress_admintab.zone_admin_user,
6935 PT_USER, &validation_failed) == Z_OK) {
6936 if (getpwnam(in_progress_admintab.zone_admin_user)
6937 == NULL) {
6938 zerr(gettext("%s %s is not a valid username"),
6939 pt_to_str(PT_USER),
6940 in_progress_admintab.zone_admin_user);
6941 validation_failed = B_TRUE;
6942 }
6943 }
6944
6945 if (end_check_reqd(in_progress_admintab.zone_admin_auths,
6946 PT_AUTHS, &validation_failed) == Z_OK) {
6947 if (!zonecfg_valid_auths(
6948 in_progress_admintab.zone_admin_auths,
6949 zone)) {
6950 validation_failed = B_TRUE;
|