Print this page
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (aslr)
7031 noexec_user_stack should be a secflag
7032 want a means to forbid mappings around NULL.


  36  * The resource/property data structures are inserted into a command
  37  * structure (see zonecfg.h), which also keeps track of command names,
  38  * miscellaneous arguments, and function handlers.  The grammar selects
  39  * the appropriate function handler, each of which takes a pointer to a
  40  * command structure as its sole argument, and invokes it.  The grammar
  41  * itself is "entered" (a la the Matrix) by yyparse(), which is called
  42  * from read_input(), our main driving function.  That in turn is called
  43  * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
  44  * of which is called from main() depending on how the program was invoked.
  45  *
  46  * The rest of this module consists of the various function handlers and
  47  * their helper functions.  Some of these functions, particularly the
  48  * X_to_str() functions, which maps command, resource and property numbers
  49  * to strings, are used quite liberally, as doing so results in a better
  50  * program w/rt I18N, reducing the need for translation notes.
  51  */
  52 
  53 #include <sys/mntent.h>
  54 #include <sys/varargs.h>
  55 #include <sys/sysmacros.h>

  56 
  57 #include <errno.h>
  58 #include <fcntl.h>
  59 #include <strings.h>
  60 #include <unistd.h>
  61 #include <ctype.h>
  62 #include <stdlib.h>
  63 #include <assert.h>
  64 #include <sys/stat.h>
  65 #include <zone.h>
  66 #include <arpa/inet.h>
  67 #include <netdb.h>
  68 #include <locale.h>
  69 #include <libintl.h>
  70 #include <alloca.h>
  71 #include <signal.h>
  72 #include <wait.h>
  73 #include <libtecla.h>
  74 #include <libzfs.h>
  75 #include <sys/brand.h>


 170         "attr",
 171         "dataset",
 172         "limitpriv",
 173         "bootargs",
 174         "brand",
 175         "dedicated-cpu",
 176         "capped-memory",
 177         ALIAS_MAXLWPS,
 178         ALIAS_MAXSHMMEM,
 179         ALIAS_MAXSHMIDS,
 180         ALIAS_MAXMSGIDS,
 181         ALIAS_MAXSEMIDS,
 182         ALIAS_SHARES,
 183         "scheduling-class",
 184         "ip-type",
 185         "capped-cpu",
 186         "hostid",
 187         "admin",
 188         "fs-allowed",
 189         ALIAS_MAXPROCS,

 190         NULL
 191 };
 192 
 193 /* These *must* match the order of the PT_ define's from zonecfg.h */
 194 char *prop_types[] = {
 195         "unknown",
 196         "zonename",
 197         "zonepath",
 198         "autoboot",
 199         "pool",
 200         "dir",
 201         "special",
 202         "type",
 203         "options",
 204         "address",
 205         "physical",
 206         "name",
 207         "value",
 208         "match",
 209         "priv",


 217         "importance",
 218         "swap",
 219         "locked",
 220         ALIAS_SHARES,
 221         ALIAS_MAXLWPS,
 222         ALIAS_MAXSHMMEM,
 223         ALIAS_MAXSHMIDS,
 224         ALIAS_MAXMSGIDS,
 225         ALIAS_MAXSEMIDS,
 226         ALIAS_MAXLOCKEDMEM,
 227         ALIAS_MAXSWAP,
 228         "scheduling-class",
 229         "ip-type",
 230         "defrouter",
 231         "hostid",
 232         "user",
 233         "auths",
 234         "fs-allowed",
 235         ALIAS_MAXPROCS,
 236         "allowed-address",



 237         NULL
 238 };
 239 
 240 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
 241 static char *prop_val_types[] = {
 242         "simple",
 243         "complex",
 244         "list",
 245 };
 246 
 247 /*
 248  * The various _cmds[] lists below are for command tab-completion.
 249  */
 250 
 251 /*
 252  * remove has a space afterwards because it has qualifiers; the other commands
 253  * that have qualifiers (add, select, etc.) don't need a space here because
 254  * they have their own _cmds[] lists below.
 255  */
 256 static const char *global_scope_cmds[] = {


 265         "info",
 266         "remove ",
 267         "revert",
 268         "select",
 269         "set",
 270         "verify",
 271         NULL
 272 };
 273 
 274 static const char *add_cmds[] = {
 275         "add fs",
 276         "add net",
 277         "add device",
 278         "add rctl",
 279         "add attr",
 280         "add dataset",
 281         "add dedicated-cpu",
 282         "add capped-cpu",
 283         "add capped-memory",
 284         "add admin",

 285         NULL
 286 };
 287 
 288 static const char *clear_cmds[] = {
 289         "clear autoboot",
 290         "clear pool",
 291         "clear limitpriv",
 292         "clear bootargs",
 293         "clear scheduling-class",
 294         "clear ip-type",
 295         "clear " ALIAS_MAXLWPS,
 296         "clear " ALIAS_MAXSHMMEM,
 297         "clear " ALIAS_MAXSHMIDS,
 298         "clear " ALIAS_MAXMSGIDS,
 299         "clear " ALIAS_MAXSEMIDS,
 300         "clear " ALIAS_SHARES,
 301         "clear " ALIAS_MAXPROCS,
 302         NULL
 303 };
 304 
 305 static const char *remove_cmds[] = {
 306         "remove fs ",
 307         "remove net ",
 308         "remove device ",
 309         "remove rctl ",
 310         "remove attr ",
 311         "remove dataset ",
 312         "remove dedicated-cpu ",
 313         "remove capped-cpu ",
 314         "remove capped-memory ",
 315         "remove admin ",

 316         NULL
 317 };
 318 
 319 static const char *select_cmds[] = {
 320         "select fs ",
 321         "select net ",
 322         "select device ",
 323         "select rctl ",
 324         "select attr ",
 325         "select dataset ",
 326         "select dedicated-cpu",
 327         "select capped-cpu",
 328         "select capped-memory",
 329         "select admin",

 330         NULL
 331 };
 332 
 333 static const char *set_cmds[] = {
 334         "set zonename=",
 335         "set zonepath=",
 336         "set brand=",
 337         "set autoboot=",
 338         "set pool=",
 339         "set limitpriv=",
 340         "set bootargs=",
 341         "set scheduling-class=",
 342         "set ip-type=",
 343         "set " ALIAS_MAXLWPS "=",
 344         "set " ALIAS_MAXSHMMEM "=",
 345         "set " ALIAS_MAXSHMIDS "=",
 346         "set " ALIAS_MAXMSGIDS "=",
 347         "set " ALIAS_MAXSEMIDS "=",
 348         "set " ALIAS_SHARES "=",
 349         "set hostid=",
 350         "set fs-allowed=",
 351         "set " ALIAS_MAXPROCS "=",
 352         NULL
 353 };
 354 
 355 static const char *info_cmds[] = {
 356         "info fs ",
 357         "info net ",
 358         "info device ",
 359         "info rctl ",
 360         "info attr ",
 361         "info dataset ",
 362         "info capped-memory",
 363         "info dedicated-cpu",
 364         "info capped-cpu",

 365         "info zonename",
 366         "info zonepath",
 367         "info autoboot",
 368         "info pool",
 369         "info limitpriv",
 370         "info bootargs",
 371         "info brand",
 372         "info scheduling-class",
 373         "info ip-type",
 374         "info max-lwps",
 375         "info max-shm-memory",
 376         "info max-shm-ids",
 377         "info max-msg-ids",
 378         "info max-sem-ids",
 379         "info cpu-shares",
 380         "info hostid",
 381         "info admin",
 382         "info fs-allowed",
 383         "info max-processes",
 384         NULL


 487         "set physical=",
 488         "set swap=",
 489         "set locked=",
 490         "clear physical",
 491         "clear swap",
 492         "clear locked",
 493         NULL
 494 };
 495 
 496 static const char *admin_res_scope_cmds[] = {
 497         "cancel",
 498         "end",
 499         "exit",
 500         "help",
 501         "info",
 502         "set user=",
 503         "set auths=",
 504         NULL
 505 };
 506 










 507 struct xif {
 508         struct xif      *xif_next;
 509         char            xif_name[LIFNAMSIZ];
 510         boolean_t       xif_has_address;
 511         boolean_t       xif_has_defrouter;
 512 };
 513 
 514 /* Global variables */
 515 
 516 /* list of network interfaces specified for exclusive IP zone */
 517 struct xif *xif;
 518 
 519 /* set early in main(), never modified thereafter, used all over the place */
 520 static char *execname;
 521 
 522 /* set in main(), used all over the place */
 523 static zone_dochandle_t handle;
 524 
 525 /* used all over the place */
 526 static char zone[ZONENAME_MAX];


 564 static boolean_t global_scope = B_TRUE;
 565 static int resource_scope;      /* should be in the RT_ list from zonecfg.h */
 566 static int end_op = -1;         /* operation on end is either add or modify */
 567 
 568 int num_prop_vals;              /* for grammar */
 569 
 570 /*
 571  * These are for keeping track of resources as they are specified as part of
 572  * the multi-step process.  They should be initialized by add_resource() or
 573  * select_func() and filled in by add_property() or set_func().
 574  */
 575 static struct zone_fstab        old_fstab, in_progress_fstab;
 576 static struct zone_nwiftab      old_nwiftab, in_progress_nwiftab;
 577 static struct zone_devtab       old_devtab, in_progress_devtab;
 578 static struct zone_rctltab      old_rctltab, in_progress_rctltab;
 579 static struct zone_attrtab      old_attrtab, in_progress_attrtab;
 580 static struct zone_dstab        old_dstab, in_progress_dstab;
 581 static struct zone_psettab      old_psettab, in_progress_psettab;
 582 static struct zone_mcaptab      old_mcaptab, in_progress_mcaptab;
 583 static struct zone_admintab     old_admintab, in_progress_admintab;

 584 
 585 static GetLine *gl;     /* The gl_get_line() resource object */
 586 
 587 static void bytes_to_units(char *str, char *buf, int bufsize);
 588 
 589 /* Functions begin here */
 590 
 591 static boolean_t
 592 initial_match(const char *line1, const char *line2, int word_end)
 593 {
 594         if (word_end <= 0)
 595                 return (B_TRUE);
 596         return (strncmp(line1, line2, word_end) == 0);
 597 }
 598 
 599 static int
 600 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
 601     int word_end)
 602 {
 603         int i, err;


 641         case RT_FS:
 642                 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
 643         case RT_NET:
 644                 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
 645         case RT_DEVICE:
 646                 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
 647         case RT_RCTL:
 648                 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
 649         case RT_ATTR:
 650                 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
 651         case RT_DATASET:
 652                 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
 653         case RT_DCPU:
 654                 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
 655         case RT_PCAP:
 656                 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
 657         case RT_MCAP:
 658                 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
 659         case RT_ADMIN:
 660                 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));




 661         }
 662         return (0);
 663 }
 664 
 665 /*
 666  * For the main CMD_func() functions below, several of them call getopt()
 667  * then check optind against argc to make sure an extra parameter was not
 668  * passed in.  The reason this is not caught in the grammar is that the
 669  * grammar just checks for a miscellaneous TOKEN, which is *expected* to
 670  * be "-F" (for example), but could be anything.  So (for example) this
 671  * check will prevent "create bogus".
 672  */
 673 
 674 cmd_t *
 675 alloc_cmd(void)
 676 {
 677         return (calloc(1, sizeof (cmd_t)));
 678 }
 679 
 680 void


 956         if ((pathstr = getenv("PATH")) == NULL) {
 957                 if (geteuid() == 0 || getuid() == 0)
 958                         pathstr = "/usr/sbin:/usr/bin";
 959                 else
 960                         pathstr = "/usr/bin:";
 961         }
 962         cp = strchr(name, '/') ? (const char *) "" : pathstr;
 963 
 964         do {
 965                 cp = exec_cat(cp, name, fname);
 966                 if (stat(fname, &stat_buf) != -1) {
 967                         /* successful find of the file */
 968                         return (0);
 969                 }
 970         } while (cp != NULL);
 971 
 972         return (-1);
 973 }
 974 
 975 static FILE *
 976 pager_open(void) {

 977         FILE *newfp;
 978         char *pager, *space;
 979 
 980         pager = getenv("PAGER");
 981         if (pager == NULL || *pager == '\0')
 982                 pager = PAGER;
 983 
 984         space = strchr(pager, ' ');
 985         if (space)
 986                 *space = '\0';
 987         if (path_find(pager) == 0) {
 988                 if (space)
 989                         *space = ' ';
 990                 if ((newfp = popen(pager, "w")) == NULL)
 991                         zerr(gettext("PAGER open failed (%s)."),
 992                             strerror(errno));
 993                 return (newfp);
 994         } else {
 995                 zerr(gettext("PAGER %s does not exist (%s)."),
 996                     pager, strerror(errno));
 997         }
 998         return (NULL);
 999 }
1000 
1001 static void
1002 pager_close(FILE *fp) {

1003         int status;
1004 
1005         status = pclose(fp);
1006         if (status == -1)
1007                 zerr(gettext("PAGER close failed (%s)."),
1008                     strerror(errno));
1009 }
1010 
1011 /*
1012  * Called with verbose TRUE when help is explicitly requested, FALSE for
1013  * unexpected errors.
1014  */
1015 
1016 void
1017 usage(boolean_t verbose, uint_t flags)
1018 {
1019         FILE *fp = verbose ? stdout : stderr;
1020         FILE *newfp;
1021         boolean_t need_to_close = B_FALSE;
1022         int i;


1210                             pt_to_str(PT_SWAP),
1211                             gettext("<qualified unsigned decimal>"));
1212                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1213                             pt_to_str(PT_LOCKED),
1214                             gettext("<qualified unsigned decimal>"));
1215                         break;
1216                 case RT_ADMIN:
1217                         (void) fprintf(fp, gettext("The '%s' resource scope is "
1218                             "used to delegate specific zone management\n"
1219                             "rights to users and roles. These rights are "
1220                             "only applicable to this zone.\n"),
1221                             rt_to_str(resource_scope));
1222                         (void) fprintf(fp, gettext("Valid commands:\n"));
1223                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1224                             pt_to_str(PT_USER),
1225                             gettext("<single user or role name>"));
1226                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1227                             pt_to_str(PT_AUTHS),
1228                             gettext("<comma separated list>"));
1229                         break;















1230                 }
1231                 (void) fprintf(fp, gettext("And from any resource scope, you "
1232                     "can:\n"));
1233                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1234                     gettext("(to conclude this operation)"));
1235                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1236                     gettext("(to cancel this operation)"));
1237                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1238                     gettext("(to exit the zonecfg utility)"));
1239         }
1240         if (flags & HELP_USAGE) {
1241                 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1242                     execname, cmd_to_str(CMD_HELP));
1243                 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1244                     execname, gettext("interactive"));
1245                 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1246                 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1247                     execname);
1248         }
1249         if (flags & HELP_SUBCMDS) {


1274                 (void) fprintf(fp,
1275                     gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1276                 (void) fprintf(fp,
1277                     gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1278                 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1279                     "IPv6 address syntax.\n"));
1280                 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1281                 (void) fprintf(fp,
1282                     gettext("<IPv6-prefix-length> := [0-128]\n"));
1283                 (void) fprintf(fp,
1284                     gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1285         }
1286         if (flags & HELP_RESOURCES) {
1287                 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1288                     "%s | %s | %s | %s | %s\n\n",
1289                     gettext("resource type"), rt_to_str(RT_FS),
1290                     rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1291                     rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1292                     rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1293                     rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1294                     rt_to_str(RT_ADMIN));
1295         }
1296         if (flags & HELP_PROPS) {
1297                 (void) fprintf(fp, gettext("For resource type ... there are "
1298                     "property types ...:\n"));
1299                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1300                     pt_to_str(PT_ZONENAME));
1301                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1302                     pt_to_str(PT_ZONEPATH));
1303                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1304                     pt_to_str(PT_BRAND));
1305                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1306                     pt_to_str(PT_AUTOBOOT));
1307                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1308                     pt_to_str(PT_BOOTARGS));
1309                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1310                     pt_to_str(PT_POOL));
1311                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1312                     pt_to_str(PT_LIMITPRIV));
1313                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1314                     pt_to_str(PT_SCHED));


1340                     pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1341                     pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1342                 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1343                     pt_to_str(PT_MATCH));
1344                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1345                     pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1346                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1347                     pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1348                     pt_to_str(PT_VALUE));
1349                 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1350                     pt_to_str(PT_NAME));
1351                 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1352                     pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1353                 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1354                     pt_to_str(PT_NCPUS));
1355                 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1356                     pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1357                     pt_to_str(PT_LOCKED));
1358                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1359                     pt_to_str(PT_USER), pt_to_str(PT_AUTHS));



1360         }
1361         if (need_to_close)
1362                 (void) pager_close(fp);
1363 }
1364 
1365 static void
1366 zone_perror(char *prefix, int err, boolean_t set_saw)
1367 {
1368         zerr("%s: %s", prefix, zonecfg_strerror(err));
1369         if (set_saw)
1370                 saw_error = B_TRUE;
1371 }
1372 
1373 /*
1374  * zone_perror() expects a single string, but for remove and select
1375  * we have both the command and the resource type, so this wrapper
1376  * function serves the same purpose in a slightly different way.
1377  */
1378 
1379 static void


1783                 return;
1784         quote_str = quoteit(prop_id);
1785         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1786             pt_to_str(prop_num), quote_str);
1787         free(quote_str);
1788 }
1789 
1790 void
1791 export_func(cmd_t *cmd)
1792 {
1793         struct zone_nwiftab nwiftab;
1794         struct zone_fstab fstab;
1795         struct zone_devtab devtab;
1796         struct zone_attrtab attrtab;
1797         struct zone_rctltab rctltab;
1798         struct zone_dstab dstab;
1799         struct zone_psettab psettab;
1800         struct zone_mcaptab mcaptab;
1801         struct zone_rctlvaltab *valptr;
1802         struct zone_admintab admintab;

1803         int err, arg;
1804         char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1805         char bootargs[BOOTARGS_MAX];
1806         char sched[MAXNAMELEN];
1807         char brand[MAXNAMELEN];
1808         char hostidp[HW_HOSTID_LEN];
1809         char fsallowedp[ZONE_FS_ALLOWED_MAX];
1810         char *limitpriv;
1811         FILE *of;
1812         boolean_t autoboot;
1813         zone_iptype_t iptype;
1814         boolean_t need_to_close = B_FALSE;
1815         boolean_t arg_err = B_FALSE;
1816 
1817         assert(cmd != NULL);
1818 
1819         outfile[0] = '\0';
1820         optind = 0;
1821         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1822                 switch (arg) {


2052                         (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
2053                             pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
2054                             psettab.zone_ncpu_max);
2055                 if (psettab.zone_importance[0] != '\0')
2056                         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2057                             pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
2058                 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2059         }
2060 
2061         if ((err = zonecfg_setadminent(handle)) != Z_OK) {
2062                 zone_perror(zone, err, B_FALSE);
2063                 goto done;
2064         }
2065         while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
2066                 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2067                     rt_to_str(RT_ADMIN));
2068                 export_prop(of, PT_USER, admintab.zone_admin_user);
2069                 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
2070                 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2071         }

2072         (void) zonecfg_endadminent(handle);
2073 












2074         /*
2075          * There is nothing to export for pcap since this resource is just
2076          * a container for an rctl alias.
2077          */
2078 
2079 done:
2080         if (need_to_close)
2081                 (void) fclose(of);
2082 }
2083 
2084 void
2085 exit_func(cmd_t *cmd)
2086 {
2087         int arg, answer;
2088         boolean_t arg_err = B_FALSE;
2089 
2090         optind = 0;
2091         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2092                 switch (arg) {
2093                 case '?':


2133 {
2134         if (path[0] != '/') {
2135                 zerr(gettext("%s is not an absolute path."), path);
2136                 return (Z_ERR);
2137         }
2138         /* If path is all slashes, then fail */
2139         if (strspn(path, "/") == strlen(path)) {
2140                 zerr(gettext("/ is not allowed as a %s."),
2141                     pt_to_str(PT_ZONEPATH));
2142                 return (Z_ERR);
2143         }
2144         return (Z_OK);
2145 }
2146 
2147 static void
2148 add_resource(cmd_t *cmd)
2149 {
2150         int type;
2151         struct zone_psettab tmp_psettab;
2152         struct zone_mcaptab tmp_mcaptab;

2153         uint64_t tmp;
2154         uint64_t tmp_mcap;
2155         char pool[MAXNAMELEN];
2156 
2157         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2158                 long_usage(CMD_ADD, B_TRUE);
2159                 goto bad;
2160         }
2161 
2162         switch (type) {
2163         case RT_FS:
2164                 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2165                 return;
2166         case RT_NET:
2167                 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2168                 return;
2169         case RT_DEVICE:
2170                 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2171                 return;
2172         case RT_RCTL:


2244                 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2245                     zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2246                     == Z_OK ||
2247                     zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2248                     &tmp_mcap) == Z_OK) {
2249                         zerr(gettext("The %s resource or a related resource "
2250                             "control already exists."), rt_to_str(RT_MCAP));
2251                         goto bad;
2252                 }
2253                 if (global_zone)
2254                         zerr(gettext("WARNING: Setting a global zone memory "
2255                             "cap too low could deny\nservice "
2256                             "to even the root user; "
2257                             "this could render the system impossible\n"
2258                             "to administer.  Please use caution."));
2259                 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2260                 return;
2261         case RT_ADMIN:
2262                 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2263                 return;








2264         default:
2265                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2266                 long_usage(CMD_ADD, B_TRUE);
2267                 usage(B_FALSE, HELP_RESOURCES);
2268         }
2269 bad:
2270         global_scope = B_TRUE;
2271         end_op = -1;
2272 }
2273 
2274 static void
2275 do_complex_rctl_val(complex_property_ptr_t cp)
2276 {
2277         struct zone_rctlvaltab *rctlvaltab;
2278         complex_property_ptr_t cx;
2279         boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2280             seen_action = B_FALSE;
2281         rctlblk_t *rctlblk;
2282         int err;
2283 


2913                 case PT_USER:
2914                         (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2915                             sizeof (admintab->zone_admin_user));
2916                         break;
2917                 case PT_AUTHS:
2918                         (void) strlcpy(admintab->zone_admin_auths,
2919                             pp->pv_simple, sizeof (admintab->zone_admin_auths));
2920                         break;
2921                 default:
2922                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2923                             Z_NO_PROPERTY_TYPE, B_TRUE);
2924                         return (Z_INSUFFICIENT_SPEC);
2925                 }
2926         }
2927         if (fill_in_only)
2928                 return (Z_OK);
2929         err = zonecfg_lookup_admin(handle, admintab);
2930         return (err);
2931 }
2932 
















































2933 static void
2934 remove_aliased_rctl(int type, char *name)
2935 {
2936         int err;
2937         uint64_t tmp;
2938 
2939         if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
2940                 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2941                     zonecfg_strerror(err));
2942                 saw_error = B_TRUE;
2943                 return;
2944         }
2945         if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
2946                 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2947                     zonecfg_strerror(err));
2948                 saw_error = B_TRUE;
2949         } else {
2950                 need_to_commit = B_TRUE;
2951         }
2952 }


3315                 return;
3316         } else {
3317                 /*
3318                  * unqualified admin removal.
3319                  * remove all admins but prompt if more
3320                  * than one.
3321                  */
3322                 if (!prompt_remove_resource(cmd, "admin"))
3323                         return;
3324 
3325                 if ((err = zonecfg_delete_admins(handle, zone))
3326                     != Z_OK)
3327                         z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3328                             err, B_TRUE);
3329                 else
3330                         need_to_commit = B_TRUE;
3331         }
3332 }
3333 
3334 static void





















3335 remove_resource(cmd_t *cmd)
3336 {
3337         int type;
3338         int arg;
3339         boolean_t arg_err = B_FALSE;
3340 
3341         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3342                 long_usage(CMD_REMOVE, B_TRUE);
3343                 return;
3344         }
3345 
3346         optind = 0;
3347         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3348                 switch (arg) {
3349                 case '?':
3350                         longer_usage(CMD_REMOVE);
3351                         arg_err = B_TRUE;
3352                         break;
3353                 case 'F':
3354                         break;


3378                 remove_rctl(cmd);
3379                 return;
3380         case RT_ATTR:
3381                 remove_attr(cmd);
3382                 return;
3383         case RT_DATASET:
3384                 remove_dataset(cmd);
3385                 return;
3386         case RT_DCPU:
3387                 remove_pset();
3388                 return;
3389         case RT_PCAP:
3390                 remove_pcap();
3391                 return;
3392         case RT_MCAP:
3393                 remove_mcap();
3394                 return;
3395         case RT_ADMIN:
3396                 remove_admin(cmd);
3397                 return;



3398         default:
3399                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3400                 long_usage(CMD_REMOVE, B_TRUE);
3401                 usage(B_FALSE, HELP_RESOURCES);
3402                 return;
3403         }
3404 }
3405 
3406 static void
3407 remove_property(cmd_t *cmd)
3408 {
3409         char *prop_id;
3410         int err, res_type, prop_type;
3411         property_value_ptr_t pp;
3412         struct zone_rctlvaltab *rctlvaltab;
3413         complex_property_ptr_t cx;
3414 
3415         res_type = resource_scope;
3416         prop_type = cmd->cmd_prop_name[0];
3417         if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {


3590                 if (prop_type == PT_IMPORTANCE) {
3591                         in_progress_psettab.zone_importance[0] = '\0';
3592                         need_to_commit = B_TRUE;
3593                         return;
3594                 }
3595                 break;
3596         case RT_MCAP:
3597                 switch (prop_type) {
3598                 case PT_PHYSICAL:
3599                         in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3600                         need_to_commit = B_TRUE;
3601                         return;
3602                 case PT_SWAP:
3603                         remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3604                         return;
3605                 case PT_LOCKED:
3606                         remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3607                         return;
3608                 }
3609                 break;
















3610         default:
3611                 break;
3612         }
3613 
3614         zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3615 }
3616 
3617 static void
3618 clear_global(cmd_t *cmd)
3619 {
3620         int err, type;
3621 
3622         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3623                 long_usage(CMD_CLEAR, B_TRUE);
3624                 return;
3625         }
3626 
3627         if (initialize(B_TRUE) != Z_OK)
3628                 return;
3629 


3843                             B_TRUE);
3844                         global_scope = B_TRUE;
3845                 }
3846                 if (res == Z_OK)
3847                         bcopy(&old_mcaptab, &in_progress_mcaptab,
3848                             sizeof (struct zone_mcaptab));
3849                 else
3850                         bzero(&in_progress_mcaptab,
3851                             sizeof (in_progress_mcaptab));
3852                 return;
3853         case RT_ADMIN:
3854                 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
3855                     != Z_OK) {
3856                         z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
3857                             B_TRUE);
3858                         global_scope = B_TRUE;
3859                 }
3860                 bcopy(&old_admintab, &in_progress_admintab,
3861                     sizeof (struct zone_admintab));
3862                 return;










3863         default:
3864                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3865                 long_usage(CMD_SELECT, B_TRUE);
3866                 usage(B_FALSE, HELP_RESOURCES);
3867                 return;
3868         }
3869 }
3870 
3871 /*
3872  * Network "addresses" can be one of the following forms:
3873  *      <IPv4 address>
3874  *      <IPv4 address>/<prefix length>
3875  *      <IPv6 address>/<prefix length>
3876  *      <host name>
3877  *      <host name>/<prefix length>
3878  * In other words, the "/" followed by a prefix length is allowed but not
3879  * required for IPv4 addresses and host names, and required for IPv6 addresses.
3880  * If a prefix length is given, it must be in the allowable range: 0 to 32 for
3881  * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
3882  * Host names must start with an alpha-numeric character, and all subsequent


4759                 return;
4760         case RT_ADMIN:
4761                 switch (prop_type) {
4762                 case PT_USER:
4763                         (void) strlcpy(in_progress_admintab.zone_admin_user,
4764                             prop_id,
4765                             sizeof (in_progress_admintab.zone_admin_user));
4766                         return;
4767                 case PT_AUTHS:
4768                         (void) strlcpy(in_progress_admintab.zone_admin_auths,
4769                             prop_id,
4770                             sizeof (in_progress_admintab.zone_admin_auths));
4771                         return;
4772                 default:
4773                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4774                             B_TRUE);
4775                         long_usage(CMD_SET, B_TRUE);
4776                         usage(B_FALSE, HELP_PROPS);
4777                         return;
4778                 }























4779         default:
4780                 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4781                 long_usage(CMD_SET, B_TRUE);
4782                 usage(B_FALSE, HELP_RESOURCES);
4783                 return;
4784         }
4785 }
4786 
4787 static void
4788 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4789 {
4790         char *qstr;
4791 
4792         if (*pval != '\0') {
4793                 qstr = quoteit(pval);
4794                 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4795                         (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4796                             qstr);
4797                 else
4798                         (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);


5373 
5374         bzero(&lookup, sizeof (lookup));
5375         res1 = zonecfg_getmcapent(handle, &lookup);
5376         res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5377         res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5378             &locked_limit);
5379 
5380         if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5381                 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5382 }
5383 
5384 static void
5385 output_auth(FILE *fp, struct zone_admintab *admintab)
5386 {
5387         (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5388         output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5389         output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5390 }
5391 
5392 static void









5393 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5394 {
5395         struct zone_admintab lookup, user;
5396         boolean_t output = B_FALSE;
5397         int err;
5398 
5399         if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5400                 zone_perror(zone, err, B_TRUE);
5401                 return;
5402         }
5403         while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5404                 if (cmd->cmd_prop_nv_pairs == 0) {
5405                         output_auth(fp, &lookup);
5406                         continue;
5407                 }
5408                 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5409                         continue;
5410                 if (strlen(user.zone_admin_user) > 0 &&
5411                     strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5412                         continue;       /* no match */
5413                 output_auth(fp, &lookup);
5414                 output = B_TRUE;
5415         }
5416         (void) zonecfg_endadminent(handle);
5417         /*
5418          * If a property n/v pair was specified, warn the user if there was
5419          * nothing to output.
5420          */
5421         if (!output && cmd->cmd_prop_nv_pairs > 0)
5422                 (void) printf(gettext("No such %s resource.\n"),
5423                     rt_to_str(RT_ADMIN));
5424 }
5425 














5426 void
5427 info_func(cmd_t *cmd)
5428 {
5429         FILE *fp = stdout;
5430         boolean_t need_to_close = B_FALSE;
5431         int type;
5432         int res1, res2;
5433         uint64_t swap_limit;
5434         uint64_t locked_limit;
5435 
5436         assert(cmd != NULL);
5437 
5438         if (initialize(B_TRUE) != Z_OK)
5439                 return;
5440 
5441         /* don't page error output */
5442         if (interactive_mode) {
5443                 if ((fp = pager_open()) != NULL)
5444                         need_to_close = B_TRUE;
5445                 else


5468                 case RT_DATASET:
5469                         output_ds(fp, &in_progress_dstab);
5470                         break;
5471                 case RT_DCPU:
5472                         output_pset(fp, &in_progress_psettab);
5473                         break;
5474                 case RT_PCAP:
5475                         output_pcap(fp);
5476                         break;
5477                 case RT_MCAP:
5478                         res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5479                             &swap_limit);
5480                         res2 = zonecfg_get_aliased_rctl(handle,
5481                             ALIAS_MAXLOCKEDMEM, &locked_limit);
5482                         output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5483                             res2, locked_limit);
5484                         break;
5485                 case RT_ADMIN:
5486                         output_auth(fp, &in_progress_admintab);
5487                         break;



5488                 }
5489                 goto cleanup;
5490         }
5491 
5492         type = cmd->cmd_res_type;
5493 
5494         if (gz_invalid_rt_property(type)) {
5495                 zerr(gettext("%s is not a valid property for the global zone."),
5496                     rt_to_str(type));
5497                 goto cleanup;
5498         }
5499 
5500         if (gz_invalid_resource(type)) {
5501                 zerr(gettext("%s is not a valid resource for the global zone."),
5502                     rt_to_str(type));
5503                 goto cleanup;
5504         }
5505 
5506         switch (cmd->cmd_res_type) {
5507         case RT_UNKNOWN:


5524                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5525                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5526                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5527                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5528                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5529                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5530                 if (!global_zone) {
5531                         info_fs(handle, fp, cmd);
5532                         info_net(handle, fp, cmd);
5533                         info_dev(handle, fp, cmd);
5534                 }
5535                 info_pset(handle, fp);
5536                 info_pcap(fp);
5537                 info_mcap(handle, fp);
5538                 if (!global_zone) {
5539                         info_attr(handle, fp, cmd);
5540                         info_ds(handle, fp, cmd);
5541                         info_auth(handle, fp, cmd);
5542                 }
5543                 info_rctl(handle, fp, cmd);

5544                 break;
5545         case RT_ZONENAME:
5546                 info_zonename(handle, fp);
5547                 break;
5548         case RT_ZONEPATH:
5549                 info_zonepath(handle, fp);
5550                 break;
5551         case RT_BRAND:
5552                 info_brand(handle, fp);
5553                 break;
5554         case RT_AUTOBOOT:
5555                 info_autoboot(handle, fp);
5556                 break;
5557         case RT_POOL:
5558                 info_pool(handle, fp);
5559                 break;
5560         case RT_LIMITPRIV:
5561                 info_limitpriv(handle, fp);
5562                 break;
5563         case RT_BOOTARGS:


5609                 info_ds(handle, fp, cmd);
5610                 break;
5611         case RT_DCPU:
5612                 info_pset(handle, fp);
5613                 break;
5614         case RT_PCAP:
5615                 info_pcap(fp);
5616                 break;
5617         case RT_MCAP:
5618                 info_mcap(handle, fp);
5619                 break;
5620         case RT_HOSTID:
5621                 info_hostid(handle, fp);
5622                 break;
5623         case RT_ADMIN:
5624                 info_auth(handle, fp, cmd);
5625                 break;
5626         case RT_FS_ALLOWED:
5627                 info_fs_allowed(handle, fp);
5628                 break;



5629         default:
5630                 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5631                     B_TRUE);
5632         }
5633 
5634 cleanup:
5635         if (need_to_close)
5636                 (void) pager_close(fp);
5637 }
5638 
5639 /*
5640  * Helper function for verify-- checks that a required string property
5641  * exists.
5642  */
5643 static void
5644 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5645 {
5646         if (strlen(attr) == 0) {
5647                 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5648                     pt_to_str(pt));


5760                                 tmp->xif_has_defrouter = B_TRUE;
5761                         return (B_TRUE);
5762                 }
5763         }
5764 
5765         tmp = malloc(sizeof (*tmp));
5766         if (tmp == NULL) {
5767                 zerr(gettext("memory allocation failed for %s"),
5768                     nwif->zone_nwif_physical);
5769                 return (B_FALSE);
5770         }
5771         strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5772             sizeof (tmp->xif_name));
5773         tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5774         tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5775         tmp->xif_next = xif;
5776         xif = tmp;
5777         return (B_TRUE);
5778 }
5779 


















































































5780 /*
5781  * See the DTD for which attributes are required for which resources.
5782  *
5783  * This function can be called by commit_func(), which needs to save things,
5784  * in addition to the general call from parse_and_run(), which doesn't need
5785  * things saved.  Since the parameters are standardized, we distinguish by
5786  * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
5787  * that a save is needed.
5788  */
5789 void
5790 verify_func(cmd_t *cmd)
5791 {
5792         struct zone_nwiftab nwiftab;
5793         struct zone_fstab fstab;
5794         struct zone_attrtab attrtab;
5795         struct zone_rctltab rctltab;
5796         struct zone_dstab dstab;
5797         struct zone_psettab psettab;
5798         struct zone_admintab admintab;

5799         char zonepath[MAXPATHLEN];
5800         char sched[MAXNAMELEN];
5801         char brand[MAXNAMELEN];
5802         char hostidp[HW_HOSTID_LEN];
5803         char fsallowedp[ZONE_FS_ALLOWED_MAX];
5804         priv_set_t *privs;
5805         char *privname = NULL;
5806         int err, ret_val = Z_OK, arg;
5807         int pset_res;
5808         boolean_t save = B_FALSE;
5809         boolean_t arg_err = B_FALSE;
5810         zone_iptype_t iptype;
5811         boolean_t has_cpu_shares = B_FALSE;
5812         boolean_t has_cpu_cap = B_FALSE;
5813         struct xif *tmp;
5814 
5815         optind = 0;
5816         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
5817                 switch (arg) {
5818                 case '?':


6075         }
6076         while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6077                 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6078                     PT_USER, &ret_val);
6079                 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6080                     PT_AUTHS, &ret_val);
6081                 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6082                     == NULL)) {
6083                         zerr(gettext("%s %s is not a valid username"),
6084                             pt_to_str(PT_USER),
6085                             admintab.zone_admin_user);
6086                         ret_val = Z_BAD_PROPERTY;
6087                 }
6088                 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6089                     admintab.zone_admin_auths, zone))) {
6090                         ret_val = Z_BAD_PROPERTY;
6091                 }
6092         }
6093         (void) zonecfg_endadminent(handle);
6094 














6095         if (!global_scope) {
6096                 zerr(gettext("resource specification incomplete"));
6097                 saw_error = B_TRUE;
6098                 if (ret_val == Z_OK)
6099                         ret_val = Z_INSUFFICIENT_SPEC;
6100         }
6101 
6102         if (save) {
6103                 if (ret_val == Z_OK) {
6104                         if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6105                                 need_to_commit = B_FALSE;
6106                                 (void) strlcpy(revert_zone, zone,
6107                                     sizeof (revert_zone));
6108                         }
6109                 } else {
6110                         zerr(gettext("Zone %s failed to verify"), zone);
6111                 }
6112         }
6113         if (ret_val != Z_OK)
6114                 zone_perror(zone, ret_val, B_TRUE);


6664                             sizeof (tmp_admintab.zone_admin_user));
6665                         err = zonecfg_lookup_admin(
6666                             handle, &tmp_admintab);
6667                         if (err == Z_OK) {
6668                                 zerr(gettext("A %s resource "
6669                                     "with the %s '%s' already exists."),
6670                                     rt_to_str(RT_ADMIN),
6671                                     pt_to_str(PT_USER),
6672                                     in_progress_admintab.zone_admin_user);
6673                                 saw_error = B_TRUE;
6674                                 return;
6675                         }
6676                         err = zonecfg_add_admin(handle,
6677                             &in_progress_admintab, zone);
6678                 } else {
6679                         err = zonecfg_modify_admin(handle,
6680                             &old_admintab, &in_progress_admintab,
6681                             zone);
6682                 }
6683                 break;














6684         default:
6685                 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
6686                     B_TRUE);
6687                 saw_error = B_TRUE;
6688                 return;
6689         }
6690 
6691         if (err != Z_OK) {
6692                 zone_perror(zone, err, B_TRUE);
6693         } else {
6694                 need_to_commit = B_TRUE;
6695                 global_scope = B_TRUE;
6696                 end_op = -1;
6697         }
6698 }
6699 
6700 void
6701 commit_func(cmd_t *cmd)
6702 {
6703         int arg;




  36  * The resource/property data structures are inserted into a command
  37  * structure (see zonecfg.h), which also keeps track of command names,
  38  * miscellaneous arguments, and function handlers.  The grammar selects
  39  * the appropriate function handler, each of which takes a pointer to a
  40  * command structure as its sole argument, and invokes it.  The grammar
  41  * itself is "entered" (a la the Matrix) by yyparse(), which is called
  42  * from read_input(), our main driving function.  That in turn is called
  43  * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
  44  * of which is called from main() depending on how the program was invoked.
  45  *
  46  * The rest of this module consists of the various function handlers and
  47  * their helper functions.  Some of these functions, particularly the
  48  * X_to_str() functions, which maps command, resource and property numbers
  49  * to strings, are used quite liberally, as doing so results in a better
  50  * program w/rt I18N, reducing the need for translation notes.
  51  */
  52 
  53 #include <sys/mntent.h>
  54 #include <sys/varargs.h>
  55 #include <sys/sysmacros.h>
  56 #include <sys/secflags.h>
  57 
  58 #include <errno.h>
  59 #include <fcntl.h>
  60 #include <strings.h>
  61 #include <unistd.h>
  62 #include <ctype.h>
  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>


 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         "security-flags",
 192         NULL
 193 };
 194 
 195 /* These *must* match the order of the PT_ define's from zonecfg.h */
 196 char *prop_types[] = {
 197         "unknown",
 198         "zonename",
 199         "zonepath",
 200         "autoboot",
 201         "pool",
 202         "dir",
 203         "special",
 204         "type",
 205         "options",
 206         "address",
 207         "physical",
 208         "name",
 209         "value",
 210         "match",
 211         "priv",


 219         "importance",
 220         "swap",
 221         "locked",
 222         ALIAS_SHARES,
 223         ALIAS_MAXLWPS,
 224         ALIAS_MAXSHMMEM,
 225         ALIAS_MAXSHMIDS,
 226         ALIAS_MAXMSGIDS,
 227         ALIAS_MAXSEMIDS,
 228         ALIAS_MAXLOCKEDMEM,
 229         ALIAS_MAXSWAP,
 230         "scheduling-class",
 231         "ip-type",
 232         "defrouter",
 233         "hostid",
 234         "user",
 235         "auths",
 236         "fs-allowed",
 237         ALIAS_MAXPROCS,
 238         "allowed-address",
 239         "default",
 240         "lower",
 241         "upper",
 242         NULL
 243 };
 244 
 245 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
 246 static char *prop_val_types[] = {
 247         "simple",
 248         "complex",
 249         "list",
 250 };
 251 
 252 /*
 253  * The various _cmds[] lists below are for command tab-completion.
 254  */
 255 
 256 /*
 257  * remove has a space afterwards because it has qualifiers; the other commands
 258  * that have qualifiers (add, select, etc.) don't need a space here because
 259  * they have their own _cmds[] lists below.
 260  */
 261 static const char *global_scope_cmds[] = {


 270         "info",
 271         "remove ",
 272         "revert",
 273         "select",
 274         "set",
 275         "verify",
 276         NULL
 277 };
 278 
 279 static const char *add_cmds[] = {
 280         "add fs",
 281         "add net",
 282         "add device",
 283         "add rctl",
 284         "add attr",
 285         "add dataset",
 286         "add dedicated-cpu",
 287         "add capped-cpu",
 288         "add capped-memory",
 289         "add admin",
 290         "add security-flags",
 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         "remove security-flags",
 323         NULL
 324 };
 325 
 326 static const char *select_cmds[] = {
 327         "select fs ",
 328         "select net ",
 329         "select device ",
 330         "select rctl ",
 331         "select attr ",
 332         "select dataset ",
 333         "select dedicated-cpu",
 334         "select capped-cpu",
 335         "select capped-memory",
 336         "select admin",
 337         "select security-flags",
 338         NULL
 339 };
 340 
 341 static const char *set_cmds[] = {
 342         "set zonename=",
 343         "set zonepath=",
 344         "set brand=",
 345         "set autoboot=",
 346         "set pool=",
 347         "set limitpriv=",
 348         "set bootargs=",
 349         "set scheduling-class=",
 350         "set ip-type=",
 351         "set " ALIAS_MAXLWPS "=",
 352         "set " ALIAS_MAXSHMMEM "=",
 353         "set " ALIAS_MAXSHMIDS "=",
 354         "set " ALIAS_MAXMSGIDS "=",
 355         "set " ALIAS_MAXSEMIDS "=",
 356         "set " ALIAS_SHARES "=",
 357         "set hostid=",
 358         "set fs-allowed=",
 359         "set " ALIAS_MAXPROCS "=",
 360         NULL
 361 };
 362 
 363 static const char *info_cmds[] = {
 364         "info fs ",
 365         "info net ",
 366         "info device ",
 367         "info rctl ",
 368         "info attr ",
 369         "info dataset ",
 370         "info capped-memory",
 371         "info dedicated-cpu",
 372         "info capped-cpu",
 373         "info security-flags",
 374         "info zonename",
 375         "info zonepath",
 376         "info autoboot",
 377         "info pool",
 378         "info limitpriv",
 379         "info bootargs",
 380         "info brand",
 381         "info scheduling-class",
 382         "info ip-type",
 383         "info max-lwps",
 384         "info max-shm-memory",
 385         "info max-shm-ids",
 386         "info max-msg-ids",
 387         "info max-sem-ids",
 388         "info cpu-shares",
 389         "info hostid",
 390         "info admin",
 391         "info fs-allowed",
 392         "info max-processes",
 393         NULL


 496         "set physical=",
 497         "set swap=",
 498         "set locked=",
 499         "clear physical",
 500         "clear swap",
 501         "clear locked",
 502         NULL
 503 };
 504 
 505 static const char *admin_res_scope_cmds[] = {
 506         "cancel",
 507         "end",
 508         "exit",
 509         "help",
 510         "info",
 511         "set user=",
 512         "set auths=",
 513         NULL
 514 };
 515 
 516 static const char *secflags_res_scope_cmds[] = {
 517         "cancel",
 518         "end",
 519         "exit",
 520         "set default=",
 521         "set lower=",
 522         "set upper=",
 523         NULL
 524 };
 525 
 526 struct xif {
 527         struct xif      *xif_next;
 528         char            xif_name[LIFNAMSIZ];
 529         boolean_t       xif_has_address;
 530         boolean_t       xif_has_defrouter;
 531 };
 532 
 533 /* Global variables */
 534 
 535 /* list of network interfaces specified for exclusive IP zone */
 536 struct xif *xif;
 537 
 538 /* set early in main(), never modified thereafter, used all over the place */
 539 static char *execname;
 540 
 541 /* set in main(), used all over the place */
 542 static zone_dochandle_t handle;
 543 
 544 /* used all over the place */
 545 static char zone[ZONENAME_MAX];


 583 static boolean_t global_scope = B_TRUE;
 584 static int resource_scope;      /* should be in the RT_ list from zonecfg.h */
 585 static int end_op = -1;         /* operation on end is either add or modify */
 586 
 587 int num_prop_vals;              /* for grammar */
 588 
 589 /*
 590  * These are for keeping track of resources as they are specified as part of
 591  * the multi-step process.  They should be initialized by add_resource() or
 592  * select_func() and filled in by add_property() or set_func().
 593  */
 594 static struct zone_fstab        old_fstab, in_progress_fstab;
 595 static struct zone_nwiftab      old_nwiftab, in_progress_nwiftab;
 596 static struct zone_devtab       old_devtab, in_progress_devtab;
 597 static struct zone_rctltab      old_rctltab, in_progress_rctltab;
 598 static struct zone_attrtab      old_attrtab, in_progress_attrtab;
 599 static struct zone_dstab        old_dstab, in_progress_dstab;
 600 static struct zone_psettab      old_psettab, in_progress_psettab;
 601 static struct zone_mcaptab      old_mcaptab, in_progress_mcaptab;
 602 static struct zone_admintab     old_admintab, in_progress_admintab;
 603 static struct zone_secflagstab  old_secflagstab, in_progress_secflagstab;
 604 
 605 static GetLine *gl;     /* The gl_get_line() resource object */
 606 
 607 static void bytes_to_units(char *str, char *buf, int bufsize);
 608 
 609 /* Functions begin here */
 610 
 611 static boolean_t
 612 initial_match(const char *line1, const char *line2, int word_end)
 613 {
 614         if (word_end <= 0)
 615                 return (B_TRUE);
 616         return (strncmp(line1, line2, word_end) == 0);
 617 }
 618 
 619 static int
 620 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
 621     int word_end)
 622 {
 623         int i, err;


 661         case RT_FS:
 662                 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
 663         case RT_NET:
 664                 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
 665         case RT_DEVICE:
 666                 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
 667         case RT_RCTL:
 668                 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
 669         case RT_ATTR:
 670                 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
 671         case RT_DATASET:
 672                 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
 673         case RT_DCPU:
 674                 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
 675         case RT_PCAP:
 676                 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
 677         case RT_MCAP:
 678                 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
 679         case RT_ADMIN:
 680                 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
 681         case RT_SECFLAGS:
 682                 return (add_stuff(cpl, line, secflags_res_scope_cmds,
 683                     word_end));
 684 
 685         }
 686         return (0);
 687 }
 688 
 689 /*
 690  * For the main CMD_func() functions below, several of them call getopt()
 691  * then check optind against argc to make sure an extra parameter was not
 692  * passed in.  The reason this is not caught in the grammar is that the
 693  * grammar just checks for a miscellaneous TOKEN, which is *expected* to
 694  * be "-F" (for example), but could be anything.  So (for example) this
 695  * check will prevent "create bogus".
 696  */
 697 
 698 cmd_t *
 699 alloc_cmd(void)
 700 {
 701         return (calloc(1, sizeof (cmd_t)));
 702 }
 703 
 704 void


 980         if ((pathstr = getenv("PATH")) == NULL) {
 981                 if (geteuid() == 0 || getuid() == 0)
 982                         pathstr = "/usr/sbin:/usr/bin";
 983                 else
 984                         pathstr = "/usr/bin:";
 985         }
 986         cp = strchr(name, '/') ? (const char *) "" : pathstr;
 987 
 988         do {
 989                 cp = exec_cat(cp, name, fname);
 990                 if (stat(fname, &stat_buf) != -1) {
 991                         /* successful find of the file */
 992                         return (0);
 993                 }
 994         } while (cp != NULL);
 995 
 996         return (-1);
 997 }
 998 
 999 static FILE *
1000 pager_open(void)
1001 {
1002         FILE *newfp;
1003         char *pager, *space;
1004 
1005         pager = getenv("PAGER");
1006         if (pager == NULL || *pager == '\0')
1007                 pager = PAGER;
1008 
1009         space = strchr(pager, ' ');
1010         if (space)
1011                 *space = '\0';
1012         if (path_find(pager) == 0) {
1013                 if (space)
1014                         *space = ' ';
1015                 if ((newfp = popen(pager, "w")) == NULL)
1016                         zerr(gettext("PAGER open failed (%s)."),
1017                             strerror(errno));
1018                 return (newfp);
1019         } else {
1020                 zerr(gettext("PAGER %s does not exist (%s)."),
1021                     pager, strerror(errno));
1022         }
1023         return (NULL);
1024 }
1025 
1026 static void
1027 pager_close(FILE *fp)
1028 {
1029         int status;
1030 
1031         status = pclose(fp);
1032         if (status == -1)
1033                 zerr(gettext("PAGER close failed (%s)."),
1034                     strerror(errno));
1035 }
1036 
1037 /*
1038  * Called with verbose TRUE when help is explicitly requested, FALSE for
1039  * unexpected errors.
1040  */
1041 
1042 void
1043 usage(boolean_t verbose, uint_t flags)
1044 {
1045         FILE *fp = verbose ? stdout : stderr;
1046         FILE *newfp;
1047         boolean_t need_to_close = B_FALSE;
1048         int i;


1236                             pt_to_str(PT_SWAP),
1237                             gettext("<qualified unsigned decimal>"));
1238                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1239                             pt_to_str(PT_LOCKED),
1240                             gettext("<qualified unsigned decimal>"));
1241                         break;
1242                 case RT_ADMIN:
1243                         (void) fprintf(fp, gettext("The '%s' resource scope is "
1244                             "used to delegate specific zone management\n"
1245                             "rights to users and roles. These rights are "
1246                             "only applicable to this zone.\n"),
1247                             rt_to_str(resource_scope));
1248                         (void) fprintf(fp, gettext("Valid commands:\n"));
1249                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1250                             pt_to_str(PT_USER),
1251                             gettext("<single user or role name>"));
1252                         (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1253                             pt_to_str(PT_AUTHS),
1254                             gettext("<comma separated list>"));
1255                         break;
1256                 case RT_SECFLAGS:
1257                         (void) fprintf(fp, gettext("The '%s' resource scope is "
1258                             "used to specify the default security-flags\n"
1259                             "of this zone, and their upper and lower bound.\n"),
1260                             rt_to_str(resource_scope));
1261                         (void) fprintf(fp, "\t%s %s=%s\n",
1262                             cmd_to_str(CMD_SET), pt_to_str(PT_DEFAULT),
1263                             gettext("<security flags>"));
1264                         (void) fprintf(fp, "\t%s %s=%s\n",
1265                             cmd_to_str(CMD_SET), pt_to_str(PT_LOWER),
1266                             gettext("<security flags>"));
1267                         (void) fprintf(fp, "\t%s %s=%s\n",
1268                             cmd_to_str(CMD_SET), pt_to_str(PT_UPPER),
1269                             gettext("<security flags>"));
1270                         break;
1271                 }
1272                 (void) fprintf(fp, gettext("And from any resource scope, you "
1273                     "can:\n"));
1274                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1275                     gettext("(to conclude this operation)"));
1276                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1277                     gettext("(to cancel this operation)"));
1278                 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1279                     gettext("(to exit the zonecfg utility)"));
1280         }
1281         if (flags & HELP_USAGE) {
1282                 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1283                     execname, cmd_to_str(CMD_HELP));
1284                 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1285                     execname, gettext("interactive"));
1286                 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1287                 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1288                     execname);
1289         }
1290         if (flags & HELP_SUBCMDS) {


1315                 (void) fprintf(fp,
1316                     gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1317                 (void) fprintf(fp,
1318                     gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1319                 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1320                     "IPv6 address syntax.\n"));
1321                 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1322                 (void) fprintf(fp,
1323                     gettext("<IPv6-prefix-length> := [0-128]\n"));
1324                 (void) fprintf(fp,
1325                     gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1326         }
1327         if (flags & HELP_RESOURCES) {
1328                 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1329                     "%s | %s | %s | %s | %s\n\n",
1330                     gettext("resource type"), rt_to_str(RT_FS),
1331                     rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1332                     rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1333                     rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1334                     rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1335                     rt_to_str(RT_ADMIN), rt_to_str(RT_SECFLAGS));
1336         }
1337         if (flags & HELP_PROPS) {
1338                 (void) fprintf(fp, gettext("For resource type ... there are "
1339                     "property types ...:\n"));
1340                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1341                     pt_to_str(PT_ZONENAME));
1342                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1343                     pt_to_str(PT_ZONEPATH));
1344                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1345                     pt_to_str(PT_BRAND));
1346                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1347                     pt_to_str(PT_AUTOBOOT));
1348                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1349                     pt_to_str(PT_BOOTARGS));
1350                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1351                     pt_to_str(PT_POOL));
1352                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1353                     pt_to_str(PT_LIMITPRIV));
1354                 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1355                     pt_to_str(PT_SCHED));


1381                     pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1382                     pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1383                 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1384                     pt_to_str(PT_MATCH));
1385                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1386                     pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1387                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1388                     pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1389                     pt_to_str(PT_VALUE));
1390                 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1391                     pt_to_str(PT_NAME));
1392                 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
1393                     pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1394                 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1395                     pt_to_str(PT_NCPUS));
1396                 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1397                     pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1398                     pt_to_str(PT_LOCKED));
1399                 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1400                     pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1401                 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n",
1402                     rt_to_str(RT_SECFLAGS), pt_to_str(PT_DEFAULT),
1403                     pt_to_str(PT_LOWER), pt_to_str(PT_UPPER));
1404         }
1405         if (need_to_close)
1406                 (void) pager_close(fp);
1407 }
1408 
1409 static void
1410 zone_perror(char *prefix, int err, boolean_t set_saw)
1411 {
1412         zerr("%s: %s", prefix, zonecfg_strerror(err));
1413         if (set_saw)
1414                 saw_error = B_TRUE;
1415 }
1416 
1417 /*
1418  * zone_perror() expects a single string, but for remove and select
1419  * we have both the command and the resource type, so this wrapper
1420  * function serves the same purpose in a slightly different way.
1421  */
1422 
1423 static void


1827                 return;
1828         quote_str = quoteit(prop_id);
1829         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1830             pt_to_str(prop_num), quote_str);
1831         free(quote_str);
1832 }
1833 
1834 void
1835 export_func(cmd_t *cmd)
1836 {
1837         struct zone_nwiftab nwiftab;
1838         struct zone_fstab fstab;
1839         struct zone_devtab devtab;
1840         struct zone_attrtab attrtab;
1841         struct zone_rctltab rctltab;
1842         struct zone_dstab dstab;
1843         struct zone_psettab psettab;
1844         struct zone_mcaptab mcaptab;
1845         struct zone_rctlvaltab *valptr;
1846         struct zone_admintab admintab;
1847         struct zone_secflagstab secflagstab;
1848         int err, arg;
1849         char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1850         char bootargs[BOOTARGS_MAX];
1851         char sched[MAXNAMELEN];
1852         char brand[MAXNAMELEN];
1853         char hostidp[HW_HOSTID_LEN];
1854         char fsallowedp[ZONE_FS_ALLOWED_MAX];
1855         char *limitpriv;
1856         FILE *of;
1857         boolean_t autoboot;
1858         zone_iptype_t iptype;
1859         boolean_t need_to_close = B_FALSE;
1860         boolean_t arg_err = B_FALSE;
1861 
1862         assert(cmd != NULL);
1863 
1864         outfile[0] = '\0';
1865         optind = 0;
1866         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1867                 switch (arg) {


2097                         (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
2098                             pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
2099                             psettab.zone_ncpu_max);
2100                 if (psettab.zone_importance[0] != '\0')
2101                         (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
2102                             pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
2103                 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2104         }
2105 
2106         if ((err = zonecfg_setadminent(handle)) != Z_OK) {
2107                 zone_perror(zone, err, B_FALSE);
2108                 goto done;
2109         }
2110         while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
2111                 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2112                     rt_to_str(RT_ADMIN));
2113                 export_prop(of, PT_USER, admintab.zone_admin_user);
2114                 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
2115                 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2116         }
2117 
2118         (void) zonecfg_endadminent(handle);
2119 
2120         if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
2121                 zone_perror(zone, err, B_FALSE);
2122                 goto done;
2123         }
2124 
2125         (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2126             rt_to_str(RT_SECFLAGS));
2127         export_prop(of, PT_DEFAULT, secflagstab.zone_secflags_default);
2128         export_prop(of, PT_LOWER, secflagstab.zone_secflags_lower);
2129         export_prop(of, PT_UPPER, secflagstab.zone_secflags_upper);
2130         (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2131 
2132         /*
2133          * There is nothing to export for pcap since this resource is just
2134          * a container for an rctl alias.
2135          */
2136 
2137 done:
2138         if (need_to_close)
2139                 (void) fclose(of);
2140 }
2141 
2142 void
2143 exit_func(cmd_t *cmd)
2144 {
2145         int arg, answer;
2146         boolean_t arg_err = B_FALSE;
2147 
2148         optind = 0;
2149         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2150                 switch (arg) {
2151                 case '?':


2191 {
2192         if (path[0] != '/') {
2193                 zerr(gettext("%s is not an absolute path."), path);
2194                 return (Z_ERR);
2195         }
2196         /* If path is all slashes, then fail */
2197         if (strspn(path, "/") == strlen(path)) {
2198                 zerr(gettext("/ is not allowed as a %s."),
2199                     pt_to_str(PT_ZONEPATH));
2200                 return (Z_ERR);
2201         }
2202         return (Z_OK);
2203 }
2204 
2205 static void
2206 add_resource(cmd_t *cmd)
2207 {
2208         int type;
2209         struct zone_psettab tmp_psettab;
2210         struct zone_mcaptab tmp_mcaptab;
2211         struct zone_secflagstab tmp_secflagstab;
2212         uint64_t tmp;
2213         uint64_t tmp_mcap;
2214         char pool[MAXNAMELEN];
2215 
2216         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2217                 long_usage(CMD_ADD, B_TRUE);
2218                 goto bad;
2219         }
2220 
2221         switch (type) {
2222         case RT_FS:
2223                 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2224                 return;
2225         case RT_NET:
2226                 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2227                 return;
2228         case RT_DEVICE:
2229                 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2230                 return;
2231         case RT_RCTL:


2303                 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2304                     zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2305                     == Z_OK ||
2306                     zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2307                     &tmp_mcap) == Z_OK) {
2308                         zerr(gettext("The %s resource or a related resource "
2309                             "control already exists."), rt_to_str(RT_MCAP));
2310                         goto bad;
2311                 }
2312                 if (global_zone)
2313                         zerr(gettext("WARNING: Setting a global zone memory "
2314                             "cap too low could deny\nservice "
2315                             "to even the root user; "
2316                             "this could render the system impossible\n"
2317                             "to administer.  Please use caution."));
2318                 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2319                 return;
2320         case RT_ADMIN:
2321                 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2322                 return;
2323         case RT_SECFLAGS:
2324                 /* Make sure we haven't already set this */
2325                 if (zonecfg_lookup_secflags(handle, &tmp_secflagstab) == Z_OK)
2326                         zerr(gettext("The %s resource already exists."),
2327                             rt_to_str(RT_SECFLAGS));
2328                 bzero(&in_progress_secflagstab,
2329                     sizeof (in_progress_secflagstab));
2330                 return;
2331         default:
2332                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2333                 long_usage(CMD_ADD, B_TRUE);
2334                 usage(B_FALSE, HELP_RESOURCES);
2335         }
2336 bad:
2337         global_scope = B_TRUE;
2338         end_op = -1;
2339 }
2340 
2341 static void
2342 do_complex_rctl_val(complex_property_ptr_t cp)
2343 {
2344         struct zone_rctlvaltab *rctlvaltab;
2345         complex_property_ptr_t cx;
2346         boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2347             seen_action = B_FALSE;
2348         rctlblk_t *rctlblk;
2349         int err;
2350 


2980                 case PT_USER:
2981                         (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2982                             sizeof (admintab->zone_admin_user));
2983                         break;
2984                 case PT_AUTHS:
2985                         (void) strlcpy(admintab->zone_admin_auths,
2986                             pp->pv_simple, sizeof (admintab->zone_admin_auths));
2987                         break;
2988                 default:
2989                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2990                             Z_NO_PROPERTY_TYPE, B_TRUE);
2991                         return (Z_INSUFFICIENT_SPEC);
2992                 }
2993         }
2994         if (fill_in_only)
2995                 return (Z_OK);
2996         err = zonecfg_lookup_admin(handle, admintab);
2997         return (err);
2998 }
2999 
3000 static int
3001 fill_in_secflagstab(cmd_t *cmd, struct zone_secflagstab *secflagstab,
3002     boolean_t fill_in_only)
3003 {
3004         int err, i;
3005         property_value_ptr_t pp;
3006 
3007         if ((err = initialize(B_TRUE)) != Z_OK)
3008                 return (err);
3009 
3010         bzero(secflagstab, sizeof (*secflagstab));
3011         for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
3012                 pp = cmd->cmd_property_ptr[i];
3013                 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
3014                         zerr(gettext("A simple value was expected here."));
3015                         saw_error = B_TRUE;
3016                         return (Z_INSUFFICIENT_SPEC);
3017                 }
3018                 switch (cmd->cmd_prop_name[i]) {
3019                 case PT_DEFAULT:
3020                         (void) strlcpy(secflagstab->zone_secflags_default,
3021                             pp->pv_simple,
3022                             sizeof (secflagstab->zone_secflags_default));
3023                         break;
3024                 case PT_LOWER:
3025                         (void) strlcpy(secflagstab->zone_secflags_lower,
3026                             pp->pv_simple,
3027                             sizeof (secflagstab->zone_secflags_lower));
3028                         break;
3029                 case PT_UPPER:
3030                         (void) strlcpy(secflagstab->zone_secflags_upper,
3031                             pp->pv_simple,
3032                             sizeof (secflagstab->zone_secflags_upper));
3033                         break;
3034                 default:
3035                         zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
3036                             Z_NO_PROPERTY_TYPE, B_TRUE);
3037                         return (Z_INSUFFICIENT_SPEC);
3038                 }
3039         }
3040         if (fill_in_only)
3041                 return (Z_OK);
3042 
3043         err = zonecfg_lookup_secflags(handle, secflagstab);
3044 
3045         return (err);
3046 }
3047 
3048 static void
3049 remove_aliased_rctl(int type, char *name)
3050 {
3051         int err;
3052         uint64_t tmp;
3053 
3054         if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
3055                 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3056                     zonecfg_strerror(err));
3057                 saw_error = B_TRUE;
3058                 return;
3059         }
3060         if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
3061                 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
3062                     zonecfg_strerror(err));
3063                 saw_error = B_TRUE;
3064         } else {
3065                 need_to_commit = B_TRUE;
3066         }
3067 }


3430                 return;
3431         } else {
3432                 /*
3433                  * unqualified admin removal.
3434                  * remove all admins but prompt if more
3435                  * than one.
3436                  */
3437                 if (!prompt_remove_resource(cmd, "admin"))
3438                         return;
3439 
3440                 if ((err = zonecfg_delete_admins(handle, zone))
3441                     != Z_OK)
3442                         z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3443                             err, B_TRUE);
3444                 else
3445                         need_to_commit = B_TRUE;
3446         }
3447 }
3448 
3449 static void
3450 remove_secflags()
3451 {
3452         int err;
3453         struct zone_secflagstab sectab = { 0 };
3454 
3455         if (zonecfg_lookup_secflags(handle, &sectab) != Z_OK) {
3456                 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
3457                     rt_to_str(RT_SECFLAGS),
3458                     zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3459                 return;
3460         }
3461 
3462         if ((err = zonecfg_delete_secflags(handle, &sectab)) != Z_OK) {
3463                 z_cmd_rt_perror(CMD_REMOVE, RT_SECFLAGS, err, B_TRUE);
3464                 return;
3465         }
3466 
3467         need_to_commit = B_TRUE;
3468 }
3469 
3470 static void
3471 remove_resource(cmd_t *cmd)
3472 {
3473         int type;
3474         int arg;
3475         boolean_t arg_err = B_FALSE;
3476 
3477         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3478                 long_usage(CMD_REMOVE, B_TRUE);
3479                 return;
3480         }
3481 
3482         optind = 0;
3483         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3484                 switch (arg) {
3485                 case '?':
3486                         longer_usage(CMD_REMOVE);
3487                         arg_err = B_TRUE;
3488                         break;
3489                 case 'F':
3490                         break;


3514                 remove_rctl(cmd);
3515                 return;
3516         case RT_ATTR:
3517                 remove_attr(cmd);
3518                 return;
3519         case RT_DATASET:
3520                 remove_dataset(cmd);
3521                 return;
3522         case RT_DCPU:
3523                 remove_pset();
3524                 return;
3525         case RT_PCAP:
3526                 remove_pcap();
3527                 return;
3528         case RT_MCAP:
3529                 remove_mcap();
3530                 return;
3531         case RT_ADMIN:
3532                 remove_admin(cmd);
3533                 return;
3534         case RT_SECFLAGS:
3535                 remove_secflags();
3536                 return;
3537         default:
3538                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3539                 long_usage(CMD_REMOVE, B_TRUE);
3540                 usage(B_FALSE, HELP_RESOURCES);
3541                 return;
3542         }
3543 }
3544 
3545 static void
3546 remove_property(cmd_t *cmd)
3547 {
3548         char *prop_id;
3549         int err, res_type, prop_type;
3550         property_value_ptr_t pp;
3551         struct zone_rctlvaltab *rctlvaltab;
3552         complex_property_ptr_t cx;
3553 
3554         res_type = resource_scope;
3555         prop_type = cmd->cmd_prop_name[0];
3556         if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {


3729                 if (prop_type == PT_IMPORTANCE) {
3730                         in_progress_psettab.zone_importance[0] = '\0';
3731                         need_to_commit = B_TRUE;
3732                         return;
3733                 }
3734                 break;
3735         case RT_MCAP:
3736                 switch (prop_type) {
3737                 case PT_PHYSICAL:
3738                         in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3739                         need_to_commit = B_TRUE;
3740                         return;
3741                 case PT_SWAP:
3742                         remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3743                         return;
3744                 case PT_LOCKED:
3745                         remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3746                         return;
3747                 }
3748                 break;
3749         case RT_SECFLAGS:
3750                 switch (prop_type) {
3751                 case PT_LOWER:
3752                         in_progress_secflagstab.zone_secflags_lower[0] = '\0';
3753                         need_to_commit = B_TRUE;
3754                         return;
3755                 case PT_DEFAULT:
3756                         in_progress_secflagstab.zone_secflags_default[0] = '\0';
3757                         need_to_commit = B_TRUE;
3758                         return;
3759                 case PT_UPPER:
3760                         in_progress_secflagstab.zone_secflags_upper[0] = '\0';
3761                         need_to_commit = B_TRUE;
3762                         return;
3763                 }
3764                 break;
3765         default:
3766                 break;
3767         }
3768 
3769         zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3770 }
3771 
3772 static void
3773 clear_global(cmd_t *cmd)
3774 {
3775         int err, type;
3776 
3777         if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3778                 long_usage(CMD_CLEAR, B_TRUE);
3779                 return;
3780         }
3781 
3782         if (initialize(B_TRUE) != Z_OK)
3783                 return;
3784 


3998                             B_TRUE);
3999                         global_scope = B_TRUE;
4000                 }
4001                 if (res == Z_OK)
4002                         bcopy(&old_mcaptab, &in_progress_mcaptab,
4003                             sizeof (struct zone_mcaptab));
4004                 else
4005                         bzero(&in_progress_mcaptab,
4006                             sizeof (in_progress_mcaptab));
4007                 return;
4008         case RT_ADMIN:
4009                 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
4010                     != Z_OK) {
4011                         z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
4012                             B_TRUE);
4013                         global_scope = B_TRUE;
4014                 }
4015                 bcopy(&old_admintab, &in_progress_admintab,
4016                     sizeof (struct zone_admintab));
4017                 return;
4018         case RT_SECFLAGS:
4019                 if ((err = fill_in_secflagstab(cmd, &old_secflagstab, B_FALSE))
4020                     != Z_OK) {
4021                         z_cmd_rt_perror(CMD_SELECT, RT_SECFLAGS, err,
4022                             B_TRUE);
4023                         global_scope = B_TRUE;
4024                 }
4025                 bcopy(&old_secflagstab, &in_progress_secflagstab,
4026                     sizeof (struct zone_secflagstab));
4027                 return;
4028         default:
4029                 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
4030                 long_usage(CMD_SELECT, B_TRUE);
4031                 usage(B_FALSE, HELP_RESOURCES);
4032                 return;
4033         }
4034 }
4035 
4036 /*
4037  * Network "addresses" can be one of the following forms:
4038  *      <IPv4 address>
4039  *      <IPv4 address>/<prefix length>
4040  *      <IPv6 address>/<prefix length>
4041  *      <host name>
4042  *      <host name>/<prefix length>
4043  * In other words, the "/" followed by a prefix length is allowed but not
4044  * required for IPv4 addresses and host names, and required for IPv6 addresses.
4045  * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4046  * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4047  * Host names must start with an alpha-numeric character, and all subsequent


4924                 return;
4925         case RT_ADMIN:
4926                 switch (prop_type) {
4927                 case PT_USER:
4928                         (void) strlcpy(in_progress_admintab.zone_admin_user,
4929                             prop_id,
4930                             sizeof (in_progress_admintab.zone_admin_user));
4931                         return;
4932                 case PT_AUTHS:
4933                         (void) strlcpy(in_progress_admintab.zone_admin_auths,
4934                             prop_id,
4935                             sizeof (in_progress_admintab.zone_admin_auths));
4936                         return;
4937                 default:
4938                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4939                             B_TRUE);
4940                         long_usage(CMD_SET, B_TRUE);
4941                         usage(B_FALSE, HELP_PROPS);
4942                         return;
4943                 }
4944         case RT_SECFLAGS: {
4945                 char *propstr;
4946 
4947                 switch (prop_type) {
4948                 case PT_DEFAULT:
4949                         propstr = in_progress_secflagstab.zone_secflags_default;
4950                         break;
4951                 case PT_UPPER:
4952                         propstr = in_progress_secflagstab.zone_secflags_upper;
4953                         break;
4954                 case PT_LOWER:
4955                         propstr = in_progress_secflagstab.zone_secflags_lower;
4956                         break;
4957                 default:
4958                         zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4959                             B_TRUE);
4960                         long_usage(CMD_SET, B_TRUE);
4961                         usage(B_FALSE, HELP_PROPS);
4962                         return;
4963                 }
4964                 (void) strlcpy(propstr, prop_id, ZONECFG_SECFLAGS_MAX);
4965                 return;
4966         }
4967         default:
4968                 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4969                 long_usage(CMD_SET, B_TRUE);
4970                 usage(B_FALSE, HELP_RESOURCES);
4971                 return;
4972         }
4973 }
4974 
4975 static void
4976 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4977 {
4978         char *qstr;
4979 
4980         if (*pval != '\0') {
4981                 qstr = quoteit(pval);
4982                 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4983                         (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4984                             qstr);
4985                 else
4986                         (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);


5561 
5562         bzero(&lookup, sizeof (lookup));
5563         res1 = zonecfg_getmcapent(handle, &lookup);
5564         res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5565         res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5566             &locked_limit);
5567 
5568         if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5569                 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5570 }
5571 
5572 static void
5573 output_auth(FILE *fp, struct zone_admintab *admintab)
5574 {
5575         (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5576         output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5577         output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5578 }
5579 
5580 static void
5581 output_secflags(FILE *fp, struct zone_secflagstab *sftab)
5582 {
5583         (void) fprintf(fp, "%s:\n", rt_to_str(RT_SECFLAGS));
5584         output_prop(fp, PT_DEFAULT, sftab->zone_secflags_default, B_TRUE);
5585         output_prop(fp, PT_LOWER, sftab->zone_secflags_lower, B_TRUE);
5586         output_prop(fp, PT_UPPER, sftab->zone_secflags_upper, B_TRUE);
5587 }
5588 
5589 static void
5590 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5591 {
5592         struct zone_admintab lookup, user;
5593         boolean_t output = B_FALSE;
5594         int err;
5595 
5596         if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5597                 zone_perror(zone, err, B_TRUE);
5598                 return;
5599         }
5600         while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5601                 if (cmd->cmd_prop_nv_pairs == 0) {
5602                         output_auth(fp, &lookup);
5603                         continue;
5604                 }
5605                 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5606                         continue;
5607                 if (strlen(user.zone_admin_user) > 0 &&
5608                     strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5609                         continue;       /* no match */
5610                 output_auth(fp, &lookup);
5611                 output = B_TRUE;
5612         }
5613         (void) zonecfg_endadminent(handle);
5614         /*
5615          * If a property n/v pair was specified, warn the user if there was
5616          * nothing to output.
5617          */
5618         if (!output && cmd->cmd_prop_nv_pairs > 0)
5619                 (void) printf(gettext("No such %s resource.\n"),
5620                     rt_to_str(RT_ADMIN));
5621 }
5622 
5623 static void
5624 info_secflags(zone_dochandle_t handle, FILE *fp)
5625 {
5626         struct zone_secflagstab sftab;
5627         int err;
5628 
5629         if ((err = zonecfg_lookup_secflags(handle, &sftab)) != Z_OK) {
5630                 zone_perror(zone, err, B_TRUE);
5631                 return;
5632         }
5633 
5634         output_secflags(fp, &sftab);
5635 }
5636 
5637 void
5638 info_func(cmd_t *cmd)
5639 {
5640         FILE *fp = stdout;
5641         boolean_t need_to_close = B_FALSE;
5642         int type;
5643         int res1, res2;
5644         uint64_t swap_limit;
5645         uint64_t locked_limit;
5646 
5647         assert(cmd != NULL);
5648 
5649         if (initialize(B_TRUE) != Z_OK)
5650                 return;
5651 
5652         /* don't page error output */
5653         if (interactive_mode) {
5654                 if ((fp = pager_open()) != NULL)
5655                         need_to_close = B_TRUE;
5656                 else


5679                 case RT_DATASET:
5680                         output_ds(fp, &in_progress_dstab);
5681                         break;
5682                 case RT_DCPU:
5683                         output_pset(fp, &in_progress_psettab);
5684                         break;
5685                 case RT_PCAP:
5686                         output_pcap(fp);
5687                         break;
5688                 case RT_MCAP:
5689                         res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5690                             &swap_limit);
5691                         res2 = zonecfg_get_aliased_rctl(handle,
5692                             ALIAS_MAXLOCKEDMEM, &locked_limit);
5693                         output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5694                             res2, locked_limit);
5695                         break;
5696                 case RT_ADMIN:
5697                         output_auth(fp, &in_progress_admintab);
5698                         break;
5699                 case RT_SECFLAGS:
5700                         output_secflags(fp, &in_progress_secflagstab);
5701                         break;
5702                 }
5703                 goto cleanup;
5704         }
5705 
5706         type = cmd->cmd_res_type;
5707 
5708         if (gz_invalid_rt_property(type)) {
5709                 zerr(gettext("%s is not a valid property for the global zone."),
5710                     rt_to_str(type));
5711                 goto cleanup;
5712         }
5713 
5714         if (gz_invalid_resource(type)) {
5715                 zerr(gettext("%s is not a valid resource for the global zone."),
5716                     rt_to_str(type));
5717                 goto cleanup;
5718         }
5719 
5720         switch (cmd->cmd_res_type) {
5721         case RT_UNKNOWN:


5738                 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5739                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5740                 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5741                 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5742                 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5743                 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5744                 if (!global_zone) {
5745                         info_fs(handle, fp, cmd);
5746                         info_net(handle, fp, cmd);
5747                         info_dev(handle, fp, cmd);
5748                 }
5749                 info_pset(handle, fp);
5750                 info_pcap(fp);
5751                 info_mcap(handle, fp);
5752                 if (!global_zone) {
5753                         info_attr(handle, fp, cmd);
5754                         info_ds(handle, fp, cmd);
5755                         info_auth(handle, fp, cmd);
5756                 }
5757                 info_rctl(handle, fp, cmd);
5758                 info_secflags(handle, fp);
5759                 break;
5760         case RT_ZONENAME:
5761                 info_zonename(handle, fp);
5762                 break;
5763         case RT_ZONEPATH:
5764                 info_zonepath(handle, fp);
5765                 break;
5766         case RT_BRAND:
5767                 info_brand(handle, fp);
5768                 break;
5769         case RT_AUTOBOOT:
5770                 info_autoboot(handle, fp);
5771                 break;
5772         case RT_POOL:
5773                 info_pool(handle, fp);
5774                 break;
5775         case RT_LIMITPRIV:
5776                 info_limitpriv(handle, fp);
5777                 break;
5778         case RT_BOOTARGS:


5824                 info_ds(handle, fp, cmd);
5825                 break;
5826         case RT_DCPU:
5827                 info_pset(handle, fp);
5828                 break;
5829         case RT_PCAP:
5830                 info_pcap(fp);
5831                 break;
5832         case RT_MCAP:
5833                 info_mcap(handle, fp);
5834                 break;
5835         case RT_HOSTID:
5836                 info_hostid(handle, fp);
5837                 break;
5838         case RT_ADMIN:
5839                 info_auth(handle, fp, cmd);
5840                 break;
5841         case RT_FS_ALLOWED:
5842                 info_fs_allowed(handle, fp);
5843                 break;
5844         case RT_SECFLAGS:
5845                 info_secflags(handle, fp);
5846                 break;
5847         default:
5848                 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5849                     B_TRUE);
5850         }
5851 
5852 cleanup:
5853         if (need_to_close)
5854                 (void) pager_close(fp);
5855 }
5856 
5857 /*
5858  * Helper function for verify-- checks that a required string property
5859  * exists.
5860  */
5861 static void
5862 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5863 {
5864         if (strlen(attr) == 0) {
5865                 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5866                     pt_to_str(pt));


5978                                 tmp->xif_has_defrouter = B_TRUE;
5979                         return (B_TRUE);
5980                 }
5981         }
5982 
5983         tmp = malloc(sizeof (*tmp));
5984         if (tmp == NULL) {
5985                 zerr(gettext("memory allocation failed for %s"),
5986                     nwif->zone_nwif_physical);
5987                 return (B_FALSE);
5988         }
5989         strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5990             sizeof (tmp->xif_name));
5991         tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5992         tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5993         tmp->xif_next = xif;
5994         xif = tmp;
5995         return (B_TRUE);
5996 }
5997 
5998 boolean_t
5999 verify_secflags(struct zone_secflagstab *tab)
6000 {
6001         secflagdelta_t def = {0};
6002         secflagdelta_t upper = {0};
6003         secflagdelta_t lower = {0};
6004         boolean_t def_set = B_FALSE;
6005         boolean_t upper_set = B_FALSE;
6006         boolean_t lower_set = B_FALSE;
6007         boolean_t ret = B_TRUE;
6008 
6009         if (strlen(tab->zone_secflags_default) > 0) {
6010                 def_set = B_TRUE;
6011                 if (secflags_parse(NULL, tab->zone_secflags_default,
6012                     &def) == -1) {
6013                         zerr(gettext("default security flags '%s' are invalid"),
6014                             tab->zone_secflags_default);
6015                         ret = B_FALSE;
6016                 }
6017         } else {
6018                 secflags_zero(&def.psd_assign);
6019                 def.psd_ass_active = B_TRUE;
6020         }
6021 
6022         if (strlen(tab->zone_secflags_upper) > 0) {
6023                 upper_set = B_TRUE;
6024                 if (secflags_parse(NULL, tab->zone_secflags_upper,
6025                     &upper) == -1) {
6026                         zerr(gettext("upper security flags '%s' are invalid"),
6027                             tab->zone_secflags_upper);
6028                         ret = B_FALSE;
6029                 }
6030         } else {
6031                 secflags_fullset(&upper.psd_assign);
6032                 upper.psd_ass_active = B_TRUE;
6033         }
6034 
6035         if (strlen(tab->zone_secflags_lower) > 0) {
6036                 lower_set = B_TRUE;
6037                 if (secflags_parse(NULL, tab->zone_secflags_lower,
6038                     &lower) == -1) {
6039                         zerr(gettext("lower security flags '%s' are invalid"),
6040                             tab->zone_secflags_lower);
6041                         ret = B_FALSE;
6042                 }
6043         } else {
6044                 secflags_zero(&lower.psd_assign);
6045                 lower.psd_ass_active = B_TRUE;
6046         }
6047 
6048         if (def_set && !def.psd_ass_active) {
6049                 zerr(gettext("only assignment of security flags is "
6050                     "allowed (default: %s)"), tab->zone_secflags_default);
6051         }
6052 
6053         if (lower_set && !lower.psd_ass_active) {
6054                 zerr(gettext("only assignment of security flags is "
6055                     "allowed (lower: %s)"), tab->zone_secflags_lower);
6056         }
6057 
6058         if (upper_set && !upper.psd_ass_active) {
6059                 zerr(gettext("only assignment of security flags is "
6060                     "allowed (upper: %s)"), tab->zone_secflags_upper);
6061         }
6062 
6063         if (def.psd_assign & ~upper.psd_assign)     { /* In default but not upper */
6064                 zerr(gettext("default secflags must be within the "
6065                     "upper limit"));
6066                 ret = B_FALSE;
6067         }
6068         if (lower.psd_assign & ~def.psd_assign) { /* In lower but not default */
6069                 zerr(gettext("default secflags must be above the lower limit"));
6070                 ret = B_FALSE;
6071         }
6072         if (lower.psd_assign & ~upper.psd_assign) { /* In lower but not upper */
6073                 zerr(gettext("lower secflags must be within the upper limit"));
6074                 ret = B_FALSE;
6075         }
6076 
6077         return (ret);
6078 }
6079 
6080 /*
6081  * See the DTD for which attributes are required for which resources.
6082  *
6083  * This function can be called by commit_func(), which needs to save things,
6084  * in addition to the general call from parse_and_run(), which doesn't need
6085  * things saved.  Since the parameters are standardized, we distinguish by
6086  * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6087  * that a save is needed.
6088  */
6089 void
6090 verify_func(cmd_t *cmd)
6091 {
6092         struct zone_nwiftab nwiftab;
6093         struct zone_fstab fstab;
6094         struct zone_attrtab attrtab;
6095         struct zone_rctltab rctltab;
6096         struct zone_dstab dstab;
6097         struct zone_psettab psettab;
6098         struct zone_admintab admintab;
6099         struct zone_secflagstab secflagstab;
6100         char zonepath[MAXPATHLEN];
6101         char sched[MAXNAMELEN];
6102         char brand[MAXNAMELEN];
6103         char hostidp[HW_HOSTID_LEN];
6104         char fsallowedp[ZONE_FS_ALLOWED_MAX];
6105         priv_set_t *privs;
6106         char *privname = NULL;
6107         int err, ret_val = Z_OK, arg;
6108         int pset_res;
6109         boolean_t save = B_FALSE;
6110         boolean_t arg_err = B_FALSE;
6111         zone_iptype_t iptype;
6112         boolean_t has_cpu_shares = B_FALSE;
6113         boolean_t has_cpu_cap = B_FALSE;
6114         struct xif *tmp;
6115 
6116         optind = 0;
6117         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6118                 switch (arg) {
6119                 case '?':


6376         }
6377         while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6378                 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6379                     PT_USER, &ret_val);
6380                 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6381                     PT_AUTHS, &ret_val);
6382                 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6383                     == NULL)) {
6384                         zerr(gettext("%s %s is not a valid username"),
6385                             pt_to_str(PT_USER),
6386                             admintab.zone_admin_user);
6387                         ret_val = Z_BAD_PROPERTY;
6388                 }
6389                 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6390                     admintab.zone_admin_auths, zone))) {
6391                         ret_val = Z_BAD_PROPERTY;
6392                 }
6393         }
6394         (void) zonecfg_endadminent(handle);
6395 
6396         if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
6397                 zone_perror(zone, err, B_TRUE);
6398                 return;
6399         }
6400 
6401         /*
6402          * No properties are required, but any specified should be
6403          * valid
6404          */
6405         if (verify_secflags(&secflagstab) != B_TRUE) {
6406                 /* Error is reported from verify_secflags */
6407                 ret_val = Z_BAD_PROPERTY;
6408         }
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                         if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6420                                 need_to_commit = B_FALSE;
6421                                 (void) strlcpy(revert_zone, zone,
6422                                     sizeof (revert_zone));
6423                         }
6424                 } else {
6425                         zerr(gettext("Zone %s failed to verify"), zone);
6426                 }
6427         }
6428         if (ret_val != Z_OK)
6429                 zone_perror(zone, ret_val, B_TRUE);


6979                             sizeof (tmp_admintab.zone_admin_user));
6980                         err = zonecfg_lookup_admin(
6981                             handle, &tmp_admintab);
6982                         if (err == Z_OK) {
6983                                 zerr(gettext("A %s resource "
6984                                     "with the %s '%s' already exists."),
6985                                     rt_to_str(RT_ADMIN),
6986                                     pt_to_str(PT_USER),
6987                                     in_progress_admintab.zone_admin_user);
6988                                 saw_error = B_TRUE;
6989                                 return;
6990                         }
6991                         err = zonecfg_add_admin(handle,
6992                             &in_progress_admintab, zone);
6993                 } else {
6994                         err = zonecfg_modify_admin(handle,
6995                             &old_admintab, &in_progress_admintab,
6996                             zone);
6997                 }
6998                 break;
6999         case RT_SECFLAGS:
7000                 if (verify_secflags(&in_progress_secflagstab) != B_TRUE) {
7001                         saw_error = B_TRUE;
7002                         return;
7003                 }
7004 
7005                 if (end_op == CMD_ADD) {
7006                         err = zonecfg_add_secflags(handle,
7007                             &in_progress_secflagstab);
7008                 } else {
7009                         err = zonecfg_modify_secflags(handle,
7010                             &old_secflagstab, &in_progress_secflagstab);
7011                 }
7012                 break;
7013         default:
7014                 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
7015                     B_TRUE);
7016                 saw_error = B_TRUE;
7017                 return;
7018         }
7019 
7020         if (err != Z_OK) {
7021                 zone_perror(zone, err, B_TRUE);
7022         } else {
7023                 need_to_commit = B_TRUE;
7024                 global_scope = B_TRUE;
7025                 end_op = -1;
7026         }
7027 }
7028 
7029 void
7030 commit_func(cmd_t *cmd)
7031 {
7032         int arg;