63 #include <stdlib.h>
  64 #include <assert.h>
  65 #include <sys/stat.h>
  66 #include <zone.h>
  67 #include <arpa/inet.h>
  68 #include <netdb.h>
  69 #include <locale.h>
  70 #include <libintl.h>
  71 #include <alloca.h>
  72 #include <signal.h>
  73 #include <wait.h>
  74 #include <libtecla.h>
  75 #include <libzfs.h>
  76 #include <sys/brand.h>
  77 #include <libbrand.h>
  78 #include <sys/systeminfo.h>
  79 #include <libdladm.h>
  80 #include <libinetutil.h>
  81 #include <pwd.h>
  82 #include <inet/ip.h>
  83 #include <uuid/uuid.h>
  84 
  85 #include <libzonecfg.h>
  86 #include "zonecfg.h"
  87 
  88 #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
  89 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
  90 #endif
  91 
  92 #define PAGER   "/usr/bin/more"
  93 #define EXEC_PREFIX     "exec "
  94 #define EXEC_LEN        (strlen(EXEC_PREFIX))
  95 
  96 struct help {
  97         uint_t  cmd_num;
  98         char    *cmd_name;
  99         uint_t  flags;
 100         char    *short_usage;
 101 };
 102 
 103 extern int yyparse(void);
 
 111 
 112 /*
 113  * Each SHELP_ should be a simple string.
 114  */
 115 
 116 #define SHELP_ADD       "add <resource-type>\n\t(global scope)\n" \
 117         "add <property-name> <property-value>\n\t(resource scope)"
 118 #define SHELP_CANCEL    "cancel"
 119 #define SHELP_CLEAR     "clear <property-name>"
 120 #define SHELP_COMMIT    "commit"
 121 #define SHELP_CREATE    "create [-F] [ -a <path> | -b | -t <template> ]"
 122 #define SHELP_DELETE    "delete [-F]"
 123 #define SHELP_END       "end"
 124 #define SHELP_EXIT      "exit [-F]"
 125 #define SHELP_EXPORT    "export [-f output-file]"
 126 #define SHELP_HELP      "help [commands] [syntax] [usage] [<command-name>]"
 127 #define SHELP_INFO      "info [<resource-type> [property-name=property-value]*]"
 128 #define SHELP_REMOVE    "remove [-F] <resource-type> " \
 129         "[ <property-name>=<property-value> ]*\n" \
 130         "\t(global scope)\n" \
 131         "remove [-F] <property-name> <property-value>\n" \
 132         "\t(resource scope)"
 133 #define SHELP_REVERT    "revert [-F]"
 134 #define SHELP_SELECT    "select <resource-type> { <property-name>=" \
 135         "<property-value> }"
 136 #define SHELP_SET       "set <property-name>=<property-value>"
 137 #define SHELP_VERIFY    "verify"
 138 
 139 static struct help helptab[] = {
 140         { CMD_ADD,      "add",          HELP_RES_PROPS, SHELP_ADD, },
 141         { CMD_CANCEL,   "cancel",       0,              SHELP_CANCEL, },
 142         { CMD_CLEAR,    "clear",        HELP_PROPS,     SHELP_CLEAR, },
 143         { CMD_COMMIT,   "commit",       0,              SHELP_COMMIT, },
 144         { CMD_CREATE,   "create",       0,              SHELP_CREATE, },
 145         { CMD_DELETE,   "delete",       0,              SHELP_DELETE, },
 146         { CMD_END,      "end",          0,              SHELP_END, },
 147         { CMD_EXIT,     "exit",         0,              SHELP_EXIT, },
 148         { CMD_EXPORT,   "export",       0,              SHELP_EXPORT, },
 149         { CMD_HELP,     "help",         0,              SHELP_HELP },
 150         { CMD_INFO,     "info",         HELP_RES_PROPS, SHELP_INFO, },
 151         { CMD_REMOVE,   "remove",       HELP_RES_PROPS, SHELP_REMOVE, },
 
 172         "attr",
 173         "dataset",
 174         "limitpriv",
 175         "bootargs",
 176         "brand",
 177         "dedicated-cpu",
 178         "capped-memory",
 179         ALIAS_MAXLWPS,
 180         ALIAS_MAXSHMMEM,
 181         ALIAS_MAXSHMIDS,
 182         ALIAS_MAXMSGIDS,
 183         ALIAS_MAXSEMIDS,
 184         ALIAS_SHARES,
 185         "scheduling-class",
 186         "ip-type",
 187         "capped-cpu",
 188         "hostid",
 189         "admin",
 190         "fs-allowed",
 191         ALIAS_MAXPROCS,
 192         ALIAS_ZFSPRI,
 193         "uuid",
 194         NULL
 195 };
 196 
 197 /* These *must* match the order of the PT_ define's from zonecfg.h */
 198 char *prop_types[] = {
 199         "unknown",
 200         "zonename",
 201         "zonepath",
 202         "autoboot",
 203         "pool",
 204         "dir",
 205         "special",
 206         "type",
 207         "options",
 208         "address",
 209         "physical",
 210         "name",
 211         "value",
 212         "match",
 213         "priv",
 
 226         ALIAS_MAXSHMMEM,
 227         ALIAS_MAXSHMIDS,
 228         ALIAS_MAXMSGIDS,
 229         ALIAS_MAXSEMIDS,
 230         ALIAS_MAXLOCKEDMEM,
 231         ALIAS_MAXSWAP,
 232         "scheduling-class",
 233         "ip-type",
 234         "defrouter",
 235         "hostid",
 236         "user",
 237         "auths",
 238         "fs-allowed",
 239         ALIAS_MAXPROCS,
 240         "allowed-address",
 241         ALIAS_ZFSPRI,
 242         "mac-addr",
 243         "vlan-id",
 244         "global-nic",
 245         "property",
 246         "uuid",
 247         NULL
 248 };
 249 
 250 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
 251 static char *prop_val_types[] = {
 252         "simple",
 253         "complex",
 254         "list",
 255 };
 256 
 257 /*
 258  * The various _cmds[] lists below are for command tab-completion.
 259  */
 260 
 261 /*
 262  * remove has a space afterwards because it has qualifiers; the other commands
 263  * that have qualifiers (add, select, etc.) don't need a space here because
 264  * they have their own _cmds[] lists below.
 265  */
 266 static const char *global_scope_cmds[] = {
 
 292         "add capped-cpu",
 293         "add capped-memory",
 294         "add admin",
 295         NULL
 296 };
 297 
 298 static const char *clear_cmds[] = {
 299         "clear autoboot",
 300         "clear pool",
 301         "clear limitpriv",
 302         "clear bootargs",
 303         "clear scheduling-class",
 304         "clear ip-type",
 305         "clear " ALIAS_MAXLWPS,
 306         "clear " ALIAS_MAXSHMMEM,
 307         "clear " ALIAS_MAXSHMIDS,
 308         "clear " ALIAS_MAXMSGIDS,
 309         "clear " ALIAS_MAXSEMIDS,
 310         "clear " ALIAS_SHARES,
 311         "clear " ALIAS_MAXPROCS,
 312         "clear " ALIAS_ZFSPRI,
 313         NULL
 314 };
 315 
 316 static const char *remove_cmds[] = {
 317         "remove fs ",
 318         "remove net ",
 319         "remove device ",
 320         "remove rctl ",
 321         "remove attr ",
 322         "remove dataset ",
 323         "remove dedicated-cpu ",
 324         "remove capped-cpu ",
 325         "remove capped-memory ",
 326         "remove admin ",
 327         NULL
 328 };
 329 
 330 static const char *select_cmds[] = {
 331         "select fs ",
 332         "select net ",
 
 343 
 344 static const char *set_cmds[] = {
 345         "set zonename=",
 346         "set zonepath=",
 347         "set brand=",
 348         "set autoboot=",
 349         "set pool=",
 350         "set limitpriv=",
 351         "set bootargs=",
 352         "set scheduling-class=",
 353         "set ip-type=",
 354         "set " ALIAS_MAXLWPS "=",
 355         "set " ALIAS_MAXSHMMEM "=",
 356         "set " ALIAS_MAXSHMIDS "=",
 357         "set " ALIAS_MAXMSGIDS "=",
 358         "set " ALIAS_MAXSEMIDS "=",
 359         "set " ALIAS_SHARES "=",
 360         "set hostid=",
 361         "set fs-allowed=",
 362         "set " ALIAS_MAXPROCS "=",
 363         "set " ALIAS_ZFSPRI "=",
 364         "set uuid=",
 365         NULL
 366 };
 367 
 368 static const char *info_cmds[] = {
 369         "info fs ",
 370         "info net ",
 371         "info device ",
 372         "info rctl ",
 373         "info attr ",
 374         "info dataset ",
 375         "info capped-memory",
 376         "info dedicated-cpu",
 377         "info capped-cpu",
 378         "info zonename",
 379         "info zonepath",
 380         "info autoboot",
 381         "info pool",
 382         "info limitpriv",
 383         "info bootargs",
 384         "info brand",
 385         "info scheduling-class",
 386         "info ip-type",
 387         "info max-lwps",
 388         "info max-shm-memory",
 389         "info max-shm-ids",
 390         "info max-msg-ids",
 391         "info max-sem-ids",
 392         "info cpu-shares",
 393         "info hostid",
 394         "info admin",
 395         "info fs-allowed",
 396         "info max-processes",
 397         "info uuid",
 398         NULL
 399 };
 400 
 401 static const char *fs_res_scope_cmds[] = {
 402         "add options ",
 403         "cancel",
 404         "end",
 405         "exit",
 406         "help",
 407         "info",
 408         "remove options ",
 409         "set dir=",
 410         "set raw=",
 411         "set special=",
 412         "set type=",
 413         "clear raw",
 414         NULL
 415 };
 416 
 417 static const char *net_res_scope_cmds[] = {
 
 534         struct xif      *xif_next;
 535         char            xif_name[LIFNAMSIZ];
 536         boolean_t       xif_has_address;
 537         boolean_t       xif_has_defrouter;
 538 };
 539 
 540 /* Global variables */
 541 
 542 /* list of network interfaces specified for exclusive IP zone */
 543 struct xif *xif;
 544 
 545 /* set early in main(), never modified thereafter, used all over the place */
 546 static char *execname;
 547 
 548 /* set in main(), used all over the place */
 549 static zone_dochandle_t handle;
 550 
 551 /* used all over the place */
 552 static char zone[ZONENAME_MAX];
 553 static char revert_zone[ZONENAME_MAX];
 554 static char new_uuid[UUID_PRINTABLE_STRING_LENGTH];
 555 
 556 /* global brand operations */
 557 static brand_handle_t brand;
 558 
 559 /* set in modifying functions, checked in read_input() */
 560 static boolean_t need_to_commit = B_FALSE;
 561 static boolean_t is_create = B_FALSE;
 562 boolean_t saw_error;
 563 
 564 /* set in yacc parser, checked in read_input() */
 565 boolean_t newline_terminated;
 566 
 567 /* set in main(), checked in lex error handler */
 568 boolean_t cmd_file_mode;
 569 
 570 /* set in exit_func(), checked in read_input() */
 571 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
 572 
 573 /* used in short_usage() and zerr() */
 574 static char *cmd_file_name = NULL;
 575 
 576 /* checked in read_input() and other places */
 577 static boolean_t ok_to_prompt = B_FALSE;
 578 
 579 /* set and checked in initialize() */
 580 static boolean_t got_handle = B_FALSE;
 581 
 
 
 983         if ((pathstr = getenv("PATH")) == NULL) {
 984                 if (geteuid() == 0 || getuid() == 0)
 985                         pathstr = "/usr/sbin:/usr/bin";
 986                 else
 987                         pathstr = "/usr/bin:";
 988         }
 989         cp = strchr(name, '/') ? (const char *) "" : pathstr;
 990 
 991         do {
 992                 cp = exec_cat(cp, name, fname);
 993                 if (stat(fname, &stat_buf) != -1) {
 994                         /* successful find of the file */
 995                         return (0);
 996                 }
 997         } while (cp != NULL);
 998 
 999         return (-1);
1000 }
1001 
1002 static FILE *
1003 pager_open(void)
1004 {
1005         FILE *newfp;
1006         char *pager, *space;
1007 
1008         pager = getenv("PAGER");
1009         if (pager == NULL || *pager == '\0')
1010                 pager = PAGER;
1011 
1012         space = strchr(pager, ' ');
1013         if (space)
1014                 *space = '\0';
1015         if (path_find(pager) == 0) {
1016                 if (space)
1017                         *space = ' ';
1018                 if ((newfp = popen(pager, "w")) == NULL)
1019                         zerr(gettext("PAGER open failed (%s)."),
1020                             strerror(errno));
1021                 return (newfp);
1022         } else {
1023                 zerr(gettext("PAGER %s does not exist (%s)."),
1024                     pager, strerror(errno));
1025         }
1026         return (NULL);
1027 }
1028 
1029 static void
1030 pager_close(FILE *fp)
1031 {
1032         int status;
1033 
1034         status = pclose(fp);
1035         if (status == -1)
1036                 zerr(gettext("PAGER close failed (%s)."),
1037                     strerror(errno));
1038 }
1039 
1040 /*
1041  * Called with verbose TRUE when help is explicitly requested, FALSE for
1042  * unexpected errors.
1043  */
1044 
1045 void
1046 usage(boolean_t verbose, uint_t flags)
1047 {
1048         FILE *fp = verbose ? stdout : stderr;
1049         FILE *newfp;
1050         boolean_t need_to_close = B_FALSE;
1051         int i;
 
1266                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1267                             pt_to_str(PT_USER),
1268                             gettext("<single user or role name>"));
1269                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1270                             pt_to_str(PT_AUTHS),
1271                             gettext("<comma separated list>"));
1272                         break;
1273                 }
1274                 (void) fprintf(fp, gettext("And from any resource scope, you "
1275                     "can:\n"));
1276                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1277                     gettext("(to conclude this operation)"));
1278                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1279                     gettext("(to cancel this operation)"));
1280                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1281                     gettext("(to exit the zonecfg utility)"));
1282         }
1283         if (flags & HELP_USAGE) {
1284                 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1285                     execname, cmd_to_str(CMD_HELP));
1286                 (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>}\t\t\t(%s)\n",
1287                     execname, gettext("interactive"));
1288                 (void) fprintf(fp, "\t%s {-z <zone>|-u <uuid>} <command>\n",
1289                     execname);
1290                 (void) fprintf(fp,
1291                     "\t%s {-z <zone>|-u <uuid>} -f <command-file>\n",
1292                     execname);
1293         }
1294         if (flags & HELP_SUBCMDS) {
1295                 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1296                 for (i = 0; i <= CMD_MAX; i++) {
1297                         (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1298                         if (verbose)
1299                                 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1300                 }
1301         }
1302         if (flags & HELP_SYNTAX) {
1303                 if (!verbose)
1304                         (void) fprintf(fp, "\n");
1305                 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1306                 (void) fprintf(fp, gettext("\t(except the reserved words "
1307                     "'%s' and anything starting with '%s')\n"), "global",
1308                     "SUNW");
1309                 (void) fprintf(fp,
1310                     gettext("\tName must be less than %d characters.\n"),
1311                     ZONENAME_MAX);
1312                 if (verbose)
 
1360                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1361                     pt_to_str(PT_IPTYPE));
1362                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1363                     pt_to_str(PT_HOSTID));
1364                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1365                     pt_to_str(PT_FS_ALLOWED));
1366                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1367                     pt_to_str(PT_MAXLWPS));
1368                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1369                     pt_to_str(PT_MAXPROCS));
1370                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1371                     pt_to_str(PT_MAXSHMMEM));
1372                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1373                     pt_to_str(PT_MAXSHMIDS));
1374                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1375                     pt_to_str(PT_MAXMSGIDS));
1376                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1377                     pt_to_str(PT_MAXSEMIDS));
1378                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1379                     pt_to_str(PT_SHARES));
1380                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1381                     pt_to_str(PT_UUID));
1382                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1383                     pt_to_str(PT_ZFSPRI));
1384                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1385                     rt_to_str(RT_FS), pt_to_str(PT_DIR),
1386                     pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1387                     pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1388                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s, %s, %s %s\n",
1389                     rt_to_str(RT_NET),
1390                     pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1391                     pt_to_str(PT_GNIC), pt_to_str(PT_MAC),
1392                     pt_to_str(PT_PHYSICAL), pt_to_str(PT_NPROP),
1393                     pt_to_str(PT_VLANID), pt_to_str(PT_DEFROUTER));
1394                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_DEVICE),
1395                     pt_to_str(PT_MATCH), pt_to_str(PT_NPROP));
1396                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1397                     pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1398                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1399                     pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1400                     pt_to_str(PT_VALUE));
1401                 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1402                     pt_to_str(PT_NAME));
1403                 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
 
1700                     cmd_to_str(cmd_num));
1701                 saw_error = B_TRUE;
1702                 return (B_TRUE);
1703         }
1704         return (B_FALSE);
1705 }
1706 
1707 /*
1708  * Create a new configuration.
1709  */
1710 void
1711 create_func(cmd_t *cmd)
1712 {
1713         int err, arg;
1714         char zone_template[ZONENAME_MAX];
1715         char attach_path[MAXPATHLEN];
1716         zone_dochandle_t tmphandle;
1717         boolean_t force = B_FALSE;
1718         boolean_t attach = B_FALSE;
1719         boolean_t arg_err = B_FALSE;
1720         uuid_t uuid;
1721 
1722         assert(cmd != NULL);
1723 
1724         /* This is the default if no arguments are given. */
1725         (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1726 
1727         optind = 0;
1728         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:X"))
1729             != EOF) {
1730                 switch (arg) {
1731                 case '?':
1732                         if (optopt == '?')
1733                                 longer_usage(CMD_CREATE);
1734                         else
1735                                 short_usage(CMD_CREATE);
1736                         arg_err = B_TRUE;
1737                         break;
1738                 case 'a':
1739                         (void) strlcpy(attach_path, optarg,
1740                             sizeof (attach_path));
1741                         attach = B_TRUE;
1742                         break;
1743                 case 'b':
1744                         (void) strlcpy(zone_template, "SUNWblank",
1745                             sizeof (zone_template));
1746                         break;
1747                 case 'F':
1748                         force = B_TRUE;
 
1798                 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1799                     zone, B_FALSE, tmphandle);
1800         else
1801                 err = zonecfg_get_template_handle(zone_template, zone,
1802                     tmphandle);
1803 
1804         if (err != Z_OK) {
1805                 zonecfg_fini_handle(tmphandle);
1806                 if (attach && err == Z_NO_ZONE)
1807                         (void) fprintf(stderr, gettext("invalid path to "
1808                             "detached zone\n"));
1809                 else if (attach && err == Z_INVALID_DOCUMENT)
1810                         (void) fprintf(stderr, gettext("Cannot attach to an "
1811                             "earlier release of the operating system\n"));
1812                 else
1813                         zone_perror(zone_template, err, B_TRUE);
1814                 return;
1815         }
1816 
1817         need_to_commit = B_TRUE;
1818         is_create = B_TRUE;
1819         zonecfg_fini_handle(handle);
1820         handle = tmphandle;
1821         got_handle = B_TRUE;
1822 
1823         /* Allocate a new uuid for this new zone */
1824         uuid_generate(uuid);
1825         uuid_unparse(uuid, new_uuid);
1826 }
1827 
1828 /*
1829  * This malloc()'s memory, which must be freed by the caller.
1830  */
1831 static char *
1832 quoteit(char *instr)
1833 {
1834         char *outstr;
1835         size_t outstrsize = strlen(instr) + 3;  /* 2 quotes + '\0' */
1836 
1837         if ((outstr = malloc(outstrsize)) == NULL) {
1838                 zone_perror(zone, Z_NOMEM, B_FALSE);
1839                 exit(Z_ERR);
1840         }
1841         if (strchr(instr, ' ') == NULL) {
1842                 (void) strlcpy(outstr, instr, outstrsize);
1843                 return (outstr);
1844         }
1845         (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
 
1866         struct zone_fstab fstab;
1867         struct zone_devtab devtab;
1868         struct zone_attrtab attrtab;
1869         struct zone_rctltab rctltab;
1870         struct zone_dstab dstab;
1871         struct zone_psettab psettab;
1872         struct zone_rctlvaltab *valptr;
1873         struct zone_res_attrtab *rap;
1874         struct zone_admintab admintab;
1875         int err, arg;
1876         char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1877         char bootargs[BOOTARGS_MAX];
1878         char sched[MAXNAMELEN];
1879         char brand[MAXNAMELEN];
1880         char hostidp[HW_HOSTID_LEN];
1881         char fsallowedp[ZONE_FS_ALLOWED_MAX];
1882         char *limitpriv;
1883         FILE *of;
1884         boolean_t autoboot;
1885         zone_iptype_t iptype;
1886         uuid_t uuid;
1887         boolean_t need_to_close = B_FALSE;
1888         boolean_t arg_err = B_FALSE;
1889 
1890         assert(cmd != NULL);
1891 
1892         outfile[0] = '\0';
1893         optind = 0;
1894         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1895                 switch (arg) {
1896                 case '?':
1897                         if (optopt == '?')
1898                                 longer_usage(CMD_EXPORT);
1899                         else
1900                                 short_usage(CMD_EXPORT);
1901                         arg_err = B_TRUE;
1902                         break;
1903                 case 'f':
1904                         (void) strlcpy(outfile, optarg, sizeof (outfile));
1905                         break;
1906                 default:
 
1977                             pt_to_str(PT_IPTYPE), "shared");
1978                         break;
1979                 case ZS_EXCLUSIVE:
1980                         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1981                             pt_to_str(PT_IPTYPE), "exclusive");
1982                         break;
1983                 }
1984         }
1985 
1986         if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1987                 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1988                     pt_to_str(PT_HOSTID), hostidp);
1989         }
1990 
1991         if (zonecfg_get_fs_allowed(handle, fsallowedp,
1992             sizeof (fsallowedp)) == Z_OK) {
1993                 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1994                     pt_to_str(PT_FS_ALLOWED), fsallowedp);
1995         }
1996 
1997         if (zonecfg_get_uuid(zone, uuid) == Z_OK && !uuid_is_null(uuid)) {
1998                 char suuid[UUID_PRINTABLE_STRING_LENGTH];
1999 
2000                 uuid_unparse(uuid, suuid);
2001                 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2002                     pt_to_str(PT_UUID), suuid);
2003         }
2004 
2005         if ((err = zonecfg_setfsent(handle)) != Z_OK) {
2006                 zone_perror(zone, err, B_FALSE);
2007                 goto done;
2008         }
2009         while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2010                 zone_fsopt_t *optptr;
2011 
2012                 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2013                     rt_to_str(RT_FS));
2014                 export_prop(of, PT_DIR, fstab.zone_fs_dir);
2015                 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
2016                 export_prop(of, PT_RAW, fstab.zone_fs_raw);
2017                 export_prop(of, PT_TYPE, fstab.zone_fs_type);
2018                 for (optptr = fstab.zone_fs_options; optptr != NULL;
2019                     optptr = optptr->zone_fsopt_next) {
2020                         /*
2021                          * Simple property values with embedded equal signs
2022                          * need to be quoted to prevent the lexer from
2023                          * mis-parsing them as complex name=value pairs.
2024                          */
 
2452 do_res_attr(struct zone_res_attrtab **headp, complex_property_ptr_t cpp)
2453 {
2454         complex_property_ptr_t cp;
2455         struct zone_res_attrtab *np;
2456         int err;
2457         boolean_t seen_name = B_FALSE, seen_value = B_FALSE;
2458 
2459         if ((np = calloc(1, sizeof (struct zone_res_attrtab))) == NULL) {
2460                 zone_perror(zone, Z_NOMEM, B_TRUE);
2461                 exit(Z_ERR);
2462         }
2463 
2464         for (cp = cpp; cp != NULL; cp = cp->cp_next) {
2465                 switch (cp->cp_type) {
2466                 case PT_NAME:
2467                         if (seen_name) {
2468                                 zerr(gettext("%s already specified"),
2469                                     pt_to_str(PT_NAME));
2470                                 goto bad;
2471                         }
2472                         if (strlcpy(np->zone_res_attr_name, cp->cp_value,
2473                             sizeof (np->zone_res_attr_name)) >=
2474                             sizeof (np->zone_res_attr_name)) {
2475                                 zerr(gettext("Input for %s is too long"),
2476                                     pt_to_str(PT_NAME));
2477                                 goto bad;
2478                         }
2479                         seen_name = B_TRUE;
2480                         break;
2481                 case PT_VALUE:
2482                         if (seen_value) {
2483                                 zerr(gettext("%s already specified"),
2484                                     pt_to_str(PT_VALUE));
2485                                 goto bad;
2486                         }
2487                         if (strlcpy(np->zone_res_attr_value, cp->cp_value,
2488                             sizeof (np->zone_res_attr_value)) >=
2489                             sizeof (np->zone_res_attr_value)) {
2490                                 zerr(gettext("Input for %s is too long"),
2491                                     pt_to_str(PT_VALUE));
2492                                 goto bad;
2493                         }
2494 
2495                         seen_value = B_TRUE;
2496                         break;
2497                 default:
2498                         zone_perror(pt_to_str(PT_NPROP), Z_NO_PROPERTY_TYPE,
2499                             B_TRUE);
2500                         long_usage(CMD_ADD, B_TRUE);
2501                         usage(B_FALSE, HELP_PROPS);
2502                         zonecfg_free_res_attr_list(np);
2503                         return;
2504                 }
2505         }
2506 
2507         if (!seen_name)
2508                 zerr(gettext("%s not specified"), pt_to_str(PT_NAME));
2509         if (!seen_value)
2510                 zerr(gettext("%s not specified"), pt_to_str(PT_VALUE));
2511 
2512         err = zonecfg_add_res_attr(headp, np);
2513         if (err != Z_OK)
2514                 zone_perror(pt_to_str(PT_NPROP), err, B_TRUE);
 
2650         default:
2651                 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2652                 long_usage(CMD_ADD, B_TRUE);
2653                 usage(B_FALSE, HELP_RESOURCES);
2654                 return;
2655         }
2656 }
2657 
2658 static boolean_t
2659 gz_invalid_resource(int type)
2660 {
2661         return (global_zone && (type == RT_FS ||
2662             type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2663             type == RT_DATASET));
2664 }
2665 
2666 static boolean_t
2667 gz_invalid_rt_property(int type)
2668 {
2669         return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2670             type == RT_AUTOBOOT || type == RT_LIMITPRIV || type == RT_UUID ||
2671             type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2672             type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2673 }
2674 
2675 static boolean_t
2676 gz_invalid_property(int type)
2677 {
2678         return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2679             type == PT_AUTOBOOT || type == PT_LIMITPRIV || type == PT_UUID ||
2680             type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2681             type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2682 }
2683 
2684 void
2685 add_func(cmd_t *cmd)
2686 {
2687         int arg;
2688         boolean_t arg_err = B_FALSE;
2689 
2690         assert(cmd != NULL);
2691 
2692         optind = 0;
2693         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2694                 switch (arg) {
2695                 case '?':
2696                         longer_usage(CMD_ADD);
2697                         arg_err = B_TRUE;
2698                         break;
2699                 default:
 
2877                         break;
2878                 case PT_RAW:
2879                         (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2880                             sizeof (fstab->zone_fs_raw));
2881                         break;
2882                 case PT_TYPE:
2883                         (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2884                             sizeof (fstab->zone_fs_type));
2885                         break;
2886                 default:
2887                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2888                             Z_NO_PROPERTY_TYPE, B_TRUE);
2889                         return (Z_INSUFFICIENT_SPEC);
2890                 }
2891         }
2892         if (fill_in_only)
2893                 return (Z_OK);
2894         return (zonecfg_lookup_filesystem(handle, fstab));
2895 }
2896 
2897 /*
2898  * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c
2899  * We're expecting a dst of at least MAXMACADDRLEN size here.
2900  */
2901 static void
2902 normalize_mac_addr(char *dst, const char *src, int len)
2903 {
2904         char *p, *e, *sep = "";
2905         long n;
2906         char buf[MAXMACADDRLEN], tmp[4];
2907 
2908         *dst = '\0';
2909         (void) strlcpy(buf, src, sizeof (buf));
2910         p = strtok(buf, ":");
2911         while (p != NULL) {
2912                 n = strtol(p, &e, 16);
2913                 if (*e != NULL || n > 0xff)
2914                         return;
2915                 (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n);
2916                 (void) strlcat(dst, tmp, len);
2917 
2918                 sep = ":";
2919                 p = strtok(NULL, ":");
2920         }
2921 }
2922 
2923 static int
2924 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2925     boolean_t fill_in_only)
2926 {
2927         int err, i;
2928         property_value_ptr_t pp;
2929 
2930         if ((err = initialize(B_TRUE)) != Z_OK)
2931                 return (err);
2932 
2933         bzero(nwiftab, sizeof (*nwiftab));
2934         for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2935                 pp = cmd->cmd_property_ptr[i];
2936                 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2937                         zerr(gettext("A simple value was expected here."));
2938                         saw_error = B_TRUE;
2939                         return (Z_INSUFFICIENT_SPEC);
2940                 }
2941                 switch (cmd->cmd_prop_name[i]) {
2942                 case PT_ADDRESS:
2943                         (void) strlcpy(nwiftab->zone_nwif_address,
2944                             pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2945                         break;
2946                 case PT_ALLOWED_ADDRESS:
2947                         (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2948                             pp->pv_simple,
2949                             sizeof (nwiftab->zone_nwif_allowed_address));
2950                         break;
2951                 case PT_PHYSICAL:
2952                         (void) strlcpy(nwiftab->zone_nwif_physical,
2953                             pp->pv_simple,
2954                             sizeof (nwiftab->zone_nwif_physical));
2955                         break;
2956                 case PT_MAC:
2957                         normalize_mac_addr(nwiftab->zone_nwif_mac,
2958                             pp->pv_simple,
2959                             sizeof (nwiftab->zone_nwif_mac));
2960                         break;
2961                 case PT_VLANID:
2962                         (void) strlcpy(nwiftab->zone_nwif_vlan_id,
2963                             pp->pv_simple,
2964                             sizeof (nwiftab->zone_nwif_vlan_id));
2965                         break;
2966                 case PT_GNIC:
2967                         (void) strlcpy(nwiftab->zone_nwif_gnic,
2968                             pp->pv_simple,
2969                             sizeof (nwiftab->zone_nwif_gnic));
2970                         break;
2971                 case PT_DEFROUTER:
2972                         (void) strlcpy(nwiftab->zone_nwif_defrouter,
2973                             pp->pv_simple,
2974                             sizeof (nwiftab->zone_nwif_defrouter));
2975                         break;
2976                 default:
2977                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
 
3201         boolean_t arg_err = B_FALSE;
3202 
3203         optind = 0;
3204         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3205                 switch (arg) {
3206                 case 'F':
3207                         force = B_TRUE;
3208                         break;
3209                 default:
3210                         arg_err = B_TRUE;
3211                         break;
3212                 }
3213         }
3214         if (arg_err)
3215                 return (B_FALSE);
3216 
3217 
3218         num = zonecfg_num_resources(handle, rsrc);
3219 
3220         if (num == 0) {
3221                 if (force)
3222                         return (B_TRUE);
3223                 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
3224                     B_TRUE);
3225                 return (B_FALSE);
3226         }
3227         if (num > 1 && !force) {
3228                 if (!interactive_mode) {
3229                         zerr(gettext("There are multiple instances of this "
3230                             "resource.  Either qualify the resource to\n"
3231                             "remove a single instance or use the -F option to "
3232                             "remove all instances."));
3233                         saw_error = B_TRUE;
3234                         return (B_FALSE);
3235                 }
3236                 (void) snprintf(prompt, sizeof (prompt), gettext(
3237                     "Are you sure you want to remove ALL '%s' resources"),
3238                     rsrc);
3239                 answer = ask_yesno(B_FALSE, prompt);
3240                 if (answer == -1) {
3241                         zerr(gettext("Resource incomplete."));
3242                         return (B_FALSE);
3243                 }
3244                 if (answer != 1)
3245                         return (B_FALSE);
3246         }
3247         return (B_TRUE);
3248 }
3249 
3250 static void
3251 remove_fs(cmd_t *cmd, boolean_t force)
3252 {
3253         int err;
3254 
3255         /* traditional, qualified fs removal */
3256         if (cmd->cmd_prop_nv_pairs > 0) {
3257                 struct zone_fstab fstab;
3258 
3259                 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
3260                         if (!force)
3261                                 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3262                         return;
3263                 }
3264                 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK) {
3265                         if (!force)
3266                                 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3267                 } else {
3268                         need_to_commit = B_TRUE;
3269                 }
3270                 zonecfg_free_fs_option_list(fstab.zone_fs_options);
3271                 return;
3272         }
3273 
3274         /*
3275          * unqualified fs removal.  remove all fs's but prompt if more
3276          * than one.
3277          */
3278         if (!prompt_remove_resource(cmd, "fs"))
3279                 return;
3280 
3281         if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
3282                 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3283         else
3284                 need_to_commit = B_TRUE;
3285 }
3286 
3287 static void
3288 remove_net(cmd_t *cmd, boolean_t force)
3289 {
3290         int err;
3291 
3292         /* traditional, qualified net removal */
3293         if (cmd->cmd_prop_nv_pairs > 0) {
3294                 struct zone_nwiftab nwiftab;
3295 
3296                 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
3297                         if (!force)
3298                                 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err,
3299                                     B_TRUE);
3300                         return;
3301                 }
3302                 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK) {
3303                         if (!force)
3304                                 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err,
3305                                     B_TRUE);
3306                 } else {
3307                         need_to_commit = B_TRUE;
3308                 }
3309                 return;
3310         }
3311 
3312         /*
3313          * unqualified net removal.  remove all nets but prompt if more
3314          * than one.
3315          */
3316         if (!prompt_remove_resource(cmd, "net"))
3317                 return;
3318 
3319         if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
3320                 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3321         else
3322                 need_to_commit = B_TRUE;
3323 }
3324 
3325 static void
3326 remove_device(cmd_t *cmd, boolean_t force)
3327 {
3328         int err;
3329 
3330         /* traditional, qualified device removal */
3331         if (cmd->cmd_prop_nv_pairs > 0) {
3332                 struct zone_devtab devtab;
3333 
3334                 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3335                         if (!force)
3336                                 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err,
3337                                     B_TRUE);
3338                         return;
3339                 }
3340                 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK) {
3341                         if (!force)
3342                                 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err,
3343                                     B_TRUE);
3344                 } else {
3345                         need_to_commit = B_TRUE;
3346                 }
3347                 return;
3348         }
3349 
3350         /*
3351          * unqualified device removal.  remove all devices but prompt if more
3352          * than one.
3353          */
3354         if (!prompt_remove_resource(cmd, "device"))
3355                 return;
3356 
3357         if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3358                 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3359         else
3360                 need_to_commit = B_TRUE;
3361 }
3362 
3363 static void
3364 remove_attr(cmd_t *cmd, boolean_t force)
3365 {
3366         int err;
3367 
3368         /* traditional, qualified attr removal */
3369         if (cmd->cmd_prop_nv_pairs > 0) {
3370                 struct zone_attrtab attrtab;
3371 
3372                 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3373                         if (!force)
3374                                 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err,
3375                                     B_TRUE);
3376                         return;
3377                 }
3378                 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK) {
3379                         if (!force)
3380                                 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err,
3381                                     B_TRUE);
3382                 } else {
3383                         need_to_commit = B_TRUE;
3384                 }
3385                 return;
3386         }
3387 
3388         /*
3389          * unqualified attr removal.  remove all attrs but prompt if more
3390          * than one.
3391          */
3392         if (!prompt_remove_resource(cmd, "attr"))
3393                 return;
3394 
3395         if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3396                 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3397         else
3398                 need_to_commit = B_TRUE;
3399 }
3400 
3401 static void
3402 remove_dataset(cmd_t *cmd, boolean_t force)
3403 {
3404         int err;
3405 
3406         /* traditional, qualified dataset removal */
3407         if (cmd->cmd_prop_nv_pairs > 0) {
3408                 struct zone_dstab dstab;
3409 
3410                 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3411                         if (!force)
3412                                 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err,
3413                                     B_TRUE);
3414                         return;
3415                 }
3416                 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK) {
3417                         if (!force)
3418                                 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err,
3419                                     B_TRUE);
3420                 } else {
3421                         need_to_commit = B_TRUE;
3422                 }
3423                 return;
3424         }
3425 
3426         /*
3427          * unqualified dataset removal.  remove all datasets but prompt if more
3428          * than one.
3429          */
3430         if (!prompt_remove_resource(cmd, "dataset"))
3431                 return;
3432 
3433         if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3434                 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3435         else
3436                 need_to_commit = B_TRUE;
3437 }
3438 
3439 static void
3440 remove_rctl(cmd_t *cmd, boolean_t force)
3441 {
3442         int err;
3443 
3444         /* traditional, qualified rctl removal */
3445         if (cmd->cmd_prop_nv_pairs > 0) {
3446                 struct zone_rctltab rctltab;
3447 
3448                 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3449                         if (!force)
3450                                 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err,
3451                                     B_TRUE);
3452                         return;
3453                 }
3454                 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK) {
3455                         if (!force)
3456                                 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err,
3457                                     B_TRUE);
3458                 } else {
3459                         need_to_commit = B_TRUE;
3460                 }
3461                 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3462                 return;
3463         }
3464 
3465         /*
3466          * unqualified rctl removal.  remove all rctls but prompt if more
3467          * than one.
3468          */
3469         if (!prompt_remove_resource(cmd, "rctl"))
3470                 return;
3471 
3472         if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3473                 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3474         else
3475                 need_to_commit = B_TRUE;
3476 }
3477 
3478 static void
3479 remove_pset(boolean_t force)
3480 {
3481         int err;
3482         struct zone_psettab psettab;
3483 
3484         if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3485                 if (!force)
3486                         z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3487                 return;
3488         }
3489         if ((err = zonecfg_delete_pset(handle)) != Z_OK) {
3490                 if (!force)
3491                         z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3492         } else {
3493                 need_to_commit = B_TRUE;
3494         }
3495 }
3496 
3497 static void
3498 remove_pcap(boolean_t force)
3499 {
3500         int err;
3501         uint64_t tmp;
3502 
3503         if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3504                 if (!force) {
3505                         zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3506                             rt_to_str(RT_PCAP),
3507                             zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3508                         saw_error = B_TRUE;
3509                 }
3510                 return;
3511         }
3512 
3513         if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK) {
3514                 if (!force)
3515                         z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3516         } else {
3517                 need_to_commit = B_TRUE;
3518         }
3519 }
3520 
3521 static void
3522 remove_mcap(boolean_t force)
3523 {
3524         int err, res1, res2, res3;
3525         uint64_t tmp;
3526         boolean_t revert = B_FALSE;
3527 
3528         res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXPHYSMEM, &tmp);
3529         res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3530         res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3531 
3532         /* if none of these exist, there is no resource to remove */
3533         if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3534                 if (!force) {
3535                         zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3536                             rt_to_str(RT_MCAP),
3537                             zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3538                         saw_error = B_TRUE;
3539                 }
3540                 return;
3541         }
3542         if (res1 == Z_OK) {
3543                 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXPHYSMEM))
3544                     != Z_OK) {
3545                         if (!force) {
3546                                 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3547                                     B_TRUE);
3548                                 revert = B_TRUE;
3549                         }
3550                 } else {
3551                         need_to_commit = B_TRUE;
3552                 }
3553         }
3554 
3555         if (res2 == Z_OK) {
3556                 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3557                     != Z_OK) {
3558                         if (!force) {
3559                                 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3560                                     B_TRUE);
3561                                 revert = B_TRUE;
3562                         }
3563                 } else {
3564                         need_to_commit = B_TRUE;
3565                 }
3566         }
3567         if (res3 == Z_OK) {
3568                 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3569                     != Z_OK) {
3570                         if (!force) {
3571                                 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err,
3572                                     B_TRUE);
3573                                 revert = B_TRUE;
3574                         }
3575                 } else {
3576                         need_to_commit = B_TRUE;
3577                 }
3578         }
3579 
3580         if (revert)
3581                 need_to_commit = B_FALSE;
3582 }
3583 
3584 static void
3585 remove_admin(cmd_t *cmd, boolean_t force)
3586 {
3587         int err;
3588 
3589         /* traditional, qualified attr removal */
3590         if (cmd->cmd_prop_nv_pairs > 0) {
3591                 struct zone_admintab admintab;
3592 
3593                 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3594                         if (!force)
3595                                 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err,
3596                                     B_TRUE);
3597                         return;
3598                 }
3599                 if ((err = zonecfg_delete_admin(handle, &admintab,
3600                     zone)) != Z_OK) {
3601                         if (!force)
3602                                 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err,
3603                                     B_TRUE);
3604                 } else {
3605                         need_to_commit = B_TRUE;
3606                 }
3607                 return;
3608         }
3609 
3610         /*
3611          * unqualified admin removal.
3612          * remove all admins but prompt if more than one.
3613          */
3614         if (!prompt_remove_resource(cmd, "admin"))
3615                 return;
3616 
3617         if ((err = zonecfg_delete_admins(handle, zone)) != Z_OK)
3618                 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN, err, B_TRUE);
3619         else
3620                 need_to_commit = B_TRUE;
3621 }
3622 
3623 static void
3624 remove_resource(cmd_t *cmd)
3625 {
3626         int type;
3627         int arg;
3628         boolean_t arg_err = B_FALSE;
3629         boolean_t force = B_FALSE;
3630 
3631         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3632                 long_usage(CMD_REMOVE, B_TRUE);
3633                 return;
3634         }
3635 
3636         optind = 0;
3637         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3638                 switch (arg) {
3639                 case '?':
3640                         longer_usage(CMD_REMOVE);
3641                         arg_err = B_TRUE;
3642                         break;
3643                 case 'F':
3644                         force = B_TRUE;
3645                         break;
3646                 default:
3647                         short_usage(CMD_REMOVE);
3648                         arg_err = B_TRUE;
3649                         break;
3650                 }
3651         }
3652         if (arg_err)
3653                 return;
3654 
3655         if (initialize(B_TRUE) != Z_OK)
3656                 return;
3657 
3658         switch (type) {
3659         case RT_FS:
3660                 remove_fs(cmd, force);
3661                 return;
3662         case RT_NET:
3663                 remove_net(cmd, force);
3664                 return;
3665         case RT_DEVICE:
3666                 remove_device(cmd, force);
3667                 return;
3668         case RT_RCTL:
3669                 remove_rctl(cmd, force);
3670                 return;
3671         case RT_ATTR:
3672                 remove_attr(cmd, force);
3673                 return;
3674         case RT_DATASET:
3675                 remove_dataset(cmd, force);
3676                 return;
3677         case RT_DCPU:
3678                 remove_pset(force);
3679                 return;
3680         case RT_PCAP:
3681                 remove_pcap(force);
3682                 return;
3683         case RT_MCAP:
3684                 remove_mcap(force);
3685                 return;
3686         case RT_ADMIN:
3687                 remove_admin(cmd, force);
3688                 return;
3689         default:
3690                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3691                 long_usage(CMD_REMOVE, B_TRUE);
3692                 usage(B_FALSE, HELP_RESOURCES);
3693                 return;
3694         }
3695 }
3696 
3697 static void
3698 remove_property(cmd_t *cmd)
3699 {
3700         char *prop_id;
3701         int err, res_type, prop_type;
3702         property_value_ptr_t pp;
3703         struct zone_rctlvaltab *rctlvaltab;
3704         struct zone_res_attrtab *np;
3705         complex_property_ptr_t cx;
3706         int arg;
3707         boolean_t force = B_FALSE;
3708         boolean_t arg_err = B_FALSE;
3709 
3710         optind = 0;
3711         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3712                 switch (arg) {
3713                 case 'F':
3714                         force = B_TRUE;
3715                         break;
3716                 default:
3717                         arg_err = B_TRUE;
3718                         break;
3719                 }
3720         }
3721         if (arg_err) {
3722                 saw_error = B_TRUE;
3723                 return;
3724         }
3725 
3726         res_type = resource_scope;
3727         prop_type = cmd->cmd_prop_name[0];
3728         if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3729                 long_usage(CMD_REMOVE, B_TRUE);
3730                 return;
3731         }
3732 
3733         if (cmd->cmd_prop_nv_pairs != 1) {
3734                 long_usage(CMD_ADD, B_TRUE);
3735                 return;
3736         }
3737 
3738         if (initialize(B_TRUE) != Z_OK)
3739                 return;
3740 
3741         switch (res_type) {
3742         case RT_FS:
3743                 if (prop_type != PT_OPTIONS) {
3744                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3745                             B_TRUE);
3746                         long_usage(CMD_REMOVE, B_TRUE);
3747                         usage(B_FALSE, HELP_PROPS);
3748                         return;
3749                 }
3750                 pp = cmd->cmd_property_ptr[0];
3751                 if (pp->pv_type == PROP_VAL_COMPLEX) {
3752                         zerr(gettext("A %s or %s value was expected here."),
3753                             pvt_to_str(PROP_VAL_SIMPLE),
3754                             pvt_to_str(PROP_VAL_LIST));
3755                         saw_error = B_TRUE;
3756                         return;
3757                 }
3758                 if (pp->pv_type == PROP_VAL_SIMPLE) {
3759                         if (pp->pv_simple == NULL) {
3760                                 long_usage(CMD_ADD, B_TRUE);
3761                                 return;
3762                         }
3763                         prop_id = pp->pv_simple;
3764                         err = zonecfg_remove_fs_option(&in_progress_fstab,
3765                             prop_id);
3766                         if (err != Z_OK && !force)
3767                                 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3768                 } else {
3769                         list_property_ptr_t list;
3770 
3771                         for (list = pp->pv_list; list != NULL;
3772                             list = list->lp_next) {
3773                                 prop_id = list->lp_simple;
3774                                 if (prop_id == NULL)
3775                                         break;
3776                                 err = zonecfg_remove_fs_option(
3777                                     &in_progress_fstab, prop_id);
3778                                 if (err != Z_OK && !force)
3779                                         zone_perror(pt_to_str(prop_type), err,
3780                                             B_TRUE);
3781                         }
3782                 }
3783                 return;
3784         case RT_NET:            /* FALLTHRU */
3785         case RT_DEVICE:
3786                 if (prop_type != PT_NPROP) {
3787                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3788                             B_TRUE);
3789                         long_usage(CMD_REMOVE, B_TRUE);
3790                         usage(B_FALSE, HELP_PROPS);
3791                         return;
3792                 }
3793                 pp = cmd->cmd_property_ptr[0];
3794                 if (pp->pv_type != PROP_VAL_COMPLEX) {
3795                         zerr(gettext("A %s value was expected here."),
3796                             pvt_to_str(PROP_VAL_COMPLEX));
3797                         saw_error = B_TRUE;
3798                         return;
 
3811                                     cx->cp_value,
3812                                     sizeof (np->zone_res_attr_value));
3813                                 break;
3814                         default:
3815                                 zone_perror(pt_to_str(prop_type),
3816                                     Z_NO_PROPERTY_TYPE, B_TRUE);
3817                                 long_usage(CMD_REMOVE, B_TRUE);
3818                                 usage(B_FALSE, HELP_PROPS);
3819                                 return;
3820                         }
3821                 }
3822                 np->zone_res_attr_next = NULL;
3823 
3824                 if (res_type == RT_NET) {
3825                         err = zonecfg_remove_res_attr(
3826                             &(in_progress_nwiftab.zone_nwif_attrp), np);
3827                 } else {                                /* RT_DEVICE */
3828                         err = zonecfg_remove_res_attr(
3829                             &(in_progress_devtab.zone_dev_attrp), np);
3830                 }
3831                 if (err != Z_OK && !force)
3832                         zone_perror(pt_to_str(prop_type), err, B_TRUE);
3833                 return;
3834         case RT_RCTL:
3835                 if (prop_type != PT_VALUE) {
3836                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3837                             B_TRUE);
3838                         long_usage(CMD_REMOVE, B_TRUE);
3839                         usage(B_FALSE, HELP_PROPS);
3840                         return;
3841                 }
3842                 pp = cmd->cmd_property_ptr[0];
3843                 if (pp->pv_type != PROP_VAL_COMPLEX) {
3844                         zerr(gettext("A %s value was expected here."),
3845                             pvt_to_str(PROP_VAL_COMPLEX));
3846                         saw_error = B_TRUE;
3847                         return;
3848                 }
3849                 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3850                         zone_perror(zone, Z_NOMEM, B_TRUE);
3851                         exit(Z_ERR);
 
3862                                     cx->cp_value,
3863                                     sizeof (rctlvaltab->zone_rctlval_limit));
3864                                 break;
3865                         case PT_ACTION:
3866                                 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3867                                     cx->cp_value,
3868                                     sizeof (rctlvaltab->zone_rctlval_action));
3869                                 break;
3870                         default:
3871                                 zone_perror(pt_to_str(prop_type),
3872                                     Z_NO_PROPERTY_TYPE, B_TRUE);
3873                                 long_usage(CMD_ADD, B_TRUE);
3874                                 usage(B_FALSE, HELP_PROPS);
3875                                 zonecfg_free_rctl_value_list(rctlvaltab);
3876                                 return;
3877                         }
3878                 }
3879                 rctlvaltab->zone_rctlval_next = NULL;
3880                 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3881                     rctlvaltab);
3882                 if (err != Z_OK && !force)
3883                         zone_perror(pt_to_str(prop_type), err, B_TRUE);
3884                 zonecfg_free_rctl_value_list(rctlvaltab);
3885                 return;
3886         default:
3887                 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3888                 long_usage(CMD_REMOVE, B_TRUE);
3889                 usage(B_FALSE, HELP_RESOURCES);
3890                 return;
3891         }
3892 }
3893 
3894 void
3895 remove_func(cmd_t *cmd)
3896 {
3897         if (zone_is_read_only(CMD_REMOVE))
3898                 return;
3899 
3900         assert(cmd != NULL);
3901 
3902         if (global_scope) {
 
3987 }
3988 
3989 static void
3990 clear_global(cmd_t *cmd)
3991 {
3992         int err, type;
3993 
3994         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3995                 long_usage(CMD_CLEAR, B_TRUE);
3996                 return;
3997         }
3998 
3999         if (initialize(B_TRUE) != Z_OK)
4000                 return;
4001 
4002         switch (type) {
4003         case PT_ZONENAME:
4004                 /* FALLTHRU */
4005         case PT_ZONEPATH:
4006                 /* FALLTHRU */
4007         case PT_UUID:
4008                 /* FALLTHRU */
4009         case PT_BRAND:
4010                 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
4011                 return;
4012         case PT_AUTOBOOT:
4013                 /* false is default; we'll treat as equivalent to clearing */
4014                 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
4015                         z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
4016                 else
4017                         need_to_commit = B_TRUE;
4018                 return;
4019         case PT_POOL:
4020                 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
4021                         z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
4022                 else
4023                         need_to_commit = B_TRUE;
4024                 return;
4025         case PT_LIMITPRIV:
4026                 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
4027                         z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
4028                 else
 
4051                 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
4052                 return;
4053         case PT_MAXPROCS:
4054                 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
4055                 return;
4056         case PT_MAXSHMMEM:
4057                 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
4058                 return;
4059         case PT_MAXSHMIDS:
4060                 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
4061                 return;
4062         case PT_MAXMSGIDS:
4063                 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
4064                 return;
4065         case PT_MAXSEMIDS:
4066                 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
4067                 return;
4068         case PT_SHARES:
4069                 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
4070                 return;
4071         case PT_ZFSPRI:
4072                 remove_aliased_rctl(PT_ZFSPRI, ALIAS_ZFSPRI);
4073                 return;
4074         case PT_HOSTID:
4075                 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
4076                         z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
4077                 else
4078                         need_to_commit = B_TRUE;
4079                 return;
4080         case PT_FS_ALLOWED:
4081                 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
4082                         z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
4083                 else
4084                         need_to_commit = B_TRUE;
4085                 return;
4086         default:
4087                 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
4088                 long_usage(CMD_CLEAR, B_TRUE);
4089                 usage(B_FALSE, HELP_PROPS);
4090                 return;
4091         }
4092 }
4093 
 
 
4544                 } else if (prop_type == PT_IPTYPE) {
4545                         res_type = RT_IPTYPE;
4546                 } else if (prop_type == PT_MAXLWPS) {
4547                         res_type = RT_MAXLWPS;
4548                 } else if (prop_type == PT_MAXPROCS) {
4549                         res_type = RT_MAXPROCS;
4550                 } else if (prop_type == PT_MAXSHMMEM) {
4551                         res_type = RT_MAXSHMMEM;
4552                 } else if (prop_type == PT_MAXSHMIDS) {
4553                         res_type = RT_MAXSHMIDS;
4554                 } else if (prop_type == PT_MAXMSGIDS) {
4555                         res_type = RT_MAXMSGIDS;
4556                 } else if (prop_type == PT_MAXSEMIDS) {
4557                         res_type = RT_MAXSEMIDS;
4558                 } else if (prop_type == PT_SHARES) {
4559                         res_type = RT_SHARES;
4560                 } else if (prop_type == PT_HOSTID) {
4561                         res_type = RT_HOSTID;
4562                 } else if (prop_type == PT_FS_ALLOWED) {
4563                         res_type = RT_FS_ALLOWED;
4564                 } else if (prop_type == PT_ZFSPRI) {
4565                         res_type = RT_ZFSPRI;
4566                 } else if (prop_type == PT_UUID) {
4567                         res_type = RT_UUID;
4568                 } else {
4569                         zerr(gettext("Cannot set a resource-specific property "
4570                             "from the global scope."));
4571                         saw_error = B_TRUE;
4572                         return;
4573                 }
4574         } else {
4575                 res_type = resource_scope;
4576         }
4577 
4578         if (force_set) {
4579                 if (res_type != RT_ZONEPATH) {
4580                         zerr(gettext("Only zonepath setting can be forced."));
4581                         saw_error = B_TRUE;
4582                         return;
4583                 }
4584                 if (!zonecfg_in_alt_root()) {
4585                         zerr(gettext("Zonepath is changeable only in an "
4586                             "alternate root."));
4587                         saw_error = B_TRUE;
 
4755                 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4756                 return;
4757         case RT_MAXPROCS:
4758                 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4759                 return;
4760         case RT_MAXSHMMEM:
4761                 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4762                 return;
4763         case RT_MAXSHMIDS:
4764                 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4765                 return;
4766         case RT_MAXMSGIDS:
4767                 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4768                 return;
4769         case RT_MAXSEMIDS:
4770                 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4771                 return;
4772         case RT_SHARES:
4773                 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4774                 return;
4775         case RT_ZFSPRI:
4776                 set_aliased_rctl(ALIAS_ZFSPRI, prop_type, prop_id);
4777                 return;
4778         case RT_HOSTID:
4779                 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4780                         if (err == Z_TOO_BIG) {
4781                                 zerr(gettext("hostid string is too large: %s"),
4782                                     prop_id);
4783                                 saw_error = B_TRUE;
4784                         } else {
4785                                 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4786                         }
4787                         return;
4788                 }
4789                 need_to_commit = B_TRUE;
4790                 return;
4791         case RT_UUID:
4792                 /*
4793                  * We can't set here.  We have to wait until commit since the
4794                  * uuid will be updating the index file and we may not have
4795                  * created the zone yet.
4796                  */
4797                 (void) strlcpy(new_uuid, prop_id, sizeof (new_uuid));
4798                 need_to_commit = B_TRUE;
4799                 return;
4800         case RT_FS_ALLOWED:
4801                 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4802                         zone_perror(zone, err, B_TRUE);
4803                 else
4804                         need_to_commit = B_TRUE;
4805                 return;
4806         case RT_FS:
4807                 switch (prop_type) {
4808                 case PT_DIR:
4809                         (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4810                             sizeof (in_progress_fstab.zone_fs_dir));
4811                         return;
4812                 case PT_SPECIAL:
4813                         (void) strlcpy(in_progress_fstab.zone_fs_special,
4814                             prop_id,
4815                             sizeof (in_progress_fstab.zone_fs_special));
4816                         return;
4817                 case PT_RAW:
4818                         (void) strlcpy(in_progress_fstab.zone_fs_raw,
4819                             prop_id, sizeof (in_progress_fstab.zone_fs_raw));
 
4855                 switch (prop_type) {
4856                 case PT_ADDRESS:
4857                 case PT_ALLOWED_ADDRESS:
4858                         if (validate_net_address_syntax(prop_id, B_FALSE)
4859                             != Z_OK) {
4860                                 saw_error = B_TRUE;
4861                                 return;
4862                         }
4863                         set_in_progress_nwiftab_address(prop_id, prop_type);
4864                         break;
4865                 case PT_PHYSICAL:
4866                         if (validate_net_physical_syntax(prop_id) != Z_OK) {
4867                                 saw_error = B_TRUE;
4868                                 return;
4869                         }
4870                         (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4871                             prop_id,
4872                             sizeof (in_progress_nwiftab.zone_nwif_physical));
4873                         break;
4874                 case PT_MAC:
4875                         normalize_mac_addr(in_progress_nwiftab.zone_nwif_mac,
4876                             prop_id,
4877                             sizeof (in_progress_nwiftab.zone_nwif_mac));
4878                         break;
4879                 case PT_VLANID:
4880                         (void) strlcpy(in_progress_nwiftab.zone_nwif_vlan_id,
4881                             prop_id,
4882                             sizeof (in_progress_nwiftab.zone_nwif_vlan_id));
4883                         break;
4884                 case PT_GNIC:
4885                         (void) strlcpy(in_progress_nwiftab.zone_nwif_gnic,
4886                             prop_id,
4887                             sizeof (in_progress_nwiftab.zone_nwif_gnic));
4888                         break;
4889                 case PT_DEFROUTER:
4890                         if (validate_net_address_syntax(prop_id, B_TRUE)
4891                             != Z_OK) {
4892                                 saw_error = B_TRUE;
4893                                 return;
4894                         }
4895                         (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
 
5380         }
5381 }
5382 
5383 static void
5384 info_hostid(zone_dochandle_t handle, FILE *fp)
5385 {
5386         char hostidp[HW_HOSTID_LEN];
5387         int err;
5388 
5389         if ((err = zonecfg_get_hostid(handle, hostidp,
5390             sizeof (hostidp))) == Z_OK) {
5391                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
5392         } else if (err == Z_BAD_PROPERTY) {
5393                 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
5394         } else {
5395                 zone_perror(zone, err, B_TRUE);
5396         }
5397 }
5398 
5399 static void
5400 info_uuid(FILE *fp)
5401 {
5402         uuid_t uuid;
5403         char suuid[UUID_PRINTABLE_STRING_LENGTH];
5404 
5405         if (new_uuid[0] != '\0') {
5406                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), new_uuid);
5407         } else if (zonecfg_get_uuid(zone, uuid) == Z_OK &&
5408             !uuid_is_null(uuid)) {
5409                 uuid_unparse(uuid, suuid);
5410                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_UUID), suuid);
5411         } else {
5412                 (void) fprintf(fp, "%s:\n", pt_to_str(PT_UUID));
5413         }
5414 }
5415 
5416 static void
5417 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
5418 {
5419         char fsallowedp[ZONE_FS_ALLOWED_MAX];
5420         int err;
5421 
5422         if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
5423             sizeof (fsallowedp))) == Z_OK) {
5424                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
5425                     fsallowedp);
5426         } else if (err == Z_BAD_PROPERTY) {
5427                 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
5428         } else {
5429                 zone_perror(zone, err, B_TRUE);
5430         }
5431 }
5432 
5433 static void
5434 output_fs(FILE *fp, struct zone_fstab *fstab)
5435 {
5436         zone_fsopt_t *this;
 
5906         (void) zonecfg_endadminent(handle);
5907         /*
5908          * If a property n/v pair was specified, warn the user if there was
5909          * nothing to output.
5910          */
5911         if (!output && cmd->cmd_prop_nv_pairs > 0)
5912                 (void) printf(gettext("No such %s resource.\n"),
5913                     rt_to_str(RT_ADMIN));
5914 }
5915 
5916 void
5917 info_func(cmd_t *cmd)
5918 {
5919         FILE *fp = stdout;
5920         boolean_t need_to_close = B_FALSE;
5921         int type;
5922         int res1, res2, res3;
5923         uint64_t swap_limit;
5924         uint64_t locked_limit;
5925         uint64_t phys_limit;
5926         struct stat statbuf;
5927 
5928         assert(cmd != NULL);
5929 
5930         if (initialize(B_TRUE) != Z_OK)
5931                 return;
5932 
5933         /* don't page error output */
5934         if (interactive_mode) {
5935                 if ((fp = pager_open()) != NULL)
5936                         need_to_close = B_TRUE;
5937                 else
5938                         fp = stdout;
5939 
5940                 setbuf(fp, NULL);
5941         }
5942 
5943         if (!global_scope) {
5944                 switch (resource_scope) {
5945                 case RT_FS:
5946                         output_fs(fp, &in_progress_fstab);
 
5996                     rt_to_str(type));
5997                 goto cleanup;
5998         }
5999 
6000         switch (cmd->cmd_res_type) {
6001         case RT_UNKNOWN:
6002                 info_zonename(handle, fp);
6003                 if (!global_zone) {
6004                         info_zonepath(handle, fp);
6005                         info_brand(handle, fp);
6006                         info_autoboot(handle, fp);
6007                         info_bootargs(handle, fp);
6008                 }
6009                 info_pool(handle, fp);
6010                 if (!global_zone) {
6011                         info_limitpriv(handle, fp);
6012                         info_sched(handle, fp);
6013                         info_iptype(handle, fp);
6014                         info_hostid(handle, fp);
6015                         info_fs_allowed(handle, fp);
6016                         info_uuid(fp);
6017                 }
6018                 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
6019                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
6020                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
6021                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
6022                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
6023                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
6024                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
6025                 info_aliased_rctl(handle, fp, ALIAS_ZFSPRI);
6026                 if (!global_zone) {
6027                         info_fs(handle, fp, cmd);
6028                         info_net(handle, fp, cmd);
6029                         info_dev(handle, fp, cmd);
6030                 }
6031                 info_pset(handle, fp);
6032                 info_pcap(fp);
6033                 info_mcap(handle, fp);
6034                 if (!global_zone) {
6035                         info_attr(handle, fp, cmd);
6036                         info_ds(handle, fp, cmd);
6037                         info_auth(handle, fp, cmd);
6038                 }
6039                 info_rctl(handle, fp, cmd);
6040                 break;
6041         case RT_ZONENAME:
6042                 info_zonename(handle, fp);
6043                 break;
6044         case RT_ZONEPATH:
6045                 info_zonepath(handle, fp);
 
6069                 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
6070                 break;
6071         case RT_MAXPROCS:
6072                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
6073                 break;
6074         case RT_MAXSHMMEM:
6075                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
6076                 break;
6077         case RT_MAXSHMIDS:
6078                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
6079                 break;
6080         case RT_MAXMSGIDS:
6081                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
6082                 break;
6083         case RT_MAXSEMIDS:
6084                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
6085                 break;
6086         case RT_SHARES:
6087                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
6088                 break;
6089         case RT_ZFSPRI:
6090                 info_aliased_rctl(handle, fp, ALIAS_ZFSPRI);
6091                 break;
6092         case RT_FS:
6093                 info_fs(handle, fp, cmd);
6094                 break;
6095         case RT_NET:
6096                 info_net(handle, fp, cmd);
6097                 break;
6098         case RT_DEVICE:
6099                 info_dev(handle, fp, cmd);
6100                 break;
6101         case RT_RCTL:
6102                 info_rctl(handle, fp, cmd);
6103                 break;
6104         case RT_ATTR:
6105                 info_attr(handle, fp, cmd);
6106                 break;
6107         case RT_DATASET:
6108                 info_ds(handle, fp, cmd);
6109                 break;
6110         case RT_DCPU:
6111                 info_pset(handle, fp);
6112                 break;
6113         case RT_PCAP:
6114                 info_pcap(fp);
6115                 break;
6116         case RT_MCAP:
6117                 info_mcap(handle, fp);
6118                 break;
6119         case RT_HOSTID:
6120                 info_hostid(handle, fp);
6121                 break;
6122         case RT_UUID:
6123                 info_uuid(fp);
6124                 break;
6125         case RT_ADMIN:
6126                 info_auth(handle, fp, cmd);
6127                 break;
6128         case RT_FS_ALLOWED:
6129                 info_fs_allowed(handle, fp);
6130                 break;
6131         default:
6132                 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
6133                     B_TRUE);
6134         }
6135 
6136 cleanup:
6137         if (need_to_close)
6138                 (void) pager_close(fp);
6139 }
6140 
6141 /*
6142  * Helper function for verify-- checks that a required string property
6143  * exists.
6144  */
 
 
6596 
6597         if (!global_scope) {
6598                 zerr(gettext("resource specification incomplete"));
6599                 saw_error = B_TRUE;
6600                 if (ret_val == Z_OK)
6601                         ret_val = Z_INSUFFICIENT_SPEC;
6602         }
6603 
6604         if (save) {
6605                 if (ret_val == Z_OK) {
6606                         /*
6607                          * If the zone doesn't yet have a debug ID, set one now.
6608                          */
6609                         if (zonecfg_get_did(handle) == -1)
6610                                 zonecfg_set_did(handle);
6611 
6612                         if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6613                                 need_to_commit = B_FALSE;
6614                                 (void) strlcpy(revert_zone, zone,
6615                                     sizeof (revert_zone));
6616 
6617                                 if (is_create) {
6618                                         zonecfg_notify_create(handle);
6619                                         is_create = B_FALSE;
6620                                 }
6621                         }
6622 
6623                         /*
6624                          * Commit a new uuid at this point since we now know the
6625                          * zone index entry will exist.
6626                          */
6627                         if (new_uuid[0] != '\0') {
6628                                 if ((err = zonecfg_set_uuid(zone, zonepath,
6629                                     new_uuid)) != Z_OK)
6630                                         zone_perror(zone, err, B_FALSE);
6631                                 else
6632                                         new_uuid[0] = '\0';
6633                         }
6634                 } else {
6635                         zerr(gettext("Zone %s failed to verify"), zone);
6636                 }
6637         }
6638         if (ret_val != Z_OK)
6639                 zone_perror(zone, ret_val, B_TRUE);
6640 }
6641 
6642 void
6643 cancel_func(cmd_t *cmd)
6644 {
6645         int arg;
6646         boolean_t arg_err = B_FALSE;
6647 
6648         assert(cmd != NULL);
6649 
6650         optind = 0;
6651         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6652                 switch (arg) {
6653                 case '?':
 
7663         for (;;) {
7664                 last_slash = strrchr(execfullname, '/');
7665                 if (last_slash == NULL) {
7666                         execbasename = execfullname;
7667                         break;
7668                 } else {
7669                         execbasename = last_slash + 1;
7670                         if (*execbasename == '\0') {
7671                                 *last_slash = '\0';
7672                                 continue;
7673                         }
7674                         break;
7675                 }
7676         }
7677         return (execbasename);
7678 }
7679 
7680 int
7681 main(int argc, char *argv[])
7682 {
7683         int err, arg, uflag = 0, zflag = 0;
7684         struct stat st;
7685         uuid_t uuidin;
7686         char zonename[ZONENAME_MAX + 1];
7687 
7688         /* This must be before anything goes to stdout. */
7689         setbuf(stdout, NULL);
7690 
7691         saw_error = B_FALSE;
7692         cmd_file_mode = B_FALSE;
7693         execname = get_execbasename(argv[0]);
7694 
7695         (void) setlocale(LC_ALL, "");
7696         (void) textdomain(TEXT_DOMAIN);
7697 
7698         if (getzoneid() != GLOBAL_ZONEID) {
7699                 zerr(gettext("%s can only be run from the global zone."),
7700                     execname);
7701                 exit(Z_ERR);
7702         }
7703 
7704         if (argc < 2) {
7705                 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7706                 exit(Z_USAGE);
7707         }
7708         if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7709                 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7710                 exit(Z_OK);
7711         }
7712 
7713         while ((arg = getopt(argc, argv, "?f:R:z:u:")) != EOF) {
7714                 switch (arg) {
7715                 case '?':
7716                         if (optopt == '?')
7717                                 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7718                         else
7719                                 usage(B_FALSE, HELP_USAGE);
7720                         exit(Z_USAGE);
7721                         /* NOTREACHED */
7722                 case 'f':
7723                         cmd_file_name = optarg;
7724                         cmd_file_mode = B_TRUE;
7725                         break;
7726                 case 'R':
7727                         if (*optarg != '/') {
7728                                 zerr(gettext("root path must be absolute: %s"),
7729                                     optarg);
7730                                 exit(Z_USAGE);
7731                         }
7732                         if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7733                                 zerr(gettext(
7734                                     "root path must be a directory: %s"),
7735                                     optarg);
7736                                 exit(Z_USAGE);
7737                         }
7738                         zonecfg_set_root(optarg);
7739                         break;
7740                 case 'u':
7741                         if (uuid_parse((char *)optarg, uuidin) == -1)
7742                                 return (Z_INVALID_PROPERTY);
7743 
7744                         if (zonecfg_get_name_by_uuid(uuidin, zonename,
7745                             ZONENAME_MAX) != Z_OK) {
7746                                 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7747                                 usage(B_FALSE, HELP_SYNTAX);
7748                                 exit(Z_USAGE);
7749                         }
7750 
7751                         (void) strlcpy(zone, zonename, sizeof (zone));
7752                         (void) strlcpy(revert_zone, zonename, sizeof (zone));
7753                         uflag = 1;
7754                         break;
7755                 case 'z':
7756                         if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7757                                 global_zone = B_TRUE;
7758                         } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7759                                 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7760                                 usage(B_FALSE, HELP_SYNTAX);
7761                                 exit(Z_USAGE);
7762                         }
7763                         (void) strlcpy(zone, optarg, sizeof (zone));
7764                         (void) strlcpy(revert_zone, optarg, sizeof (zone));
7765                         zflag = 1;
7766                         break;
7767                 default:
7768                         usage(B_FALSE, HELP_USAGE);
7769                         exit(Z_USAGE);
7770                 }
7771         }
7772 
7773         if (optind > argc || strcmp(zone, "") == 0 || (uflag && zflag)) {
7774                 usage(B_FALSE, HELP_USAGE);
7775                 exit(Z_USAGE);
7776         }
7777 
7778         if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7779                 read_only_mode = B_FALSE;
7780         } else if (err == Z_ACCES) {
7781                 read_only_mode = B_TRUE;
7782                 /* skip this message in one-off from command line mode */
7783                 if (optind == argc)
7784                         (void) fprintf(stderr, gettext("WARNING: you do not "
7785                             "have write access to this zone's configuration "
7786                             "file;\ngoing into read-only mode.\n"));
7787         } else {
7788                 fprintf(stderr, "%s: Could not access zone configuration "
7789                     "store: %s\n", execname, zonecfg_strerror(err));
7790                 exit(Z_ERR);
7791         }
7792 
7793         if ((handle = zonecfg_init_handle()) == NULL) {
 
 | 
 
 
  63 #include <stdlib.h>
  64 #include <assert.h>
  65 #include <sys/stat.h>
  66 #include <zone.h>
  67 #include <arpa/inet.h>
  68 #include <netdb.h>
  69 #include <locale.h>
  70 #include <libintl.h>
  71 #include <alloca.h>
  72 #include <signal.h>
  73 #include <wait.h>
  74 #include <libtecla.h>
  75 #include <libzfs.h>
  76 #include <sys/brand.h>
  77 #include <libbrand.h>
  78 #include <sys/systeminfo.h>
  79 #include <libdladm.h>
  80 #include <libinetutil.h>
  81 #include <pwd.h>
  82 #include <inet/ip.h>
  83 
  84 #include <libzonecfg.h>
  85 #include "zonecfg.h"
  86 
  87 #if !defined(TEXT_DOMAIN)               /* should be defined by cc -D */
  88 #define TEXT_DOMAIN     "SYS_TEST"      /* Use this only if it wasn't */
  89 #endif
  90 
  91 #define PAGER   "/usr/bin/more"
  92 #define EXEC_PREFIX     "exec "
  93 #define EXEC_LEN        (strlen(EXEC_PREFIX))
  94 
  95 struct help {
  96         uint_t  cmd_num;
  97         char    *cmd_name;
  98         uint_t  flags;
  99         char    *short_usage;
 100 };
 101 
 102 extern int yyparse(void);
 
 110 
 111 /*
 112  * Each SHELP_ should be a simple string.
 113  */
 114 
 115 #define SHELP_ADD       "add <resource-type>\n\t(global scope)\n" \
 116         "add <property-name> <property-value>\n\t(resource scope)"
 117 #define SHELP_CANCEL    "cancel"
 118 #define SHELP_CLEAR     "clear <property-name>"
 119 #define SHELP_COMMIT    "commit"
 120 #define SHELP_CREATE    "create [-F] [ -a <path> | -b | -t <template> ]"
 121 #define SHELP_DELETE    "delete [-F]"
 122 #define SHELP_END       "end"
 123 #define SHELP_EXIT      "exit [-F]"
 124 #define SHELP_EXPORT    "export [-f output-file]"
 125 #define SHELP_HELP      "help [commands] [syntax] [usage] [<command-name>]"
 126 #define SHELP_INFO      "info [<resource-type> [property-name=property-value]*]"
 127 #define SHELP_REMOVE    "remove [-F] <resource-type> " \
 128         "[ <property-name>=<property-value> ]*\n" \
 129         "\t(global scope)\n" \
 130         "remove <property-name> <property-value>\n" \
 131         "\t(resource scope)"
 132 #define SHELP_REVERT    "revert [-F]"
 133 #define SHELP_SELECT    "select <resource-type> { <property-name>=" \
 134         "<property-value> }"
 135 #define SHELP_SET       "set <property-name>=<property-value>"
 136 #define SHELP_VERIFY    "verify"
 137 
 138 static struct help helptab[] = {
 139         { CMD_ADD,      "add",          HELP_RES_PROPS, SHELP_ADD, },
 140         { CMD_CANCEL,   "cancel",       0,              SHELP_CANCEL, },
 141         { CMD_CLEAR,    "clear",        HELP_PROPS,     SHELP_CLEAR, },
 142         { CMD_COMMIT,   "commit",       0,              SHELP_COMMIT, },
 143         { CMD_CREATE,   "create",       0,              SHELP_CREATE, },
 144         { CMD_DELETE,   "delete",       0,              SHELP_DELETE, },
 145         { CMD_END,      "end",          0,              SHELP_END, },
 146         { CMD_EXIT,     "exit",         0,              SHELP_EXIT, },
 147         { CMD_EXPORT,   "export",       0,              SHELP_EXPORT, },
 148         { CMD_HELP,     "help",         0,              SHELP_HELP },
 149         { CMD_INFO,     "info",         HELP_RES_PROPS, SHELP_INFO, },
 150         { CMD_REMOVE,   "remove",       HELP_RES_PROPS, SHELP_REMOVE, },
 
 171         "attr",
 172         "dataset",
 173         "limitpriv",
 174         "bootargs",
 175         "brand",
 176         "dedicated-cpu",
 177         "capped-memory",
 178         ALIAS_MAXLWPS,
 179         ALIAS_MAXSHMMEM,
 180         ALIAS_MAXSHMIDS,
 181         ALIAS_MAXMSGIDS,
 182         ALIAS_MAXSEMIDS,
 183         ALIAS_SHARES,
 184         "scheduling-class",
 185         "ip-type",
 186         "capped-cpu",
 187         "hostid",
 188         "admin",
 189         "fs-allowed",
 190         ALIAS_MAXPROCS,
 191         NULL
 192 };
 193 
 194 /* These *must* match the order of the PT_ define's from zonecfg.h */
 195 char *prop_types[] = {
 196         "unknown",
 197         "zonename",
 198         "zonepath",
 199         "autoboot",
 200         "pool",
 201         "dir",
 202         "special",
 203         "type",
 204         "options",
 205         "address",
 206         "physical",
 207         "name",
 208         "value",
 209         "match",
 210         "priv",
 
 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[] = {
 
 288         "add capped-cpu",
 289         "add capped-memory",
 290         "add admin",
 291         NULL
 292 };
 293 
 294 static const char *clear_cmds[] = {
 295         "clear autoboot",
 296         "clear pool",
 297         "clear limitpriv",
 298         "clear bootargs",
 299         "clear scheduling-class",
 300         "clear ip-type",
 301         "clear " ALIAS_MAXLWPS,
 302         "clear " ALIAS_MAXSHMMEM,
 303         "clear " ALIAS_MAXSHMIDS,
 304         "clear " ALIAS_MAXMSGIDS,
 305         "clear " ALIAS_MAXSEMIDS,
 306         "clear " ALIAS_SHARES,
 307         "clear " ALIAS_MAXPROCS,
 308         NULL
 309 };
 310 
 311 static const char *remove_cmds[] = {
 312         "remove fs ",
 313         "remove net ",
 314         "remove device ",
 315         "remove rctl ",
 316         "remove attr ",
 317         "remove dataset ",
 318         "remove dedicated-cpu ",
 319         "remove capped-cpu ",
 320         "remove capped-memory ",
 321         "remove admin ",
 322         NULL
 323 };
 324 
 325 static const char *select_cmds[] = {
 326         "select fs ",
 327         "select net ",
 
 338 
 339 static const char *set_cmds[] = {
 340         "set zonename=",
 341         "set zonepath=",
 342         "set brand=",
 343         "set autoboot=",
 344         "set pool=",
 345         "set limitpriv=",
 346         "set bootargs=",
 347         "set scheduling-class=",
 348         "set ip-type=",
 349         "set " ALIAS_MAXLWPS "=",
 350         "set " ALIAS_MAXSHMMEM "=",
 351         "set " ALIAS_MAXSHMIDS "=",
 352         "set " ALIAS_MAXMSGIDS "=",
 353         "set " ALIAS_MAXSEMIDS "=",
 354         "set " ALIAS_SHARES "=",
 355         "set hostid=",
 356         "set fs-allowed=",
 357         "set " ALIAS_MAXPROCS "=",
 358         NULL
 359 };
 360 
 361 static const char *info_cmds[] = {
 362         "info fs ",
 363         "info net ",
 364         "info device ",
 365         "info rctl ",
 366         "info attr ",
 367         "info dataset ",
 368         "info capped-memory",
 369         "info dedicated-cpu",
 370         "info capped-cpu",
 371         "info zonename",
 372         "info zonepath",
 373         "info autoboot",
 374         "info pool",
 375         "info limitpriv",
 376         "info bootargs",
 377         "info brand",
 378         "info scheduling-class",
 379         "info ip-type",
 380         "info max-lwps",
 381         "info max-shm-memory",
 382         "info max-shm-ids",
 383         "info max-msg-ids",
 384         "info max-sem-ids",
 385         "info cpu-shares",
 386         "info hostid",
 387         "info admin",
 388         "info fs-allowed",
 389         "info max-processes",
 390         NULL
 391 };
 392 
 393 static const char *fs_res_scope_cmds[] = {
 394         "add options ",
 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[] = {
 
 526         struct xif      *xif_next;
 527         char            xif_name[LIFNAMSIZ];
 528         boolean_t       xif_has_address;
 529         boolean_t       xif_has_defrouter;
 530 };
 531 
 532 /* Global variables */
 533 
 534 /* list of network interfaces specified for exclusive IP zone */
 535 struct xif *xif;
 536 
 537 /* set early in main(), never modified thereafter, used all over the place */
 538 static char *execname;
 539 
 540 /* set in main(), used all over the place */
 541 static zone_dochandle_t handle;
 542 
 543 /* used all over the place */
 544 static char zone[ZONENAME_MAX];
 545 static char revert_zone[ZONENAME_MAX];
 546 
 547 /* global brand operations */
 548 static brand_handle_t brand;
 549 
 550 /* set in modifying functions, checked in read_input() */
 551 static boolean_t need_to_commit = B_FALSE;
 552 boolean_t saw_error;
 553 
 554 /* set in yacc parser, checked in read_input() */
 555 boolean_t newline_terminated;
 556 
 557 /* set in main(), checked in lex error handler */
 558 boolean_t cmd_file_mode;
 559 
 560 /* set in exit_func(), checked in read_input() */
 561 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
 562 
 563 /* used in short_usage() and zerr() */
 564 static char *cmd_file_name = NULL;
 565 
 566 /* checked in read_input() and other places */
 567 static boolean_t ok_to_prompt = B_FALSE;
 568 
 569 /* set and checked in initialize() */
 570 static boolean_t got_handle = B_FALSE;
 571 
 
 
 973         if ((pathstr = getenv("PATH")) == NULL) {
 974                 if (geteuid() == 0 || getuid() == 0)
 975                         pathstr = "/usr/sbin:/usr/bin";
 976                 else
 977                         pathstr = "/usr/bin:";
 978         }
 979         cp = strchr(name, '/') ? (const char *) "" : pathstr;
 980 
 981         do {
 982                 cp = exec_cat(cp, name, fname);
 983                 if (stat(fname, &stat_buf) != -1) {
 984                         /* successful find of the file */
 985                         return (0);
 986                 }
 987         } while (cp != NULL);
 988 
 989         return (-1);
 990 }
 991 
 992 static FILE *
 993 pager_open(void) {
 994         FILE *newfp;
 995         char *pager, *space;
 996 
 997         pager = getenv("PAGER");
 998         if (pager == NULL || *pager == '\0')
 999                 pager = PAGER;
1000 
1001         space = strchr(pager, ' ');
1002         if (space)
1003                 *space = '\0';
1004         if (path_find(pager) == 0) {
1005                 if (space)
1006                         *space = ' ';
1007                 if ((newfp = popen(pager, "w")) == NULL)
1008                         zerr(gettext("PAGER open failed (%s)."),
1009                             strerror(errno));
1010                 return (newfp);
1011         } else {
1012                 zerr(gettext("PAGER %s does not exist (%s)."),
1013                     pager, strerror(errno));
1014         }
1015         return (NULL);
1016 }
1017 
1018 static void
1019 pager_close(FILE *fp) {
1020         int status;
1021 
1022         status = pclose(fp);
1023         if (status == -1)
1024                 zerr(gettext("PAGER close failed (%s)."),
1025                     strerror(errno));
1026 }
1027 
1028 /*
1029  * Called with verbose TRUE when help is explicitly requested, FALSE for
1030  * unexpected errors.
1031  */
1032 
1033 void
1034 usage(boolean_t verbose, uint_t flags)
1035 {
1036         FILE *fp = verbose ? stdout : stderr;
1037         FILE *newfp;
1038         boolean_t need_to_close = B_FALSE;
1039         int i;
 
1254                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1255                             pt_to_str(PT_USER),
1256                             gettext("<single user or role name>"));
1257                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1258                             pt_to_str(PT_AUTHS),
1259                             gettext("<comma separated list>"));
1260                         break;
1261                 }
1262                 (void) fprintf(fp, gettext("And from any resource scope, you "
1263                     "can:\n"));
1264                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1265                     gettext("(to conclude this operation)"));
1266                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1267                     gettext("(to cancel this operation)"));
1268                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1269                     gettext("(to exit the zonecfg utility)"));
1270         }
1271         if (flags & HELP_USAGE) {
1272                 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1273                     execname, cmd_to_str(CMD_HELP));
1274                 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1275                     execname, gettext("interactive"));
1276                 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1277                 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1278                     execname);
1279         }
1280         if (flags & HELP_SUBCMDS) {
1281                 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1282                 for (i = 0; i <= CMD_MAX; i++) {
1283                         (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1284                         if (verbose)
1285                                 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1286                 }
1287         }
1288         if (flags & HELP_SYNTAX) {
1289                 if (!verbose)
1290                         (void) fprintf(fp, "\n");
1291                 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1292                 (void) fprintf(fp, gettext("\t(except the reserved words "
1293                     "'%s' and anything starting with '%s')\n"), "global",
1294                     "SUNW");
1295                 (void) fprintf(fp,
1296                     gettext("\tName must be less than %d characters.\n"),
1297                     ZONENAME_MAX);
1298                 if (verbose)
 
1346                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1347                     pt_to_str(PT_IPTYPE));
1348                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1349                     pt_to_str(PT_HOSTID));
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),
 
1682                     cmd_to_str(cmd_num));
1683                 saw_error = B_TRUE;
1684                 return (B_TRUE);
1685         }
1686         return (B_FALSE);
1687 }
1688 
1689 /*
1690  * Create a new configuration.
1691  */
1692 void
1693 create_func(cmd_t *cmd)
1694 {
1695         int err, arg;
1696         char zone_template[ZONENAME_MAX];
1697         char attach_path[MAXPATHLEN];
1698         zone_dochandle_t tmphandle;
1699         boolean_t force = B_FALSE;
1700         boolean_t attach = B_FALSE;
1701         boolean_t arg_err = B_FALSE;
1702 
1703         assert(cmd != NULL);
1704 
1705         /* This is the default if no arguments are given. */
1706         (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1707 
1708         optind = 0;
1709         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
1710             != EOF) {
1711                 switch (arg) {
1712                 case '?':
1713                         if (optopt == '?')
1714                                 longer_usage(CMD_CREATE);
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;
 
1779                 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1780                     zone, B_FALSE, tmphandle);
1781         else
1782                 err = zonecfg_get_template_handle(zone_template, zone,
1783                     tmphandle);
1784 
1785         if (err != Z_OK) {
1786                 zonecfg_fini_handle(tmphandle);
1787                 if (attach && err == Z_NO_ZONE)
1788                         (void) fprintf(stderr, gettext("invalid path to "
1789                             "detached zone\n"));
1790                 else if (attach && err == Z_INVALID_DOCUMENT)
1791                         (void) fprintf(stderr, gettext("Cannot attach to an "
1792                             "earlier release of the operating system\n"));
1793                 else
1794                         zone_perror(zone_template, err, B_TRUE);
1795                 return;
1796         }
1797 
1798         need_to_commit = B_TRUE;
1799         zonecfg_fini_handle(handle);
1800         handle = tmphandle;
1801         got_handle = B_TRUE;
1802 }
1803 
1804 /*
1805  * This malloc()'s memory, which must be freed by the caller.
1806  */
1807 static char *
1808 quoteit(char *instr)
1809 {
1810         char *outstr;
1811         size_t outstrsize = strlen(instr) + 3;  /* 2 quotes + '\0' */
1812 
1813         if ((outstr = malloc(outstrsize)) == NULL) {
1814                 zone_perror(zone, Z_NOMEM, B_FALSE);
1815                 exit(Z_ERR);
1816         }
1817         if (strchr(instr, ' ') == NULL) {
1818                 (void) strlcpy(outstr, instr, outstrsize);
1819                 return (outstr);
1820         }
1821         (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
 
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) {
1870                 switch (arg) {
1871                 case '?':
1872                         if (optopt == '?')
1873                                 longer_usage(CMD_EXPORT);
1874                         else
1875                                 short_usage(CMD_EXPORT);
1876                         arg_err = B_TRUE;
1877                         break;
1878                 case 'f':
1879                         (void) strlcpy(outfile, optarg, sizeof (outfile));
1880                         break;
1881                 default:
 
1952                             pt_to_str(PT_IPTYPE), "shared");
1953                         break;
1954                 case ZS_EXCLUSIVE:
1955                         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1956                             pt_to_str(PT_IPTYPE), "exclusive");
1957                         break;
1958                 }
1959         }
1960 
1961         if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1962                 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1963                     pt_to_str(PT_HOSTID), hostidp);
1964         }
1965 
1966         if (zonecfg_get_fs_allowed(handle, fsallowedp,
1967             sizeof (fsallowedp)) == Z_OK) {
1968                 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1969                     pt_to_str(PT_FS_ALLOWED), fsallowedp);
1970         }
1971 
1972         if ((err = zonecfg_setfsent(handle)) != Z_OK) {
1973                 zone_perror(zone, err, B_FALSE);
1974                 goto done;
1975         }
1976         while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
1977                 zone_fsopt_t *optptr;
1978 
1979                 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1980                     rt_to_str(RT_FS));
1981                 export_prop(of, PT_DIR, fstab.zone_fs_dir);
1982                 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
1983                 export_prop(of, PT_RAW, fstab.zone_fs_raw);
1984                 export_prop(of, PT_TYPE, fstab.zone_fs_type);
1985                 for (optptr = fstab.zone_fs_options; optptr != NULL;
1986                     optptr = optptr->zone_fsopt_next) {
1987                         /*
1988                          * Simple property values with embedded equal signs
1989                          * need to be quoted to prevent the lexer from
1990                          * mis-parsing them as complex name=value pairs.
1991                          */
 
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);
 
2606         default:
2607                 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2608                 long_usage(CMD_ADD, B_TRUE);
2609                 usage(B_FALSE, HELP_RESOURCES);
2610                 return;
2611         }
2612 }
2613 
2614 static boolean_t
2615 gz_invalid_resource(int type)
2616 {
2617         return (global_zone && (type == RT_FS ||
2618             type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2619             type == RT_DATASET));
2620 }
2621 
2622 static boolean_t
2623 gz_invalid_rt_property(int type)
2624 {
2625         return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2626             type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
2627             type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2628             type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2629 }
2630 
2631 static boolean_t
2632 gz_invalid_property(int type)
2633 {
2634         return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2635             type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
2636             type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2637             type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2638 }
2639 
2640 void
2641 add_func(cmd_t *cmd)
2642 {
2643         int arg;
2644         boolean_t arg_err = B_FALSE;
2645 
2646         assert(cmd != NULL);
2647 
2648         optind = 0;
2649         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2650                 switch (arg) {
2651                 case '?':
2652                         longer_usage(CMD_ADD);
2653                         arg_err = B_TRUE;
2654                         break;
2655                 default:
 
2833                         break;
2834                 case PT_RAW:
2835                         (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2836                             sizeof (fstab->zone_fs_raw));
2837                         break;
2838                 case PT_TYPE:
2839                         (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2840                             sizeof (fstab->zone_fs_type));
2841                         break;
2842                 default:
2843                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2844                             Z_NO_PROPERTY_TYPE, B_TRUE);
2845                         return (Z_INSUFFICIENT_SPEC);
2846                 }
2847         }
2848         if (fill_in_only)
2849                 return (Z_OK);
2850         return (zonecfg_lookup_filesystem(handle, fstab));
2851 }
2852 
2853 static int
2854 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2855     boolean_t fill_in_only)
2856 {
2857         int err, i;
2858         property_value_ptr_t pp;
2859 
2860         if ((err = initialize(B_TRUE)) != Z_OK)
2861                 return (err);
2862 
2863         bzero(nwiftab, sizeof (*nwiftab));
2864         for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2865                 pp = cmd->cmd_property_ptr[i];
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]),
 
3131         boolean_t arg_err = B_FALSE;
3132 
3133         optind = 0;
3134         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
3135                 switch (arg) {
3136                 case 'F':
3137                         force = B_TRUE;
3138                         break;
3139                 default:
3140                         arg_err = B_TRUE;
3141                         break;
3142                 }
3143         }
3144         if (arg_err)
3145                 return (B_FALSE);
3146 
3147 
3148         num = zonecfg_num_resources(handle, rsrc);
3149 
3150         if (num == 0) {
3151                 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
3152                     B_TRUE);
3153                 return (B_FALSE);
3154         }
3155         if (num > 1 && !force) {
3156                 if (!interactive_mode) {
3157                         zerr(gettext("There are multiple instances of this "
3158                             "resource.  Either qualify the resource to\n"
3159                             "remove a single instance or use the -F option to "
3160                             "remove all instances."));
3161                         saw_error = B_TRUE;
3162                         return (B_FALSE);
3163                 }
3164                 (void) snprintf(prompt, sizeof (prompt), gettext(
3165                     "Are you sure you want to remove ALL '%s' resources"),
3166                     rsrc);
3167                 answer = ask_yesno(B_FALSE, prompt);
3168                 if (answer == -1) {
3169                         zerr(gettext("Resource incomplete."));
3170                         return (B_FALSE);
3171                 }
3172                 if (answer != 1)
3173                         return (B_FALSE);
3174         }
3175         return (B_TRUE);
3176 }
3177 
3178 static void
3179 remove_fs(cmd_t *cmd)
3180 {
3181         int err;
3182 
3183         /* traditional, qualified fs removal */
3184         if (cmd->cmd_prop_nv_pairs > 0) {
3185                 struct zone_fstab fstab;
3186 
3187                 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
3188                         z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3189                         return;
3190                 }
3191                 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
3192                         z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3193                 else
3194                         need_to_commit = B_TRUE;
3195                 zonecfg_free_fs_option_list(fstab.zone_fs_options);
3196                 return;
3197         }
3198 
3199         /*
3200          * unqualified fs removal.  remove all fs's but prompt if more
3201          * than one.
3202          */
3203         if (!prompt_remove_resource(cmd, "fs"))
3204                 return;
3205 
3206         if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
3207                 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
3208         else
3209                 need_to_commit = B_TRUE;
3210 }
3211 
3212 static void
3213 remove_net(cmd_t *cmd)
3214 {
3215         int err;
3216 
3217         /* traditional, qualified net removal */
3218         if (cmd->cmd_prop_nv_pairs > 0) {
3219                 struct zone_nwiftab nwiftab;
3220 
3221                 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
3222                         z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3223                         return;
3224                 }
3225                 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
3226                         z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3227                 else
3228                         need_to_commit = B_TRUE;
3229                 return;
3230         }
3231 
3232         /*
3233          * unqualified net removal.  remove all nets but prompt if more
3234          * than one.
3235          */
3236         if (!prompt_remove_resource(cmd, "net"))
3237                 return;
3238 
3239         if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
3240                 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
3241         else
3242                 need_to_commit = B_TRUE;
3243 }
3244 
3245 static void
3246 remove_device(cmd_t *cmd)
3247 {
3248         int err;
3249 
3250         /* traditional, qualified device removal */
3251         if (cmd->cmd_prop_nv_pairs > 0) {
3252                 struct zone_devtab devtab;
3253 
3254                 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3255                         z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3256                         return;
3257                 }
3258                 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
3259                         z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3260                 else
3261                         need_to_commit = B_TRUE;
3262                 return;
3263         }
3264 
3265         /*
3266          * unqualified device removal.  remove all devices but prompt if more
3267          * than one.
3268          */
3269         if (!prompt_remove_resource(cmd, "device"))
3270                 return;
3271 
3272         if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3273                 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3274         else
3275                 need_to_commit = B_TRUE;
3276 }
3277 
3278 static void
3279 remove_attr(cmd_t *cmd)
3280 {
3281         int err;
3282 
3283         /* traditional, qualified attr removal */
3284         if (cmd->cmd_prop_nv_pairs > 0) {
3285                 struct zone_attrtab attrtab;
3286 
3287                 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3288                         z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3289                         return;
3290                 }
3291                 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
3292                         z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3293                 else
3294                         need_to_commit = B_TRUE;
3295                 return;
3296         }
3297 
3298         /*
3299          * unqualified attr removal.  remove all attrs but prompt if more
3300          * than one.
3301          */
3302         if (!prompt_remove_resource(cmd, "attr"))
3303                 return;
3304 
3305         if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3306                 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3307         else
3308                 need_to_commit = B_TRUE;
3309 }
3310 
3311 static void
3312 remove_dataset(cmd_t *cmd)
3313 {
3314         int err;
3315 
3316         /* traditional, qualified dataset removal */
3317         if (cmd->cmd_prop_nv_pairs > 0) {
3318                 struct zone_dstab dstab;
3319 
3320                 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3321                         z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3322                         return;
3323                 }
3324                 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
3325                         z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3326                 else
3327                         need_to_commit = B_TRUE;
3328                 return;
3329         }
3330 
3331         /*
3332          * unqualified dataset removal.  remove all datasets but prompt if more
3333          * than one.
3334          */
3335         if (!prompt_remove_resource(cmd, "dataset"))
3336                 return;
3337 
3338         if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3339                 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3340         else
3341                 need_to_commit = B_TRUE;
3342 }
3343 
3344 static void
3345 remove_rctl(cmd_t *cmd)
3346 {
3347         int err;
3348 
3349         /* traditional, qualified rctl removal */
3350         if (cmd->cmd_prop_nv_pairs > 0) {
3351                 struct zone_rctltab rctltab;
3352 
3353                 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3354                         z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3355                         return;
3356                 }
3357                 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
3358                         z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3359                 else
3360                         need_to_commit = B_TRUE;
3361                 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3362                 return;
3363         }
3364 
3365         /*
3366          * unqualified rctl removal.  remove all rctls but prompt if more
3367          * than one.
3368          */
3369         if (!prompt_remove_resource(cmd, "rctl"))
3370                 return;
3371 
3372         if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3373                 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3374         else
3375                 need_to_commit = B_TRUE;
3376 }
3377 
3378 static void
3379 remove_pset()
3380 {
3381         int err;
3382         struct zone_psettab psettab;
3383 
3384         if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3385                 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3386                 return;
3387         }
3388         if ((err = zonecfg_delete_pset(handle)) != Z_OK)
3389                 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3390         else
3391                 need_to_commit = B_TRUE;
3392 }
3393 
3394 static void
3395 remove_pcap()
3396 {
3397         int err;
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)
3461                 need_to_commit = B_FALSE;
3462 }
3463 
3464 static void
3465 remove_admin(cmd_t *cmd)
3466 {
3467         int err;
3468 
3469         /* traditional, qualified attr removal */
3470         if (cmd->cmd_prop_nv_pairs > 0) {
3471                 struct zone_admintab admintab;
3472 
3473                 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3474                         z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3475                             err, B_TRUE);
3476                         return;
3477                 }
3478                 if ((err = zonecfg_delete_admin(handle, &admintab,
3479                     zone))
3480                     != Z_OK)
3481                         z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3482                             err, B_TRUE);
3483                 else
3484                         need_to_commit = B_TRUE;
3485                 return;
3486         } else {
3487                 /*
3488                  * unqualified admin removal.
3489                  * remove all admins but prompt if more
3490                  * than one.
3491                  */
3492                 if (!prompt_remove_resource(cmd, "admin"))
3493                         return;
3494 
3495                 if ((err = zonecfg_delete_admins(handle, zone))
3496                     != Z_OK)
3497                         z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3498                             err, B_TRUE);
3499                 else
3500                         need_to_commit = B_TRUE;
3501         }
3502 }
3503 
3504 static void
3505 remove_resource(cmd_t *cmd)
3506 {
3507         int type;
3508         int arg;
3509         boolean_t arg_err = B_FALSE;
3510 
3511         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3512                 long_usage(CMD_REMOVE, B_TRUE);
3513                 return;
3514         }
3515 
3516         optind = 0;
3517         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3518                 switch (arg) {
3519                 case '?':
3520                         longer_usage(CMD_REMOVE);
3521                         arg_err = B_TRUE;
3522                         break;
3523                 case 'F':
3524                         break;
3525                 default:
3526                         short_usage(CMD_REMOVE);
3527                         arg_err = B_TRUE;
3528                         break;
3529                 }
3530         }
3531         if (arg_err)
3532                 return;
3533 
3534         if (initialize(B_TRUE) != Z_OK)
3535                 return;
3536 
3537         switch (type) {
3538         case RT_FS:
3539                 remove_fs(cmd);
3540                 return;
3541         case RT_NET:
3542                 remove_net(cmd);
3543                 return;
3544         case RT_DEVICE:
3545                 remove_device(cmd);
3546                 return;
3547         case RT_RCTL:
3548                 remove_rctl(cmd);
3549                 return;
3550         case RT_ATTR:
3551                 remove_attr(cmd);
3552                 return;
3553         case RT_DATASET:
3554                 remove_dataset(cmd);
3555                 return;
3556         case RT_DCPU:
3557                 remove_pset();
3558                 return;
3559         case RT_PCAP:
3560                 remove_pcap();
3561                 return;
3562         case RT_MCAP:
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) {
3604                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3605                             B_TRUE);
3606                         long_usage(CMD_REMOVE, B_TRUE);
3607                         usage(B_FALSE, HELP_PROPS);
3608                         return;
3609                 }
3610                 pp = cmd->cmd_property_ptr[0];
3611                 if (pp->pv_type == PROP_VAL_COMPLEX) {
3612                         zerr(gettext("A %s or %s value was expected here."),
3613                             pvt_to_str(PROP_VAL_SIMPLE),
3614                             pvt_to_str(PROP_VAL_LIST));
3615                         saw_error = B_TRUE;
3616                         return;
3617                 }
3618                 if (pp->pv_type == PROP_VAL_SIMPLE) {
3619                         if (pp->pv_simple == NULL) {
3620                                 long_usage(CMD_ADD, B_TRUE);
3621                                 return;
3622                         }
3623                         prop_id = pp->pv_simple;
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;
 
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);
 
3722                                     cx->cp_value,
3723                                     sizeof (rctlvaltab->zone_rctlval_limit));
3724                                 break;
3725                         case PT_ACTION:
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) {
 
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 
3862         switch (type) {
3863         case PT_ZONENAME:
3864                 /* FALLTHRU */
3865         case PT_ZONEPATH:
3866                 /* FALLTHRU */
3867         case PT_BRAND:
3868                 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
3869                 return;
3870         case PT_AUTOBOOT:
3871                 /* false is default; we'll treat as equivalent to clearing */
3872                 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
3873                         z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
3874                 else
3875                         need_to_commit = B_TRUE;
3876                 return;
3877         case PT_POOL:
3878                 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
3879                         z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
3880                 else
3881                         need_to_commit = B_TRUE;
3882                 return;
3883         case PT_LIMITPRIV:
3884                 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
3885                         z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
3886                 else
 
3909                 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
3910                 return;
3911         case PT_MAXPROCS:
3912                 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
3913                 return;
3914         case PT_MAXSHMMEM:
3915                 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
3916                 return;
3917         case PT_MAXSHMIDS:
3918                 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
3919                 return;
3920         case PT_MAXMSGIDS:
3921                 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
3922                 return;
3923         case PT_MAXSEMIDS:
3924                 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
3925                 return;
3926         case PT_SHARES:
3927                 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
3928                 return;
3929         case PT_HOSTID:
3930                 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
3931                         z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
3932                 else
3933                         need_to_commit = B_TRUE;
3934                 return;
3935         case PT_FS_ALLOWED:
3936                 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
3937                         z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
3938                 else
3939                         need_to_commit = B_TRUE;
3940                 return;
3941         default:
3942                 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
3943                 long_usage(CMD_CLEAR, B_TRUE);
3944                 usage(B_FALSE, HELP_PROPS);
3945                 return;
3946         }
3947 }
3948 
 
 
4399                 } else if (prop_type == PT_IPTYPE) {
4400                         res_type = RT_IPTYPE;
4401                 } else if (prop_type == PT_MAXLWPS) {
4402                         res_type = RT_MAXLWPS;
4403                 } else if (prop_type == PT_MAXPROCS) {
4404                         res_type = RT_MAXPROCS;
4405                 } else if (prop_type == PT_MAXSHMMEM) {
4406                         res_type = RT_MAXSHMMEM;
4407                 } else if (prop_type == PT_MAXSHMIDS) {
4408                         res_type = RT_MAXSHMIDS;
4409                 } else if (prop_type == PT_MAXMSGIDS) {
4410                         res_type = RT_MAXMSGIDS;
4411                 } else if (prop_type == PT_MAXSEMIDS) {
4412                         res_type = RT_MAXSEMIDS;
4413                 } else if (prop_type == PT_SHARES) {
4414                         res_type = RT_SHARES;
4415                 } else if (prop_type == PT_HOSTID) {
4416                         res_type = RT_HOSTID;
4417                 } else if (prop_type == PT_FS_ALLOWED) {
4418                         res_type = RT_FS_ALLOWED;
4419                 } else {
4420                         zerr(gettext("Cannot set a resource-specific property "
4421                             "from the global scope."));
4422                         saw_error = B_TRUE;
4423                         return;
4424                 }
4425         } else {
4426                 res_type = resource_scope;
4427         }
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;
 
4606                 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4607                 return;
4608         case RT_MAXPROCS:
4609                 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4610                 return;
4611         case RT_MAXSHMMEM:
4612                 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4613                 return;
4614         case RT_MAXSHMIDS:
4615                 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4616                 return;
4617         case RT_MAXMSGIDS:
4618                 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4619                 return;
4620         case RT_MAXSEMIDS:
4621                 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4622                 return;
4623         case RT_SHARES:
4624                 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4625                 return;
4626         case RT_HOSTID:
4627                 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4628                         if (err == Z_TOO_BIG) {
4629                                 zerr(gettext("hostid string is too large: %s"),
4630                                     prop_id);
4631                                 saw_error = B_TRUE;
4632                         } else {
4633                                 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4634                         }
4635                         return;
4636                 }
4637                 need_to_commit = B_TRUE;
4638                 return;
4639         case RT_FS_ALLOWED:
4640                 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4641                         zone_perror(zone, err, B_TRUE);
4642                 else
4643                         need_to_commit = B_TRUE;
4644                 return;
4645         case RT_FS:
4646                 switch (prop_type) {
4647                 case PT_DIR:
4648                         (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4649                             sizeof (in_progress_fstab.zone_fs_dir));
4650                         return;
4651                 case PT_SPECIAL:
4652                         (void) strlcpy(in_progress_fstab.zone_fs_special,
4653                             prop_id,
4654                             sizeof (in_progress_fstab.zone_fs_special));
4655                         return;
4656                 case PT_RAW:
4657                         (void) strlcpy(in_progress_fstab.zone_fs_raw,
4658                             prop_id, sizeof (in_progress_fstab.zone_fs_raw));
 
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,
 
5219         }
5220 }
5221 
5222 static void
5223 info_hostid(zone_dochandle_t handle, FILE *fp)
5224 {
5225         char hostidp[HW_HOSTID_LEN];
5226         int err;
5227 
5228         if ((err = zonecfg_get_hostid(handle, hostidp,
5229             sizeof (hostidp))) == Z_OK) {
5230                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
5231         } else if (err == Z_BAD_PROPERTY) {
5232                 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
5233         } else {
5234                 zone_perror(zone, err, B_TRUE);
5235         }
5236 }
5237 
5238 static void
5239 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
5240 {
5241         char fsallowedp[ZONE_FS_ALLOWED_MAX];
5242         int err;
5243 
5244         if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
5245             sizeof (fsallowedp))) == Z_OK) {
5246                 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
5247                     fsallowedp);
5248         } else if (err == Z_BAD_PROPERTY) {
5249                 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
5250         } else {
5251                 zone_perror(zone, err, B_TRUE);
5252         }
5253 }
5254 
5255 static void
5256 output_fs(FILE *fp, struct zone_fstab *fstab)
5257 {
5258         zone_fsopt_t *this;
 
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);
 
5817                     rt_to_str(type));
5818                 goto cleanup;
5819         }
5820 
5821         switch (cmd->cmd_res_type) {
5822         case RT_UNKNOWN:
5823                 info_zonename(handle, fp);
5824                 if (!global_zone) {
5825                         info_zonepath(handle, fp);
5826                         info_brand(handle, fp);
5827                         info_autoboot(handle, fp);
5828                         info_bootargs(handle, fp);
5829                 }
5830                 info_pool(handle, fp);
5831                 if (!global_zone) {
5832                         info_limitpriv(handle, fp);
5833                         info_sched(handle, fp);
5834                         info_iptype(handle, fp);
5835                         info_hostid(handle, fp);
5836                         info_fs_allowed(handle, fp);
5837                 }
5838                 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5839                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5840                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5841                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5842                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5843                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5844                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5845                 if (!global_zone) {
5846                         info_fs(handle, fp, cmd);
5847                         info_net(handle, fp, cmd);
5848                         info_dev(handle, fp, cmd);
5849                 }
5850                 info_pset(handle, fp);
5851                 info_pcap(fp);
5852                 info_mcap(handle, fp);
5853                 if (!global_zone) {
5854                         info_attr(handle, fp, cmd);
5855                         info_ds(handle, fp, cmd);
5856                         info_auth(handle, fp, cmd);
5857                 }
5858                 info_rctl(handle, fp, cmd);
5859                 break;
5860         case RT_ZONENAME:
5861                 info_zonename(handle, fp);
5862                 break;
5863         case RT_ZONEPATH:
5864                 info_zonepath(handle, fp);
 
5888                 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5889                 break;
5890         case RT_MAXPROCS:
5891                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5892                 break;
5893         case RT_MAXSHMMEM:
5894                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5895                 break;
5896         case RT_MAXSHMIDS:
5897                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5898                 break;
5899         case RT_MAXMSGIDS:
5900                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5901                 break;
5902         case RT_MAXSEMIDS:
5903                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5904                 break;
5905         case RT_SHARES:
5906                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5907                 break;
5908         case RT_FS:
5909                 info_fs(handle, fp, cmd);
5910                 break;
5911         case RT_NET:
5912                 info_net(handle, fp, cmd);
5913                 break;
5914         case RT_DEVICE:
5915                 info_dev(handle, fp, cmd);
5916                 break;
5917         case RT_RCTL:
5918                 info_rctl(handle, fp, cmd);
5919                 break;
5920         case RT_ATTR:
5921                 info_attr(handle, fp, cmd);
5922                 break;
5923         case RT_DATASET:
5924                 info_ds(handle, fp, cmd);
5925                 break;
5926         case RT_DCPU:
5927                 info_pset(handle, fp);
5928                 break;
5929         case RT_PCAP:
5930                 info_pcap(fp);
5931                 break;
5932         case RT_MCAP:
5933                 info_mcap(handle, fp);
5934                 break;
5935         case RT_HOSTID:
5936                 info_hostid(handle, fp);
5937                 break;
5938         case RT_ADMIN:
5939                 info_auth(handle, fp, cmd);
5940                 break;
5941         case RT_FS_ALLOWED:
5942                 info_fs_allowed(handle, fp);
5943                 break;
5944         default:
5945                 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5946                     B_TRUE);
5947         }
5948 
5949 cleanup:
5950         if (need_to_close)
5951                 (void) pager_close(fp);
5952 }
5953 
5954 /*
5955  * Helper function for verify-- checks that a required string property
5956  * exists.
5957  */
 
 
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);
6445 
6446         optind = 0;
6447         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6448                 switch (arg) {
6449                 case '?':
 
7459         for (;;) {
7460                 last_slash = strrchr(execfullname, '/');
7461                 if (last_slash == NULL) {
7462                         execbasename = execfullname;
7463                         break;
7464                 } else {
7465                         execbasename = last_slash + 1;
7466                         if (*execbasename == '\0') {
7467                                 *last_slash = '\0';
7468                                 continue;
7469                         }
7470                         break;
7471                 }
7472         }
7473         return (execbasename);
7474 }
7475 
7476 int
7477 main(int argc, char *argv[])
7478 {
7479         int err, arg;
7480         struct stat st;
7481 
7482         /* This must be before anything goes to stdout. */
7483         setbuf(stdout, NULL);
7484 
7485         saw_error = B_FALSE;
7486         cmd_file_mode = B_FALSE;
7487         execname = get_execbasename(argv[0]);
7488 
7489         (void) setlocale(LC_ALL, "");
7490         (void) textdomain(TEXT_DOMAIN);
7491 
7492         if (getzoneid() != GLOBAL_ZONEID) {
7493                 zerr(gettext("%s can only be run from the global zone."),
7494                     execname);
7495                 exit(Z_ERR);
7496         }
7497 
7498         if (argc < 2) {
7499                 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7500                 exit(Z_USAGE);
7501         }
7502         if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7503                 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7504                 exit(Z_OK);
7505         }
7506 
7507         while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
7508                 switch (arg) {
7509                 case '?':
7510                         if (optopt == '?')
7511                                 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7512                         else
7513                                 usage(B_FALSE, HELP_USAGE);
7514                         exit(Z_USAGE);
7515                         /* NOTREACHED */
7516                 case 'f':
7517                         cmd_file_name = optarg;
7518                         cmd_file_mode = B_TRUE;
7519                         break;
7520                 case 'R':
7521                         if (*optarg != '/') {
7522                                 zerr(gettext("root path must be absolute: %s"),
7523                                     optarg);
7524                                 exit(Z_USAGE);
7525                         }
7526                         if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7527                                 zerr(gettext(
7528                                     "root path must be a directory: %s"),
7529                                     optarg);
7530                                 exit(Z_USAGE);
7531                         }
7532                         zonecfg_set_root(optarg);
7533                         break;
7534                 case 'z':
7535                         if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7536                                 global_zone = B_TRUE;
7537                         } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7538                                 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7539                                 usage(B_FALSE, HELP_SYNTAX);
7540                                 exit(Z_USAGE);
7541                         }
7542                         (void) strlcpy(zone, optarg, sizeof (zone));
7543                         (void) strlcpy(revert_zone, optarg, sizeof (zone));
7544                         break;
7545                 default:
7546                         usage(B_FALSE, HELP_USAGE);
7547                         exit(Z_USAGE);
7548                 }
7549         }
7550 
7551         if (optind > argc || strcmp(zone, "") == 0) {
7552                 usage(B_FALSE, HELP_USAGE);
7553                 exit(Z_USAGE);
7554         }
7555 
7556         if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7557                 read_only_mode = B_FALSE;
7558         } else if (err == Z_ACCES) {
7559                 read_only_mode = B_TRUE;
7560                 /* skip this message in one-off from command line mode */
7561                 if (optind == argc)
7562                         (void) fprintf(stderr, gettext("WARNING: you do not "
7563                             "have write access to this zone's configuration "
7564                             "file;\ngoing into read-only mode.\n"));
7565         } else {
7566                 fprintf(stderr, "%s: Could not access zone configuration "
7567                     "store: %s\n", execname, zonecfg_strerror(err));
7568                 exit(Z_ERR);
7569         }
7570 
7571         if ((handle = zonecfg_init_handle()) == NULL) {
 
 |