Print this page
OS-200 need a better mechanism for storing persistent zone_did
OS-511 make zonecfg device resource extensible, like the net resource
OS-224 add more zonecfg net properties
OS-216 store all net config info on zone
Reduce lint
OS-5139 cpu_cap is sometimes off by 1 when set with package fss or cap_cap direct update
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
OS-399 zone phys. mem. cap should be a rctl and have associated kstat


   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;