Print this page
Code review comments from pmooney (sundry), and igork (screwups in zonecfg refactoring)
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 (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
2121                 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
2122                     rt_to_str(RT_SECFLAGS));
2123                 export_prop(of, PT_DEFAULT, secflagstab.zone_secflags_default);
2124                 export_prop(of, PT_LOWER, secflagstab.zone_secflags_lower);
2125                 export_prop(of, PT_UPPER, secflagstab.zone_secflags_upper);
2126                 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
2127         }
2128 
2129         /*
2130          * There is nothing to export for pcap since this resource is just
2131          * a container for an rctl alias.
2132          */
2133 
2134 done:
2135         if (need_to_close)
2136                 (void) fclose(of);
2137 }
2138 
2139 void
2140 exit_func(cmd_t *cmd)
2141 {
2142         int arg, answer;
2143         boolean_t arg_err = B_FALSE;
2144 
2145         optind = 0;
2146         while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2147                 switch (arg) {
2148                 case '?':


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


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


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


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


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


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


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


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


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


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


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


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


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


6369         }
6370         while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6371                 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6372                     PT_USER, &ret_val);
6373                 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6374                     PT_AUTHS, &ret_val);
6375                 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6376                     == NULL)) {
6377                         zerr(gettext("%s %s is not a valid username"),
6378                             pt_to_str(PT_USER),
6379                             admintab.zone_admin_user);
6380                         ret_val = Z_BAD_PROPERTY;
6381                 }
6382                 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6383                     admintab.zone_admin_auths, zone))) {
6384                         ret_val = Z_BAD_PROPERTY;
6385                 }
6386         }
6387         (void) zonecfg_endadminent(handle);
6388 
6389         if (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
6390                 /*
6391                  * No properties are required, but any specified should be
6392                  * valid
6393                  */
6394                 if (verify_secflags(&secflagstab) != B_TRUE) {
6395                         /* Error is reported from verify_secflags */
6396                         ret_val = Z_BAD_PROPERTY;
6397                 }
6398         }
6399 
6400         if (!global_scope) {
6401                 zerr(gettext("resource specification incomplete"));
6402                 saw_error = B_TRUE;
6403                 if (ret_val == Z_OK)
6404                         ret_val = Z_INSUFFICIENT_SPEC;
6405         }
6406 
6407         if (save) {
6408                 if (ret_val == Z_OK) {
6409                         if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6410                                 need_to_commit = B_FALSE;
6411                                 (void) strlcpy(revert_zone, zone,
6412                                     sizeof (revert_zone));
6413                         }
6414                 } else {
6415                         zerr(gettext("Zone %s failed to verify"), zone);
6416                 }
6417         }
6418         if (ret_val != Z_OK)
6419                 zone_perror(zone, ret_val, B_TRUE);


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