1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2015 by Delphix. All rights reserved.
  26  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * zoneadm is a command interpreter for zone administration.  It is all in
  31  * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
  32  * main() calls parse_and_run() which calls cmd_match(), then invokes the
  33  * appropriate command's handler function.  The rest of the program is the
  34  * handler functions and their helper functions.
  35  *
  36  * Some of the helper functions are used largely to simplify I18N: reducing
  37  * the need for translation notes.  This is particularly true of many of
  38  * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
  39  * than zerror(gettext("foo failed")) with a translation note indicating
  40  * that "foo" need not be translated.
  41  */
  42 
  43 #include <stdio.h>
  44 #include <errno.h>
  45 #include <unistd.h>
  46 #include <signal.h>
  47 #include <stdarg.h>
  48 #include <ctype.h>
  49 #include <stdlib.h>
  50 #include <string.h>
  51 #include <wait.h>
  52 #include <zone.h>
  53 #include <priv.h>
  54 #include <locale.h>
  55 #include <libintl.h>
  56 #include <libzonecfg.h>
  57 #include <bsm/adt.h>
  58 #include <sys/brand.h>
  59 #include <sys/param.h>
  60 #include <sys/types.h>
  61 #include <sys/stat.h>
  62 #include <sys/statvfs.h>
  63 #include <assert.h>
  64 #include <sys/sockio.h>
  65 #include <sys/mntent.h>
  66 #include <limits.h>
  67 #include <dirent.h>
  68 #include <uuid/uuid.h>
  69 #include <fcntl.h>
  70 #include <door.h>
  71 #include <macros.h>
  72 #include <libgen.h>
  73 #include <fnmatch.h>
  74 #include <sys/modctl.h>
  75 #include <libbrand.h>
  76 #include <libscf.h>
  77 #include <procfs.h>
  78 #include <strings.h>
  79 #include <pool.h>
  80 #include <sys/pool.h>
  81 #include <sys/priocntl.h>
  82 #include <sys/fsspriocntl.h>
  83 #include <libdladm.h>
  84 #include <libdllink.h>
  85 #include <pwd.h>
  86 #include <auth_list.h>
  87 #include <auth_attr.h>
  88 #include <secdb.h>
  89 
  90 #include "zoneadm.h"
  91 
  92 #define MAXARGS 8
  93 #define SOURCE_ZONE (CMD_MAX + 1)
  94 
  95 /* Reflects kernel zone entries */
  96 typedef struct zone_entry {
  97         zoneid_t        zid;
  98         char            zname[ZONENAME_MAX];
  99         char            *zstate_str;
 100         zone_state_t    zstate_num;
 101         char            zbrand[MAXNAMELEN];
 102         char            zroot[MAXPATHLEN];
 103         char            zuuid[UUID_PRINTABLE_STRING_LENGTH];
 104         zone_iptype_t   ziptype;
 105         zoneid_t        zdid;
 106 } zone_entry_t;
 107 
 108 #define CLUSTER_BRAND_NAME      "cluster"
 109 
 110 static zone_entry_t *zents;
 111 static size_t nzents;
 112 
 113 #define LOOPBACK_IF     "lo0"
 114 #define SOCKET_AF(af)   (((af) == AF_UNSPEC) ? AF_INET : (af))
 115 
 116 struct net_if {
 117         char    *name;
 118         int     af;
 119 };
 120 
 121 /* 0755 is the default directory mode. */
 122 #define DEFAULT_DIR_MODE \
 123         (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 124 
 125 struct cmd {
 126         uint_t  cmd_num;                                /* command number */
 127         char    *cmd_name;                              /* command name */
 128         char    *short_usage;                           /* short form help */
 129         int     (*handler)(int argc, char *argv[]);     /* function to call */
 130 
 131 };
 132 
 133 #define SHELP_HELP      "help"
 134 #define SHELP_BOOT      "boot [-- boot_arguments]"
 135 #define SHELP_HALT      "halt"
 136 #define SHELP_READY     "ready"
 137 #define SHELP_SHUTDOWN  "shutdown [-r [-- boot_arguments]]"
 138 #define SHELP_REBOOT    "reboot [-- boot_arguments]"
 139 #define SHELP_LIST      "list [-cinpv]"
 140 #define SHELP_VERIFY    "verify"
 141 #define SHELP_INSTALL   "install [brand-specific args]"
 142 #define SHELP_UNINSTALL "uninstall [-F] [brand-specific args]"
 143 #define SHELP_CLONE     "clone [-m method] [-s <ZFS snapshot>] "\
 144         "[brand-specific args] zonename"
 145 #define SHELP_MOVE      "move zonepath"
 146 #define SHELP_DETACH    "detach [-n] [brand-specific args]"
 147 #define SHELP_ATTACH    "attach [-F] [-n <path>] [brand-specific args]"
 148 #define SHELP_MARK      "mark incomplete"
 149 
 150 #define EXEC_PREFIX     "exec "
 151 #define EXEC_LEN        (strlen(EXEC_PREFIX))
 152 #define RMCOMMAND       "/usr/bin/rm -rf"
 153 
 154 static int cleanup_zonepath(char *, boolean_t);
 155 
 156 
 157 static int help_func(int argc, char *argv[]);
 158 static int ready_func(int argc, char *argv[]);
 159 static int boot_func(int argc, char *argv[]);
 160 static int shutdown_func(int argc, char *argv[]);
 161 static int halt_func(int argc, char *argv[]);
 162 static int reboot_func(int argc, char *argv[]);
 163 static int list_func(int argc, char *argv[]);
 164 static int verify_func(int argc, char *argv[]);
 165 static int install_func(int argc, char *argv[]);
 166 static int uninstall_func(int argc, char *argv[]);
 167 static int mount_func(int argc, char *argv[]);
 168 static int unmount_func(int argc, char *argv[]);
 169 static int clone_func(int argc, char *argv[]);
 170 static int move_func(int argc, char *argv[]);
 171 static int detach_func(int argc, char *argv[]);
 172 static int attach_func(int argc, char *argv[]);
 173 static int mark_func(int argc, char *argv[]);
 174 static int apply_func(int argc, char *argv[]);
 175 static int sysboot_func(int argc, char *argv[]);
 176 static int sanity_check(char *zone, int cmd_num, boolean_t running,
 177     boolean_t unsafe_when_running, boolean_t force);
 178 static int cmd_match(char *cmd);
 179 static int verify_details(int, char *argv[]);
 180 static int verify_brand(zone_dochandle_t, int, char *argv[]);
 181 static int invoke_brand_handler(int, char *argv[]);
 182 
 183 static struct cmd cmdtab[] = {
 184         { CMD_HELP,             "help",         SHELP_HELP,     help_func },
 185         { CMD_BOOT,             "boot",         SHELP_BOOT,     boot_func },
 186         { CMD_HALT,             "halt",         SHELP_HALT,     halt_func },
 187         { CMD_READY,            "ready",        SHELP_READY,    ready_func },
 188         { CMD_SHUTDOWN,         "shutdown",     SHELP_SHUTDOWN, shutdown_func },
 189         { CMD_REBOOT,           "reboot",       SHELP_REBOOT,   reboot_func },
 190         { CMD_LIST,             "list",         SHELP_LIST,     list_func },
 191         { CMD_VERIFY,           "verify",       SHELP_VERIFY,   verify_func },
 192         { CMD_INSTALL,          "install",      SHELP_INSTALL,  install_func },
 193         { CMD_UNINSTALL,        "uninstall",    SHELP_UNINSTALL,
 194             uninstall_func },
 195         /* mount and unmount are private commands for admin/install */
 196         { CMD_MOUNT,            "mount",        NULL,           mount_func },
 197         { CMD_UNMOUNT,          "unmount",      NULL,           unmount_func },
 198         { CMD_CLONE,            "clone",        SHELP_CLONE,    clone_func },
 199         { CMD_MOVE,             "move",         SHELP_MOVE,     move_func },
 200         { CMD_DETACH,           "detach",       SHELP_DETACH,   detach_func },
 201         { CMD_ATTACH,           "attach",       SHELP_ATTACH,   attach_func },
 202         { CMD_MARK,             "mark",         SHELP_MARK,     mark_func },
 203         { CMD_APPLY,            "apply",        NULL,           apply_func },
 204         { CMD_SYSBOOT,          "sysboot",      NULL,           sysboot_func }
 205 };
 206 
 207 /* global variables */
 208 
 209 /* set early in main(), never modified thereafter, used all over the place */
 210 static char *execname;
 211 static char target_brand[MAXNAMELEN];
 212 static char default_brand[MAXPATHLEN];
 213 static char *locale;
 214 char *target_zone;
 215 static char *target_uuid;
 216 char *username;
 217 
 218 char *
 219 cmd_to_str(int cmd_num)
 220 {
 221         assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
 222         return (cmdtab[cmd_num].cmd_name);
 223 }
 224 
 225 /* This is a separate function because of gettext() wrapping. */
 226 static char *
 227 long_help(int cmd_num)
 228 {
 229         assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
 230         switch (cmd_num) {
 231         case CMD_HELP:
 232                 return (gettext("Print usage message."));
 233         case CMD_BOOT:
 234                 return (gettext("Activates (boots) specified zone.  See "
 235                     "zoneadm(1m) for valid boot\n\targuments."));
 236         case CMD_HALT:
 237                 return (gettext("Halts specified zone, bypassing shutdown "
 238                     "scripts and removing runtime\n\tresources of the zone."));
 239         case CMD_READY:
 240                 return (gettext("Prepares a zone for running applications but "
 241                     "does not start any user\n\tprocesses in the zone."));
 242         case CMD_SHUTDOWN:
 243                 return (gettext("Gracefully shutdown the zone or reboot if "
 244                     "the '-r' option is specified.\n\t"
 245                     "See zoneadm(1m) for valid boot arguments."));
 246         case CMD_REBOOT:
 247                 return (gettext("Restarts the zone (equivalent to a halt / "
 248                     "boot sequence).\n\tFails if the zone is not active.  "
 249                     "See zoneadm(1m) for valid boot\n\targuments."));
 250         case CMD_LIST:
 251                 return (gettext("Lists the current zones, or a "
 252                     "specific zone if indicated.  By default,\n\tall "
 253                     "running zones are listed, though this can be "
 254                     "expanded to all\n\tinstalled zones with the -i "
 255                     "option or all configured zones with the\n\t-c "
 256                     "option.  When used with the general -z <zone> and/or -u "
 257                     "<uuid-match>\n\toptions, lists only the specified "
 258                     "matching zone, but lists it\n\tregardless of its state, "
 259                     "and the -i, -c, and -n options are disallowed.  The\n\t-v "
 260                     "option can be used to display verbose information: zone "
 261                     "name, id,\n\tcurrent state, root directory and options.  "
 262                     "The -p option can be used\n\tto request machine-parsable "
 263                     "output.  The -v and -p options are mutually\n\texclusive."
 264                     "  If neither -v nor -p is used, just the zone name is "
 265                     "listed."));
 266         case CMD_VERIFY:
 267                 return (gettext("Check to make sure the configuration "
 268                     "can safely be instantiated\n\ton the machine: "
 269                     "physical network interfaces exist, etc."));
 270         case CMD_INSTALL:
 271                 return (gettext("Install the configuration on to the system.  "
 272                     "All arguments are passed to the brand installation "
 273                     "function;\n\tsee brands(5) for more information."));
 274         case CMD_UNINSTALL:
 275                 return (gettext("Uninstall the configuration from the system.  "
 276                     "The -F flag can be used\n\tto force the action.  All "
 277                     "other arguments are passed to the brand\n\tuninstall "
 278                     "function; see brands(5) for more information."));
 279         case CMD_CLONE:
 280                 return (gettext("Clone the installation of another zone.  "
 281                     "The -m option can be used to\n\tspecify 'copy' which "
 282                     "forces a copy of the source zone.  The -s option\n\t"
 283                     "can be used to specify the name of a ZFS snapshot "
 284                     "that was taken from\n\ta previous clone command.  The "
 285                     "snapshot will be used as the source\n\tinstead of "
 286                     "creating a new ZFS snapshot.  All other arguments are "
 287                     "passed\n\tto the brand clone function; see "
 288                     "brands(5) for more information."));
 289         case CMD_MOVE:
 290                 return (gettext("Move the zone to a new zonepath."));
 291         case CMD_DETACH:
 292                 return (gettext("Detach the zone from the system. The zone "
 293                     "state is changed to\n\t'configured' (but the files under "
 294                     "the zonepath are untouched).\n\tThe zone can subsequently "
 295                     "be attached, or can be moved to another\n\tsystem and "
 296                     "attached there.  The -n option can be used to specify\n\t"
 297                     "'no-execute' mode.  When -n is used, the information "
 298                     "needed to attach\n\tthe zone is sent to standard output "
 299                     "but the zone is not actually\n\tdetached.  All other "
 300                     "arguments are passed to the brand detach function;\n\tsee "
 301                     "brands(5) for more information."));
 302         case CMD_ATTACH:
 303                 return (gettext("Attach the zone to the system.  The zone "
 304                     "state must be 'configured'\n\tprior to attach; upon "
 305                     "successful completion, the zone state will be\n\t"
 306                     "'installed'.  The system software on the current "
 307                     "system must be\n\tcompatible with the software on the "
 308                     "zone's original system.\n\tSpecify -F "
 309                     "to force the attach and skip software compatibility "
 310                     "tests.\n\tThe -n option can be used to specify "
 311                     "'no-execute' mode.  When -n is\n\tused, the information "
 312                     "needed to attach the zone is read from the\n\tspecified "
 313                     "path and the configuration is only validated.  The path "
 314                     "can\n\tbe '-' to specify standard input.  The -F and -n "
 315                     "options are mutually\n\texclusive.  All other arguments "
 316                     "are passed to the brand attach\n\tfunction; see "
 317                     "brands(5) for more information."));
 318         case CMD_MARK:
 319                 return (gettext("Set the state of the zone.  This can be used "
 320                     "to force the zone\n\tstate to 'incomplete' "
 321                     "administratively if some activity has rendered\n\tthe "
 322                     "zone permanently unusable.  The only valid state that "
 323                     "may be\n\tspecified is 'incomplete'."));
 324         default:
 325                 return ("");
 326         }
 327         /* NOTREACHED */
 328         return (NULL);
 329 }
 330 
 331 /*
 332  * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
 333  * unexpected errors.
 334  */
 335 
 336 static int
 337 usage(boolean_t explicit)
 338 {
 339         int i;
 340         FILE *fd = explicit ? stdout : stderr;
 341 
 342         (void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
 343         (void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
 344             execname);
 345         (void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
 346             gettext("subcommand"));
 347         (void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
 348         for (i = CMD_MIN; i <= CMD_MAX; i++) {
 349                 if (cmdtab[i].short_usage == NULL)
 350                         continue;
 351                 (void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
 352                 if (explicit)
 353                         (void) fprintf(fd, "\t%s\n\n", long_help(i));
 354         }
 355         if (!explicit)
 356                 (void) fputs("\n", fd);
 357         return (Z_USAGE);
 358 }
 359 
 360 static void
 361 sub_usage(char *short_usage, int cmd_num)
 362 {
 363         (void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
 364         (void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
 365 }
 366 
 367 /*
 368  * zperror() is like perror(3c) except that this also prints the executable
 369  * name at the start of the message, and takes a boolean indicating whether
 370  * to call libc'c strerror() or that from libzonecfg.
 371  */
 372 
 373 void
 374 zperror(const char *str, boolean_t zonecfg_error)
 375 {
 376         (void) fprintf(stderr, "%s: %s: %s\n", execname, str,
 377             zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
 378 }
 379 
 380 /*
 381  * zperror2() is very similar to zperror() above, except it also prints a
 382  * supplied zone name after the executable.
 383  *
 384  * All current consumers of this function want libzonecfg's strerror() rather
 385  * than libc's; if this ever changes, this function can be made more generic
 386  * like zperror() above.
 387  */
 388 
 389 void
 390 zperror2(const char *zone, const char *str)
 391 {
 392         (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
 393             zonecfg_strerror(errno));
 394 }
 395 
 396 /* PRINTFLIKE1 */
 397 void
 398 zerror(const char *fmt, ...)
 399 {
 400         va_list alist;
 401 
 402         va_start(alist, fmt);
 403         (void) fprintf(stderr, "%s: ", execname);
 404         if (target_zone != NULL)
 405                 (void) fprintf(stderr, "zone '%s': ", target_zone);
 406         (void) vfprintf(stderr, fmt, alist);
 407         (void) fprintf(stderr, "\n");
 408         va_end(alist);
 409 }
 410 
 411 static void *
 412 safe_calloc(size_t nelem, size_t elsize)
 413 {
 414         void *r = calloc(nelem, elsize);
 415 
 416         if (r == NULL) {
 417                 zerror(gettext("failed to allocate %lu bytes: %s"),
 418                     (ulong_t)nelem * elsize, strerror(errno));
 419                 exit(Z_ERR);
 420         }
 421         return (r);
 422 }
 423 
 424 static void
 425 zone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
 426 {
 427         static boolean_t firsttime = B_TRUE;
 428         char *ip_type_str;
 429 
 430         /* Skip a zone that shutdown while we were collecting data. */
 431         if (zent->zname[0] == '\0')
 432                 return;
 433 
 434         if (zent->ziptype == ZS_EXCLUSIVE)
 435                 ip_type_str = "excl";
 436         else
 437                 ip_type_str = "shared";
 438 
 439         assert(!(verbose && parsable));
 440         if (firsttime && verbose) {
 441                 firsttime = B_FALSE;
 442                 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
 443                     ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
 444                     "IP");
 445         }
 446         if (!verbose) {
 447                 char *cp, *clim;
 448                 char zdid[80];
 449 
 450                 if (!parsable) {
 451                         (void) printf("%s\n", zent->zname);
 452                         return;
 453                 }
 454                 if (zent->zid == ZONE_ID_UNDEFINED)
 455                         (void) printf("-");
 456                 else
 457                         (void) printf("%lu", zent->zid);
 458                 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
 459                 cp = zent->zroot;
 460                 while ((clim = strchr(cp, ':')) != NULL) {
 461                         (void) printf("%.*s\\:", clim - cp, cp);
 462                         cp = clim + 1;
 463                 }
 464                 if (zent->zdid == -1)
 465                         zdid[0] = '\0';
 466                 else
 467                         (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid);
 468                 (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
 469                     ip_type_str, zdid);
 470                 return;
 471         }
 472         if (zent->zstate_str != NULL) {
 473                 if (zent->zid == ZONE_ID_UNDEFINED)
 474                         (void) printf("%*s", ZONEID_WIDTH, "-");
 475                 else
 476                         (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
 477                 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
 478                     zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
 479         }
 480 }
 481 
 482 static int
 483 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
 484 {
 485         char root[MAXPATHLEN], *cp;
 486         int err;
 487         uuid_t uuid;
 488         zone_dochandle_t handle;
 489 
 490         (void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
 491         (void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
 492         (void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand));
 493         zent->zstate_str = "???";
 494 
 495         zent->zid = zid;
 496 
 497         if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
 498             !uuid_is_null(uuid))
 499                 uuid_unparse(uuid, zent->zuuid);
 500         else
 501                 zent->zuuid[0] = '\0';
 502 
 503         /*
 504          * For labeled zones which query the zone path of lower-level
 505          * zones, the path needs to be adjusted to drop the final
 506          * "/root" component. This adjusted path is then useful
 507          * for reading down any exported directories from the
 508          * lower-level zone.
 509          */
 510         if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
 511                 if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
 512                     sizeof (zent->zroot)) == -1) {
 513                         zperror2(zent->zname,
 514                             gettext("could not get zone path."));
 515                         return (Z_ERR);
 516                 }
 517                 cp = zent->zroot + strlen(zent->zroot) - 5;
 518                 if (cp > zent->zroot && strcmp(cp, "/root") == 0)
 519                         *cp = 0;
 520         } else {
 521                 if ((err = zone_get_zonepath(zent->zname, root,
 522                     sizeof (root))) != Z_OK) {
 523                         errno = err;
 524                         zperror2(zent->zname,
 525                             gettext("could not get zone path."));
 526                         return (Z_ERR);
 527                 }
 528                 (void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
 529         }
 530 
 531         if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
 532                 errno = err;
 533                 zperror2(zent->zname, gettext("could not get state"));
 534                 return (Z_ERR);
 535         }
 536         zent->zstate_str = zone_state_str(zent->zstate_num);
 537 
 538         /*
 539          * A zone's brand is only available in the .xml file describing it,
 540          * which is only visible to the global zone.  This causes
 541          * zone_get_brand() to fail when called from within a non-global
 542          * zone.  Fortunately we only do this on labeled systems, where we
 543          * know all zones are native.
 544          */
 545         if (getzoneid() != GLOBAL_ZONEID) {
 546                 assert(is_system_labeled() != 0);
 547                 (void) strlcpy(zent->zbrand, default_brand,
 548                     sizeof (zent->zbrand));
 549         } else if (zone_get_brand(zent->zname, zent->zbrand,
 550             sizeof (zent->zbrand)) != Z_OK) {
 551                 zperror2(zent->zname, gettext("could not get brand name"));
 552                 return (Z_ERR);
 553         }
 554 
 555         /*
 556          * Get ip type of the zone.
 557          * Note for global zone, ZS_SHARED is set always.
 558          */
 559         if (zid == GLOBAL_ZONEID) {
 560                 zent->ziptype = ZS_SHARED;
 561                 return (Z_OK);
 562         }
 563 
 564         if ((handle = zonecfg_init_handle()) == NULL) {
 565                 zperror2(zent->zname, gettext("could not init handle"));
 566                 return (Z_ERR);
 567         }
 568         if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
 569                 zperror2(zent->zname, gettext("could not get handle"));
 570                 zonecfg_fini_handle(handle);
 571                 return (Z_ERR);
 572         }
 573 
 574         if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
 575                 zperror2(zent->zname, gettext("could not get ip-type"));
 576                 zonecfg_fini_handle(handle);
 577                 return (Z_ERR);
 578         }
 579 
 580         /*
 581          * There is a race condition where the zone could boot while
 582          * we're walking the index file.  In this case the zone state
 583          * could be seen as running from the call above, but the zoneid
 584          * would be undefined.
 585          *
 586          * There is also a race condition where the zone could shutdown after
 587          * we got its running state above.  This is also not an error and
 588          * we fall back to getting the ziptype from the zone configuration.
 589          */
 590         if (zent->zstate_num == ZONE_STATE_RUNNING &&
 591             zid != ZONE_ID_UNDEFINED) {
 592                 ushort_t flags;
 593 
 594                 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
 595                     sizeof (flags)) >= 0) {
 596                         if (flags & ZF_NET_EXCL)
 597                                 zent->ziptype = ZS_EXCLUSIVE;
 598                         else
 599                                 zent->ziptype = ZS_SHARED;
 600                 }
 601         }
 602 
 603         zent->zdid = zonecfg_get_did(handle);
 604 
 605         zonecfg_fini_handle(handle);
 606 
 607         return (Z_OK);
 608 }
 609 
 610 /*
 611  * fetch_zents() calls zone_list(2) to find out how many zones are running
 612  * (which is stored in the global nzents), then calls zone_list(2) again
 613  * to fetch the list of running zones (stored in the global zents).  This
 614  * function may be called multiple times, so if zents is already set, we
 615  * return immediately to save work.
 616  *
 617  * Note that the data about running zones can change while this function
 618  * is running, so its possible that the list of zones will have empty slots
 619  * at the end.
 620  */
 621 
 622 static int
 623 fetch_zents(void)
 624 {
 625         zoneid_t *zids = NULL;
 626         uint_t nzents_saved;
 627         int i, retv;
 628         FILE *fp;
 629         boolean_t inaltroot;
 630         zone_entry_t *zentp;
 631         const char *altroot;
 632 
 633         if (nzents > 0)
 634                 return (Z_OK);
 635 
 636         if (zone_list(NULL, &nzents) != 0) {
 637                 zperror(gettext("failed to get zoneid list"), B_FALSE);
 638                 return (Z_ERR);
 639         }
 640 
 641 again:
 642         if (nzents == 0)
 643                 return (Z_OK);
 644 
 645         zids = safe_calloc(nzents, sizeof (zoneid_t));
 646         nzents_saved = nzents;
 647 
 648         if (zone_list(zids, &nzents) != 0) {
 649                 zperror(gettext("failed to get zone list"), B_FALSE);
 650                 free(zids);
 651                 return (Z_ERR);
 652         }
 653         if (nzents != nzents_saved) {
 654                 /* list changed, try again */
 655                 free(zids);
 656                 goto again;
 657         }
 658 
 659         zents = safe_calloc(nzents, sizeof (zone_entry_t));
 660 
 661         inaltroot = zonecfg_in_alt_root();
 662         if (inaltroot) {
 663                 fp = zonecfg_open_scratch("", B_FALSE);
 664                 altroot = zonecfg_get_root();
 665         } else {
 666                 fp = NULL;
 667         }
 668         zentp = zents;
 669         retv = Z_OK;
 670         for (i = 0; i < nzents; i++) {
 671                 char name[ZONENAME_MAX];
 672                 char altname[ZONENAME_MAX];
 673                 char rev_altroot[MAXPATHLEN];
 674 
 675                 if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
 676                         /*
 677                          * There is a race condition where the zone may have
 678                          * shutdown since we retrieved the number of running
 679                          * zones above.  This is not an error, there will be
 680                          * an empty slot at the end of the list.
 681                          */
 682                         continue;
 683                 }
 684                 if (zonecfg_is_scratch(name)) {
 685                         /* Ignore scratch zones by default */
 686                         if (!inaltroot)
 687                                 continue;
 688                         if (fp == NULL ||
 689                             zonecfg_reverse_scratch(fp, name, altname,
 690                             sizeof (altname), rev_altroot,
 691                             sizeof (rev_altroot)) == -1) {
 692                                 zerror(gettext("could not resolve scratch "
 693                                     "zone %s"), name);
 694                                 retv = Z_ERR;
 695                                 continue;
 696                         }
 697                         /* Ignore zones in other alternate roots */
 698                         if (strcmp(rev_altroot, altroot) != 0)
 699                                 continue;
 700                         (void) strcpy(name, altname);
 701                 } else {
 702                         /* Ignore non-scratch when in an alternate root */
 703                         if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
 704                                 continue;
 705                 }
 706                 if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
 707                         /*
 708                          * There is a race condition where the zone may have
 709                          * shutdown since we retrieved the number of running
 710                          * zones above.  This is not an error, there will be
 711                          * an empty slot at the end of the list.
 712                          */
 713                         continue;
 714                 }
 715                 zentp++;
 716         }
 717         nzents = zentp - zents;
 718         if (fp != NULL)
 719                 zonecfg_close_scratch(fp);
 720 
 721         free(zids);
 722         return (retv);
 723 }
 724 
 725 static int
 726 zone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable,
 727     boolean_t exclude_global)
 728 {
 729         int i;
 730         zone_entry_t zent;
 731         FILE *cookie;
 732         char *name;
 733 
 734         /*
 735          * First get the list of running zones from the kernel and print them.
 736          * If that is all we need, then return.
 737          */
 738         if ((i = fetch_zents()) != Z_OK) {
 739                 /*
 740                  * No need for error messages; fetch_zents() has already taken
 741                  * care of this.
 742                  */
 743                 return (i);
 744         }
 745         for (i = 0; i < nzents; i++) {
 746                 if (exclude_global && zents[i].zid == GLOBAL_ZONEID)
 747                         continue;
 748                 zone_print(&zents[i], verbose, parsable);
 749         }
 750         if (min_state >= ZONE_STATE_RUNNING)
 751                 return (Z_OK);
 752         /*
 753          * Next, get the full list of zones from the configuration, skipping
 754          * any we have already printed.
 755          */
 756         cookie = setzoneent();
 757         while ((name = getzoneent(cookie)) != NULL) {
 758                 for (i = 0; i < nzents; i++) {
 759                         if (strcmp(zents[i].zname, name) == 0)
 760                                 break;
 761                 }
 762                 if (i < nzents) {
 763                         free(name);
 764                         continue;
 765                 }
 766                 if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
 767                         free(name);
 768                         continue;
 769                 }
 770                 free(name);
 771                 if (zent.zstate_num >= min_state)
 772                         zone_print(&zent, verbose, parsable);
 773         }
 774         endzoneent(cookie);
 775         return (Z_OK);
 776 }
 777 
 778 /*
 779  * Retrieve a zone entry by name.  Returns NULL if no such zone exists.
 780  */
 781 static zone_entry_t *
 782 lookup_running_zone(const char *str)
 783 {
 784         int i;
 785 
 786         if (fetch_zents() != Z_OK)
 787                 return (NULL);
 788 
 789         for (i = 0; i < nzents; i++) {
 790                 if (strcmp(str, zents[i].zname) == 0)
 791                         return (&zents[i]);
 792         }
 793         return (NULL);
 794 }
 795 
 796 /*
 797  * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
 798  * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
 799  */
 800 static boolean_t
 801 bad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
 802 {
 803         char *str;
 804 
 805         assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
 806             bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
 807             bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
 808         /*
 809          * TRANSLATION_NOTE
 810          * The strings below will be used as part of a larger message,
 811          * either:
 812          * (file name) must be (owner|group|world) (read|writ|execut)able
 813          * or
 814          * (file name) must not be (owner|group|world) (read|writ|execut)able
 815          */
 816         switch (bit) {
 817         case S_IRUSR:
 818                 str = gettext("owner readable");
 819                 break;
 820         case S_IWUSR:
 821                 str = gettext("owner writable");
 822                 break;
 823         case S_IXUSR:
 824                 str = gettext("owner executable");
 825                 break;
 826         case S_IRGRP:
 827                 str = gettext("group readable");
 828                 break;
 829         case S_IWGRP:
 830                 str = gettext("group writable");
 831                 break;
 832         case S_IXGRP:
 833                 str = gettext("group executable");
 834                 break;
 835         case S_IROTH:
 836                 str = gettext("world readable");
 837                 break;
 838         case S_IWOTH:
 839                 str = gettext("world writable");
 840                 break;
 841         case S_IXOTH:
 842                 str = gettext("world executable");
 843                 break;
 844         }
 845         if ((mode & bit) == (on ? 0 : bit)) {
 846                 /*
 847                  * TRANSLATION_NOTE
 848                  * The first parameter below is a file name; the second
 849                  * is one of the "(owner|group|world) (read|writ|execut)able"
 850                  * strings from above.
 851                  */
 852                 /*
 853                  * The code below could be simplified but not in a way
 854                  * that would easily translate to non-English locales.
 855                  */
 856                 if (on) {
 857                         (void) fprintf(stderr, gettext("%s must be %s.\n"),
 858                             file, str);
 859                 } else {
 860                         (void) fprintf(stderr, gettext("%s must not be %s.\n"),
 861                             file, str);
 862                 }
 863                 return (B_TRUE);
 864         }
 865         return (B_FALSE);
 866 }
 867 
 868 /*
 869  * We want to make sure that no zone has its zone path as a child node
 870  * (in the directory sense) of any other.  We do that by comparing this
 871  * zone's path to the path of all other (non-global) zones.  The comparison
 872  * in each case is simple: add '/' to the end of the path, then do a
 873  * strncmp() of the two paths, using the length of the shorter one.
 874  */
 875 
 876 static int
 877 crosscheck_zonepaths(char *path)
 878 {
 879         char rpath[MAXPATHLEN];         /* resolved path */
 880         char path_copy[MAXPATHLEN];     /* copy of original path */
 881         char rpath_copy[MAXPATHLEN];    /* copy of original rpath */
 882         struct zoneent *ze;
 883         int res, err;
 884         FILE *cookie;
 885 
 886         cookie = setzoneent();
 887         while ((ze = getzoneent_private(cookie)) != NULL) {
 888                 /* Skip zones which are not installed. */
 889                 if (ze->zone_state < ZONE_STATE_INSTALLED) {
 890                         free(ze);
 891                         continue;
 892                 }
 893                 /* Skip the global zone and the current target zone. */
 894                 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
 895                     strcmp(ze->zone_name, target_zone) == 0) {
 896                         free(ze);
 897                         continue;
 898                 }
 899                 if (strlen(ze->zone_path) == 0) {
 900                         /* old index file without path, fall back */
 901                         if ((err = zone_get_zonepath(ze->zone_name,
 902                             ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
 903                                 errno = err;
 904                                 zperror2(ze->zone_name,
 905                                     gettext("could not get zone path"));
 906                                 free(ze);
 907                                 continue;
 908                         }
 909                 }
 910                 (void) snprintf(path_copy, sizeof (path_copy), "%s%s",
 911                     zonecfg_get_root(), ze->zone_path);
 912                 res = resolvepath(path_copy, rpath, sizeof (rpath));
 913                 if (res == -1) {
 914                         if (errno != ENOENT) {
 915                                 zperror(path_copy, B_FALSE);
 916                                 free(ze);
 917                                 return (Z_ERR);
 918                         }
 919                         (void) printf(gettext("WARNING: zone %s is installed, "
 920                             "but its %s %s does not exist.\n"), ze->zone_name,
 921                             "zonepath", path_copy);
 922                         free(ze);
 923                         continue;
 924                 }
 925                 rpath[res] = '\0';
 926                 (void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
 927                 (void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
 928                 if (strncmp(path_copy, rpath_copy,
 929                     min(strlen(path_copy), strlen(rpath_copy))) == 0) {
 930                         /*
 931                          * TRANSLATION_NOTE
 932                          * zonepath is a literal that should not be translated.
 933                          */
 934                         (void) fprintf(stderr, gettext("%s zonepath (%s) and "
 935                             "%s zonepath (%s) overlap.\n"),
 936                             target_zone, path, ze->zone_name, rpath);
 937                         free(ze);
 938                         return (Z_ERR);
 939                 }
 940                 free(ze);
 941         }
 942         endzoneent(cookie);
 943         return (Z_OK);
 944 }
 945 
 946 static int
 947 validate_zonepath(char *path, int cmd_num)
 948 {
 949         int res;                        /* result of last library/system call */
 950         boolean_t err = B_FALSE;        /* have we run into an error? */
 951         struct stat stbuf;
 952         struct statvfs64 vfsbuf;
 953         char rpath[MAXPATHLEN];         /* resolved path */
 954         char ppath[MAXPATHLEN];         /* parent path */
 955         char rppath[MAXPATHLEN];        /* resolved parent path */
 956         char rootpath[MAXPATHLEN];      /* root path */
 957         zone_state_t state;
 958 
 959         if (path[0] != '/') {
 960                 (void) fprintf(stderr,
 961                     gettext("%s is not an absolute path.\n"), path);
 962                 return (Z_ERR);
 963         }
 964         if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
 965                 if ((errno != ENOENT) ||
 966                     (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
 967                     cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
 968                         zperror(path, B_FALSE);
 969                         return (Z_ERR);
 970                 }
 971                 if (cmd_num == CMD_VERIFY) {
 972                         /*
 973                          * TRANSLATION_NOTE
 974                          * zoneadm is a literal that should not be translated.
 975                          */
 976                         (void) fprintf(stderr, gettext("WARNING: %s does not "
 977                             "exist, so it could not be verified.\nWhen "
 978                             "'zoneadm %s' is run, '%s' will try to create\n%s, "
 979                             "and '%s' will be tried again,\nbut the '%s' may "
 980                             "fail if:\nthe parent directory of %s is group- or "
 981                             "other-writable\nor\n%s overlaps with any other "
 982                             "installed zones.\n"), path,
 983                             cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
 984                             path, cmd_to_str(CMD_VERIFY),
 985                             cmd_to_str(CMD_VERIFY), path, path);
 986                         return (Z_OK);
 987                 }
 988                 /*
 989                  * The zonepath is supposed to be mode 700 but its
 990                  * parent(s) 755.  So use 755 on the mkdirp() then
 991                  * chmod() the zonepath itself to 700.
 992                  */
 993                 if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
 994                         zperror(path, B_FALSE);
 995                         return (Z_ERR);
 996                 }
 997                 /*
 998                  * If the chmod() fails, report the error, but might
 999                  * as well continue the verify procedure.
1000                  */
1001                 if (chmod(path, S_IRWXU) != 0)
1002                         zperror(path, B_FALSE);
1003                 /*
1004                  * Since the mkdir() succeeded, we should not have to
1005                  * worry about a subsequent ENOENT, thus this should
1006                  * only recurse once.
1007                  */
1008                 return (validate_zonepath(path, cmd_num));
1009         }
1010         rpath[res] = '\0';
1011         if (strcmp(path, rpath) != 0) {
1012                 errno = Z_RESOLVED_PATH;
1013                 zperror(path, B_TRUE);
1014                 return (Z_ERR);
1015         }
1016         if ((res = stat(rpath, &stbuf)) != 0) {
1017                 zperror(rpath, B_FALSE);
1018                 return (Z_ERR);
1019         }
1020         if (!S_ISDIR(stbuf.st_mode)) {
1021                 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
1022                     rpath);
1023                 return (Z_ERR);
1024         }
1025         if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) {
1026                 (void) printf(gettext("WARNING: %s is on a temporary "
1027                     "file system.\n"), rpath);
1028         }
1029         if (crosscheck_zonepaths(rpath) != Z_OK)
1030                 return (Z_ERR);
1031         /*
1032          * Try to collect and report as many minor errors as possible
1033          * before returning, so the user can learn everything that needs
1034          * to be fixed up front.
1035          */
1036         if (stbuf.st_uid != 0) {
1037                 (void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1038                     rpath);
1039                 err = B_TRUE;
1040 
1041                 /* Try to change owner */
1042                 if (cmd_num != CMD_VERIFY) {
1043                         (void) fprintf(stderr, gettext("%s: changing owner "
1044                             "to root.\n"), rpath);
1045                         if (chown(rpath, 0, -1) != 0) {
1046                                 zperror(rpath, B_FALSE);
1047                                 return (Z_ERR);
1048                         } else {
1049                                 err = B_FALSE;
1050                         }
1051                 }
1052         }
1053         err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
1054         err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
1055         err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
1056         err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
1057         err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
1058         err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
1059         err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
1060         err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
1061         err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
1062 
1063         /* If the group perms are wrong, fix them */
1064         if (err && (cmd_num != CMD_VERIFY)) {
1065                 (void) fprintf(stderr, gettext("%s: changing permissions "
1066                     "to 0700.\n"), rpath);
1067                 if (chmod(rpath, S_IRWXU) != 0) {
1068                         zperror(path, B_FALSE);
1069                 } else {
1070                         err = B_FALSE;
1071                 }
1072         }
1073 
1074         (void) snprintf(ppath, sizeof (ppath), "%s/..", path);
1075         if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
1076                 zperror(ppath, B_FALSE);
1077                 return (Z_ERR);
1078         }
1079         rppath[res] = '\0';
1080         if ((res = stat(rppath, &stbuf)) != 0) {
1081                 zperror(rppath, B_FALSE);
1082                 return (Z_ERR);
1083         }
1084         /* theoretically impossible */
1085         if (!S_ISDIR(stbuf.st_mode)) {
1086                 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
1087                     rppath);
1088                 return (Z_ERR);
1089         }
1090         if (stbuf.st_uid != 0) {
1091                 (void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1092                     rppath);
1093                 err = B_TRUE;
1094         }
1095         err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
1096         err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
1097         err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
1098         err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
1099         err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
1100         if (strcmp(rpath, rppath) == 0) {
1101                 (void) fprintf(stderr, gettext("%s is its own parent.\n"),
1102                     rppath);
1103                 err = B_TRUE;
1104         }
1105 
1106         if (statvfs64(rpath, &vfsbuf) != 0) {
1107                 zperror(rpath, B_FALSE);
1108                 return (Z_ERR);
1109         }
1110         if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
1111                 /*
1112                  * TRANSLATION_NOTE
1113                  * Zonepath and NFS are literals that should not be translated.
1114                  */
1115                 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
1116                     "mounted file system.\n"
1117                     "\tA local file system must be used.\n"), rpath);
1118                 return (Z_ERR);
1119         }
1120         if (vfsbuf.f_flag & ST_NOSUID) {
1121                 /*
1122                  * TRANSLATION_NOTE
1123                  * Zonepath and nosuid are literals that should not be
1124                  * translated.
1125                  */
1126                 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
1127                     "file system.\n"), rpath);
1128                 return (Z_ERR);
1129         }
1130 
1131         if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
1132                 errno = res;
1133                 zperror2(target_zone, gettext("could not get state"));
1134                 return (Z_ERR);
1135         }
1136         /*
1137          * The existence of the root path is only bad in the configured state,
1138          * as it is *supposed* to be there at the installed and later states.
1139          * However, the root path is expected to be there if the zone is
1140          * detached.
1141          * State/command mismatches are caught earlier in verify_details().
1142          */
1143         if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1144                 if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1145                     sizeof (rootpath)) {
1146                         /*
1147                          * TRANSLATION_NOTE
1148                          * Zonepath is a literal that should not be translated.
1149                          */
1150                         (void) fprintf(stderr,
1151                             gettext("Zonepath %s is too long.\n"), rpath);
1152                         return (Z_ERR);
1153                 }
1154                 if ((res = stat(rootpath, &stbuf)) == 0) {
1155                         if (zonecfg_detached(rpath)) {
1156                                 (void) fprintf(stderr,
1157                                     gettext("Cannot %s detached "
1158                                     "zone.\nUse attach or remove %s "
1159                                     "directory.\n"), cmd_to_str(cmd_num),
1160                                     rpath);
1161                                 return (Z_ERR);
1162                         }
1163 
1164                         /* Not detached, check if it really looks ok. */
1165 
1166                         if (!S_ISDIR(stbuf.st_mode)) {
1167                                 (void) fprintf(stderr, gettext("%s is not a "
1168                                     "directory.\n"), rootpath);
1169                                 return (Z_ERR);
1170                         }
1171 
1172                         if (stbuf.st_uid != 0) {
1173                                 (void) fprintf(stderr, gettext("%s is not "
1174                                     "owned by root.\n"), rootpath);
1175                                 return (Z_ERR);
1176                         }
1177 
1178                         if ((stbuf.st_mode & 0777) != 0755) {
1179                                 (void) fprintf(stderr, gettext("%s mode is not "
1180                                     "0755.\n"), rootpath);
1181                                 return (Z_ERR);
1182                         }
1183                 }
1184         }
1185 
1186         return (err ? Z_ERR : Z_OK);
1187 }
1188 
1189 static int
1190 invoke_brand_handler(int cmd_num, char *argv[])
1191 {
1192         zone_dochandle_t handle;
1193         int err;
1194 
1195         if ((handle = zonecfg_init_handle()) == NULL) {
1196                 zperror(cmd_to_str(cmd_num), B_TRUE);
1197                 return (Z_ERR);
1198         }
1199         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1200                 errno = err;
1201                 zperror(cmd_to_str(cmd_num), B_TRUE);
1202                 zonecfg_fini_handle(handle);
1203                 return (Z_ERR);
1204         }
1205         if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1206                 zonecfg_fini_handle(handle);
1207                 return (Z_ERR);
1208         }
1209         zonecfg_fini_handle(handle);
1210         return (Z_OK);
1211 }
1212 
1213 static int
1214 ready_func(int argc, char *argv[])
1215 {
1216         zone_cmd_arg_t zarg;
1217         int arg;
1218 
1219         if (zonecfg_in_alt_root()) {
1220                 zerror(gettext("cannot ready zone in alternate root"));
1221                 return (Z_ERR);
1222         }
1223 
1224         optind = 0;
1225         if ((arg = getopt(argc, argv, "?")) != EOF) {
1226                 switch (arg) {
1227                 case '?':
1228                         sub_usage(SHELP_READY, CMD_READY);
1229                         return (optopt == '?' ? Z_OK : Z_USAGE);
1230                 default:
1231                         sub_usage(SHELP_READY, CMD_READY);
1232                         return (Z_USAGE);
1233                 }
1234         }
1235         if (argc > optind) {
1236                 sub_usage(SHELP_READY, CMD_READY);
1237                 return (Z_USAGE);
1238         }
1239         if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE)
1240             != Z_OK)
1241                 return (Z_ERR);
1242         if (verify_details(CMD_READY, argv) != Z_OK)
1243                 return (Z_ERR);
1244 
1245         zarg.cmd = Z_READY;
1246         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
1247                 zerror(gettext("call to %s failed"), "zoneadmd");
1248                 return (Z_ERR);
1249         }
1250         return (Z_OK);
1251 }
1252 
1253 static int
1254 boot_func(int argc, char *argv[])
1255 {
1256         zone_cmd_arg_t zarg;
1257         boolean_t force = B_FALSE;
1258         int arg;
1259 
1260         if (zonecfg_in_alt_root()) {
1261                 zerror(gettext("cannot boot zone in alternate root"));
1262                 return (Z_ERR);
1263         }
1264 
1265         zarg.bootbuf[0] = '\0';
1266 
1267         /*
1268          * The following getopt processes arguments to zone boot; that
1269          * is to say, the [here] portion of the argument string:
1270          *
1271          *      zoneadm -z myzone boot [here] -- -v -m verbose
1272          *
1273          * Where [here] can either be nothing, -? (in which case we bail
1274          * and print usage), -f (a private option to indicate that the
1275          * boot operation should be 'forced'), or -s.  Support for -s is
1276          * vestigal and obsolete, but is retained because it was a
1277          * documented interface and there are known consumers including
1278          * admin/install; the proper way to specify boot arguments like -s
1279          * is:
1280          *
1281          *      zoneadm -z myzone boot -- -s -v -m verbose.
1282          */
1283         optind = 0;
1284         while ((arg = getopt(argc, argv, "?fs")) != EOF) {
1285                 switch (arg) {
1286                 case '?':
1287                         sub_usage(SHELP_BOOT, CMD_BOOT);
1288                         return (optopt == '?' ? Z_OK : Z_USAGE);
1289                 case 's':
1290                         (void) strlcpy(zarg.bootbuf, "-s",
1291                             sizeof (zarg.bootbuf));
1292                         break;
1293                 case 'f':
1294                         force = B_TRUE;
1295                         break;
1296                 default:
1297                         sub_usage(SHELP_BOOT, CMD_BOOT);
1298                         return (Z_USAGE);
1299                 }
1300         }
1301 
1302         for (; optind < argc; optind++) {
1303                 if (strlcat(zarg.bootbuf, argv[optind],
1304                     sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1305                         zerror(gettext("Boot argument list too long"));
1306                         return (Z_ERR);
1307                 }
1308                 if (optind < argc - 1)
1309                         if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1310                             sizeof (zarg.bootbuf)) {
1311                                 zerror(gettext("Boot argument list too long"));
1312                                 return (Z_ERR);
1313                         }
1314         }
1315         if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force)
1316             != Z_OK)
1317                 return (Z_ERR);
1318         if (verify_details(CMD_BOOT, argv) != Z_OK)
1319                 return (Z_ERR);
1320         zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT;
1321         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
1322                 zerror(gettext("call to %s failed"), "zoneadmd");
1323                 return (Z_ERR);
1324         }
1325 
1326         return (Z_OK);
1327 }
1328 
1329 static void
1330 fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
1331 {
1332         ssize_t result;
1333         uuid_t uuid;
1334         FILE *fp;
1335         ushort_t flags;
1336 
1337         (void) memset(zeptr, 0, sizeof (*zeptr));
1338 
1339         zeptr->zid = zid;
1340 
1341         /*
1342          * Since we're looking up our own (non-global) zone name,
1343          * we can be assured that it will succeed.
1344          */
1345         result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
1346         assert(result >= 0);
1347         if (zonecfg_is_scratch(zeptr->zname) &&
1348             (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
1349                 (void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
1350                     sizeof (zeptr->zname), NULL, 0);
1351                 zonecfg_close_scratch(fp);
1352         }
1353 
1354         if (is_system_labeled()) {
1355                 (void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
1356                     sizeof (zeptr->zroot));
1357                 (void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME,
1358                     sizeof (zeptr->zbrand));
1359         } else {
1360                 (void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
1361                 (void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand,
1362                     sizeof (zeptr->zbrand));
1363         }
1364 
1365         zeptr->zstate_str = "running";
1366         if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
1367             !uuid_is_null(uuid))
1368                 uuid_unparse(uuid, zeptr->zuuid);
1369 
1370         if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
1371                 zperror2(zeptr->zname, gettext("could not get zone flags"));
1372                 exit(Z_ERR);
1373         }
1374         if (flags & ZF_NET_EXCL)
1375                 zeptr->ziptype = ZS_EXCLUSIVE;
1376         else
1377                 zeptr->ziptype = ZS_SHARED;
1378 }
1379 
1380 static int
1381 list_func(int argc, char *argv[])
1382 {
1383         zone_entry_t *zentp, zent;
1384         int arg, retv;
1385         boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE,
1386             exclude_global = B_FALSE;
1387         zone_state_t min_state = ZONE_STATE_RUNNING;
1388         zoneid_t zone_id = getzoneid();
1389 
1390         if (target_zone == NULL) {
1391                 /* all zones: default view to running but allow override */
1392                 optind = 0;
1393                 while ((arg = getopt(argc, argv, "?cinpv")) != EOF) {
1394                         switch (arg) {
1395                         case '?':
1396                                 sub_usage(SHELP_LIST, CMD_LIST);
1397                                 return (optopt == '?' ? Z_OK : Z_USAGE);
1398                                 /*
1399                                  * The 'i' and 'c' options are not mutually
1400                                  * exclusive so if 'c' is given, then min_state
1401                                  * is set to 0 (ZONE_STATE_CONFIGURED) which is
1402                                  * the lowest possible state.  If 'i' is given,
1403                                  * then min_state is set to be the lowest state
1404                                  * so far.
1405                                  */
1406                         case 'c':
1407                                 min_state = ZONE_STATE_CONFIGURED;
1408                                 break;
1409                         case 'i':
1410                                 min_state = min(ZONE_STATE_INSTALLED,
1411                                     min_state);
1412 
1413                                 break;
1414                         case 'n':
1415                                 exclude_global = B_TRUE;
1416                                 break;
1417                         case 'p':
1418                                 parsable = B_TRUE;
1419                                 break;
1420                         case 'v':
1421                                 verbose = B_TRUE;
1422                                 break;
1423                         default:
1424                                 sub_usage(SHELP_LIST, CMD_LIST);
1425                                 return (Z_USAGE);
1426                         }
1427                 }
1428                 if (parsable && verbose) {
1429                         zerror(gettext("%s -p and -v are mutually exclusive."),
1430                             cmd_to_str(CMD_LIST));
1431                         return (Z_ERR);
1432                 }
1433                 if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
1434                         retv = zone_print_list(min_state, verbose, parsable,
1435                             exclude_global);
1436                 } else {
1437                         fake_up_local_zone(zone_id, &zent);
1438                         retv = Z_OK;
1439                         zone_print(&zent, verbose, parsable);
1440                 }
1441                 return (retv);
1442         }
1443 
1444         /*
1445          * Specific target zone: disallow -i/-c/-n suboptions.
1446          */
1447         optind = 0;
1448         while ((arg = getopt(argc, argv, "?pv")) != EOF) {
1449                 switch (arg) {
1450                 case '?':
1451                         sub_usage(SHELP_LIST, CMD_LIST);
1452                         return (optopt == '?' ? Z_OK : Z_USAGE);
1453                 case 'p':
1454                         parsable = B_TRUE;
1455                         break;
1456                 case 'v':
1457                         verbose = B_TRUE;
1458                         break;
1459                 default:
1460                         sub_usage(SHELP_LIST, CMD_LIST);
1461                         return (Z_USAGE);
1462                 }
1463         }
1464         if (parsable && verbose) {
1465                 zerror(gettext("%s -p and -v are mutually exclusive."),
1466                     cmd_to_str(CMD_LIST));
1467                 return (Z_ERR);
1468         }
1469         if (argc > optind) {
1470                 sub_usage(SHELP_LIST, CMD_LIST);
1471                 return (Z_USAGE);
1472         }
1473         if (zone_id != GLOBAL_ZONEID && !is_system_labeled()) {
1474                 fake_up_local_zone(zone_id, &zent);
1475                 /*
1476                  * main() will issue a Z_NO_ZONE error if it cannot get an
1477                  * id for target_zone, which in a non-global zone should
1478                  * happen for any zone name except `zonename`.  Thus we
1479                  * assert() that here but don't otherwise check.
1480                  */
1481                 assert(strcmp(zent.zname, target_zone) == 0);
1482                 zone_print(&zent, verbose, parsable);
1483                 output = B_TRUE;
1484         } else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
1485                 zone_print(zentp, verbose, parsable);
1486                 output = B_TRUE;
1487         } else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
1488             &zent) == Z_OK) {
1489                 zone_print(&zent, verbose, parsable);
1490                 output = B_TRUE;
1491         }
1492 
1493         /*
1494          * Invoke brand-specific handler. Note that we do this
1495          * only if we're in the global zone, and target_zone is specified
1496          * and it is not the global zone.
1497          */
1498         if (zone_id == GLOBAL_ZONEID && target_zone != NULL &&
1499             strcmp(target_zone, GLOBAL_ZONENAME) != 0)
1500                 if (invoke_brand_handler(CMD_LIST, argv) != Z_OK)
1501                         return (Z_ERR);
1502 
1503         return (output ? Z_OK : Z_ERR);
1504 }
1505 
1506 int
1507 do_subproc(char *cmdbuf)
1508 {
1509         void (*saveint)(int);
1510         void (*saveterm)(int);
1511         void (*savequit)(int);
1512         void (*savehup)(int);
1513         int pid, child, status;
1514 
1515         if ((child = vfork()) == 0) {
1516                 (void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL);
1517         }
1518 
1519         if (child == -1)
1520                 return (-1);
1521 
1522         saveint = sigset(SIGINT, SIG_IGN);
1523         saveterm = sigset(SIGTERM, SIG_IGN);
1524         savequit = sigset(SIGQUIT, SIG_IGN);
1525         savehup = sigset(SIGHUP, SIG_IGN);
1526 
1527         while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
1528                 ;
1529 
1530         (void) sigset(SIGINT, saveint);
1531         (void) sigset(SIGTERM, saveterm);
1532         (void) sigset(SIGQUIT, savequit);
1533         (void) sigset(SIGHUP, savehup);
1534 
1535         return (pid == -1 ? -1 : status);
1536 }
1537 
1538 int
1539 subproc_status(const char *cmd, int status, boolean_t verbose_failure)
1540 {
1541         if (WIFEXITED(status)) {
1542                 int exit_code = WEXITSTATUS(status);
1543 
1544                 if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK))
1545                         zerror(gettext("'%s' failed with exit code %d."), cmd,
1546                             exit_code);
1547 
1548                 return (exit_code);
1549         } else if (WIFSIGNALED(status)) {
1550                 int signal = WTERMSIG(status);
1551                 char sigstr[SIG2STR_MAX];
1552 
1553                 if (sig2str(signal, sigstr) == 0) {
1554                         zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
1555                             sigstr);
1556                 } else {
1557                         zerror(gettext("'%s' terminated by an unknown signal."),
1558                             cmd);
1559                 }
1560         } else {
1561                 zerror(gettext("'%s' failed for unknown reasons."), cmd);
1562         }
1563 
1564         /*
1565          * Assume a subprocess that died due to a signal or an unknown error
1566          * should be considered an exit code of ZONE_SUBPROC_FATAL, as the
1567          * user will likely need to do some manual cleanup.
1568          */
1569         return (ZONE_SUBPROC_FATAL);
1570 }
1571 
1572 static int
1573 auth_check(char *user, char *zone, int cmd_num)
1574 {
1575         char authname[MAXAUTHS];
1576 
1577         switch (cmd_num) {
1578         case CMD_LIST:
1579         case CMD_HELP:
1580                 return (Z_OK);
1581         case SOURCE_ZONE:
1582                 (void) strlcpy(authname, ZONE_CLONEFROM_AUTH, MAXAUTHS);
1583                 break;
1584         case CMD_BOOT:
1585         case CMD_HALT:
1586         case CMD_READY:
1587         case CMD_SHUTDOWN:
1588         case CMD_REBOOT:
1589         case CMD_SYSBOOT:
1590         case CMD_VERIFY:
1591         case CMD_INSTALL:
1592         case CMD_UNINSTALL:
1593         case CMD_MOUNT:
1594         case CMD_UNMOUNT:
1595         case CMD_CLONE:
1596         case CMD_MOVE:
1597         case CMD_DETACH:
1598         case CMD_ATTACH:
1599         case CMD_MARK:
1600         case CMD_APPLY:
1601         default:
1602                 (void) strlcpy(authname, ZONE_MANAGE_AUTH, MAXAUTHS);
1603                 break;
1604         }
1605         (void) strlcat(authname, KV_OBJECT, MAXAUTHS);
1606         (void) strlcat(authname, zone, MAXAUTHS);
1607         if (chkauthattr(authname, user) == 0) {
1608                 return (Z_ERR);
1609         } else {
1610                 /*
1611                  * Some subcommands, e.g. install, run subcommands,
1612                  * e.g. sysidcfg, that require a real uid of root,
1613                  *  so switch to root, here.
1614                  */
1615                 if (setuid(0) == -1) {
1616                         zperror(gettext("insufficient privilege"), B_TRUE);
1617                         return (Z_ERR);
1618                 }
1619                 return (Z_OK);
1620         }
1621 }
1622 
1623 /*
1624  * Various sanity checks; make sure:
1625  * 1. We're in the global zone.
1626  * 2. The calling user has sufficient privilege.
1627  * 3. The target zone is neither the global zone nor anything starting with
1628  *    "SUNW".
1629  * 4a. If we're looking for a 'not running' (i.e., configured or installed)
1630  *     zone, the name service knows about it.
1631  * 4b. For some operations which expect a zone not to be running, that it is
1632  *     not already running (or ready).
1633  */
1634 static int
1635 sanity_check(char *zone, int cmd_num, boolean_t running,
1636     boolean_t unsafe_when_running, boolean_t force)
1637 {
1638         zone_entry_t *zent;
1639         priv_set_t *privset;
1640         zone_state_t state, min_state;
1641         char kernzone[ZONENAME_MAX];
1642         FILE *fp;
1643 
1644         if (getzoneid() != GLOBAL_ZONEID) {
1645                 switch (cmd_num) {
1646                 case CMD_HALT:
1647                         zerror(gettext("use %s to %s this zone."), "halt(1M)",
1648                             cmd_to_str(cmd_num));
1649                         break;
1650                 case CMD_SHUTDOWN:
1651                         zerror(gettext("use %s to %s this zone."),
1652                             "shutdown(1M)", cmd_to_str(cmd_num));
1653                         break;
1654                 case CMD_REBOOT:
1655                         zerror(gettext("use %s to %s this zone."),
1656                             "reboot(1M)", cmd_to_str(cmd_num));
1657                         break;
1658                 default:
1659                         zerror(gettext("must be in the global zone to %s a "
1660                             "zone."), cmd_to_str(cmd_num));
1661                         break;
1662                 }
1663                 return (Z_ERR);
1664         }
1665 
1666         if ((privset = priv_allocset()) == NULL) {
1667                 zerror(gettext("%s failed"), "priv_allocset");
1668                 return (Z_ERR);
1669         }
1670 
1671         if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1672                 zerror(gettext("%s failed"), "getppriv");
1673                 priv_freeset(privset);
1674                 return (Z_ERR);
1675         }
1676 
1677         if (priv_isfullset(privset) == B_FALSE) {
1678                 zerror(gettext("only a privileged user may %s a zone."),
1679                     cmd_to_str(cmd_num));
1680                 priv_freeset(privset);
1681                 return (Z_ERR);
1682         }
1683         priv_freeset(privset);
1684 
1685         if (zone == NULL) {
1686                 zerror(gettext("no zone specified"));
1687                 return (Z_ERR);
1688         }
1689 
1690         if (auth_check(username, zone, cmd_num) == Z_ERR) {
1691                 zerror(gettext("User %s is not authorized to %s this zone."),
1692                     username, cmd_to_str(cmd_num));
1693                 return (Z_ERR);
1694         }
1695 
1696         if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
1697                 zerror(gettext("%s operation is invalid for the global zone."),
1698                     cmd_to_str(cmd_num));
1699                 return (Z_ERR);
1700         }
1701 
1702         if (strncmp(zone, "SUNW", 4) == 0) {
1703                 zerror(gettext("%s operation is invalid for zones starting "
1704                     "with SUNW."), cmd_to_str(cmd_num));
1705                 return (Z_ERR);
1706         }
1707 
1708         if (!zonecfg_in_alt_root()) {
1709                 zent = lookup_running_zone(zone);
1710         } else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
1711                 zent = NULL;
1712         } else {
1713                 if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
1714                     kernzone, sizeof (kernzone)) == 0)
1715                         zent = lookup_running_zone(kernzone);
1716                 else
1717                         zent = NULL;
1718                 zonecfg_close_scratch(fp);
1719         }
1720 
1721         /*
1722          * Look up from the kernel for 'running' zones.
1723          */
1724         if (running && !force) {
1725                 if (zent == NULL) {
1726                         zerror(gettext("not running"));
1727                         return (Z_ERR);
1728                 }
1729         } else {
1730                 int err;
1731 
1732                 if (unsafe_when_running && zent != NULL) {
1733                         /* check whether the zone is ready or running */
1734                         if ((err = zone_get_state(zent->zname,
1735                             &zent->zstate_num)) != Z_OK) {
1736                                 errno = err;
1737                                 zperror2(zent->zname,
1738                                     gettext("could not get state"));
1739                                 /* can't tell, so hedge */
1740                                 zent->zstate_str = "ready/running";
1741                         } else {
1742                                 zent->zstate_str =
1743                                     zone_state_str(zent->zstate_num);
1744                         }
1745                         zerror(gettext("%s operation is invalid for %s zones."),
1746                             cmd_to_str(cmd_num), zent->zstate_str);
1747                         return (Z_ERR);
1748                 }
1749                 if ((err = zone_get_state(zone, &state)) != Z_OK) {
1750                         errno = err;
1751                         zperror2(zone, gettext("could not get state"));
1752                         return (Z_ERR);
1753                 }
1754                 switch (cmd_num) {
1755                 case CMD_UNINSTALL:
1756                         if (state == ZONE_STATE_CONFIGURED) {
1757                                 zerror(gettext("is already in state '%s'."),
1758                                     zone_state_str(ZONE_STATE_CONFIGURED));
1759                                 return (Z_ERR);
1760                         }
1761                         break;
1762                 case CMD_ATTACH:
1763                         if (state == ZONE_STATE_INSTALLED) {
1764                                 zerror(gettext("is already %s."),
1765                                     zone_state_str(ZONE_STATE_INSTALLED));
1766                                 return (Z_ERR);
1767                         } else if (state == ZONE_STATE_INCOMPLETE && !force) {
1768                                 zerror(gettext("zone is %s; %s required."),
1769                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1770                                     cmd_to_str(CMD_UNINSTALL));
1771                                 return (Z_ERR);
1772                         }
1773                         break;
1774                 case CMD_CLONE:
1775                 case CMD_INSTALL:
1776                         if (state == ZONE_STATE_INSTALLED) {
1777                                 zerror(gettext("is already %s."),
1778                                     zone_state_str(ZONE_STATE_INSTALLED));
1779                                 return (Z_ERR);
1780                         } else if (state == ZONE_STATE_INCOMPLETE) {
1781                                 zerror(gettext("zone is %s; %s required."),
1782                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1783                                     cmd_to_str(CMD_UNINSTALL));
1784                                 return (Z_ERR);
1785                         }
1786                         break;
1787                 case CMD_DETACH:
1788                 case CMD_MOVE:
1789                 case CMD_READY:
1790                 case CMD_BOOT:
1791                 case CMD_MOUNT:
1792                 case CMD_MARK:
1793                         if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
1794                             force)
1795                                 min_state = ZONE_STATE_INCOMPLETE;
1796                         else if (cmd_num == CMD_MARK)
1797                                 min_state = ZONE_STATE_CONFIGURED;
1798                         else
1799                                 min_state = ZONE_STATE_INSTALLED;
1800 
1801                         if (state < min_state) {
1802                                 zerror(gettext("must be %s before %s."),
1803                                     zone_state_str(min_state),
1804                                     cmd_to_str(cmd_num));
1805                                 return (Z_ERR);
1806                         }
1807                         break;
1808                 case CMD_VERIFY:
1809                         if (state == ZONE_STATE_INCOMPLETE) {
1810                                 zerror(gettext("zone is %s; %s required."),
1811                                     zone_state_str(ZONE_STATE_INCOMPLETE),
1812                                     cmd_to_str(CMD_UNINSTALL));
1813                                 return (Z_ERR);
1814                         }
1815                         break;
1816                 case CMD_UNMOUNT:
1817                         if (state != ZONE_STATE_MOUNTED) {
1818                                 zerror(gettext("must be %s before %s."),
1819                                     zone_state_str(ZONE_STATE_MOUNTED),
1820                                     cmd_to_str(cmd_num));
1821                                 return (Z_ERR);
1822                         }
1823                         break;
1824                 case CMD_SYSBOOT:
1825                         if (state != ZONE_STATE_INSTALLED) {
1826                                 zerror(gettext("%s operation is invalid for %s "
1827                                     "zones."), cmd_to_str(cmd_num),
1828                                     zone_state_str(state));
1829                                 return (Z_ERR);
1830                         }
1831                         break;
1832                 }
1833         }
1834         return (Z_OK);
1835 }
1836 
1837 static int
1838 halt_func(int argc, char *argv[])
1839 {
1840         zone_cmd_arg_t zarg;
1841         int arg;
1842 
1843         if (zonecfg_in_alt_root()) {
1844                 zerror(gettext("cannot halt zone in alternate root"));
1845                 return (Z_ERR);
1846         }
1847 
1848         optind = 0;
1849         if ((arg = getopt(argc, argv, "?")) != EOF) {
1850                 switch (arg) {
1851                 case '?':
1852                         sub_usage(SHELP_HALT, CMD_HALT);
1853                         return (optopt == '?' ? Z_OK : Z_USAGE);
1854                 default:
1855                         sub_usage(SHELP_HALT, CMD_HALT);
1856                         return (Z_USAGE);
1857                 }
1858         }
1859         if (argc > optind) {
1860                 sub_usage(SHELP_HALT, CMD_HALT);
1861                 return (Z_USAGE);
1862         }
1863         /*
1864          * zoneadmd should be the one to decide whether or not to proceed,
1865          * so even though it seems that the fourth parameter below should
1866          * perhaps be B_TRUE, it really shouldn't be.
1867          */
1868         if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
1869             != Z_OK)
1870                 return (Z_ERR);
1871 
1872         /*
1873          * Invoke brand-specific handler.
1874          */
1875         if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
1876                 return (Z_ERR);
1877 
1878         zarg.cmd = Z_HALT;
1879         return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale,
1880             B_TRUE) == 0) ?  Z_OK : Z_ERR);
1881 }
1882 
1883 static int
1884 shutdown_func(int argc, char *argv[])
1885 {
1886         zone_cmd_arg_t zarg;
1887         int arg;
1888         boolean_t reboot = B_FALSE;
1889 
1890         zarg.cmd = Z_SHUTDOWN;
1891 
1892         if (zonecfg_in_alt_root()) {
1893                 zerror(gettext("cannot shut down zone in alternate root"));
1894                 return (Z_ERR);
1895         }
1896 
1897         optind = 0;
1898         while ((arg = getopt(argc, argv, "?r")) != EOF) {
1899                 switch (arg) {
1900                 case '?':
1901                         sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN);
1902                         return (optopt == '?' ? Z_OK : Z_USAGE);
1903                 case 'r':
1904                         reboot = B_TRUE;
1905                         break;
1906                 default:
1907                         sub_usage(SHELP_SHUTDOWN, CMD_SHUTDOWN);
1908                         return (Z_USAGE);
1909                 }
1910         }
1911 
1912         zarg.bootbuf[0] = '\0';
1913         for (; optind < argc; optind++) {
1914                 if (strlcat(zarg.bootbuf, argv[optind],
1915                     sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1916                         zerror(gettext("Boot argument list too long"));
1917                         return (Z_ERR);
1918                 }
1919                 if (optind < argc - 1)
1920                         if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1921                             sizeof (zarg.bootbuf)) {
1922                                 zerror(gettext("Boot argument list too long"));
1923                                 return (Z_ERR);
1924                         }
1925         }
1926 
1927         /*
1928          * zoneadmd should be the one to decide whether or not to proceed,
1929          * so even though it seems that the third parameter below should
1930          * perhaps be B_TRUE, it really shouldn't be.
1931          */
1932         if (sanity_check(target_zone, CMD_SHUTDOWN, B_TRUE, B_FALSE, B_FALSE)
1933             != Z_OK)
1934                 return (Z_ERR);
1935 
1936         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != Z_OK)
1937                 return (Z_ERR);
1938 
1939         if (reboot) {
1940                 if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE,
1941                     B_FALSE) != Z_OK)
1942                         return (Z_ERR);
1943 
1944                 zarg.cmd = Z_BOOT;
1945                 if (zonecfg_call_zoneadmd(target_zone, &zarg, locale,
1946                     B_TRUE) != Z_OK)
1947                         return (Z_ERR);
1948         }
1949         return (Z_OK);
1950 }
1951 
1952 static int
1953 reboot_func(int argc, char *argv[])
1954 {
1955         zone_cmd_arg_t zarg;
1956         int arg;
1957 
1958         if (zonecfg_in_alt_root()) {
1959                 zerror(gettext("cannot reboot zone in alternate root"));
1960                 return (Z_ERR);
1961         }
1962 
1963         optind = 0;
1964         if ((arg = getopt(argc, argv, "?")) != EOF) {
1965                 switch (arg) {
1966                 case '?':
1967                         sub_usage(SHELP_REBOOT, CMD_REBOOT);
1968                         return (optopt == '?' ? Z_OK : Z_USAGE);
1969                 default:
1970                         sub_usage(SHELP_REBOOT, CMD_REBOOT);
1971                         return (Z_USAGE);
1972                 }
1973         }
1974 
1975         zarg.bootbuf[0] = '\0';
1976         for (; optind < argc; optind++) {
1977                 if (strlcat(zarg.bootbuf, argv[optind],
1978                     sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1979                         zerror(gettext("Boot argument list too long"));
1980                         return (Z_ERR);
1981                 }
1982                 if (optind < argc - 1)
1983                         if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1984                             sizeof (zarg.bootbuf)) {
1985                                 zerror(gettext("Boot argument list too long"));
1986                                 return (Z_ERR);
1987                         }
1988         }
1989 
1990 
1991         /*
1992          * zoneadmd should be the one to decide whether or not to proceed,
1993          * so even though it seems that the fourth parameter below should
1994          * perhaps be B_TRUE, it really shouldn't be.
1995          */
1996         if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE)
1997             != Z_OK)
1998                 return (Z_ERR);
1999         if (verify_details(CMD_REBOOT, argv) != Z_OK)
2000                 return (Z_ERR);
2001 
2002         zarg.cmd = Z_REBOOT;
2003         return ((zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) == 0)
2004             ? Z_OK : Z_ERR);
2005 }
2006 
2007 static int
2008 get_hook(brand_handle_t bh, char *cmd, size_t len, int (*bp)(brand_handle_t,
2009     const char *, const char *, char *, size_t), char *zonename, char *zonepath)
2010 {
2011         if (strlcpy(cmd, EXEC_PREFIX, len) >= len)
2012                 return (Z_ERR);
2013 
2014         if (bp(bh, zonename, zonepath, cmd + EXEC_LEN, len - EXEC_LEN) != 0)
2015                 return (Z_ERR);
2016 
2017         if (strlen(cmd) <= EXEC_LEN)
2018                 cmd[0] = '\0';
2019 
2020         return (Z_OK);
2021 }
2022 
2023 static int
2024 verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[])
2025 {
2026         char cmdbuf[MAXPATHLEN];
2027         int err;
2028         char zonepath[MAXPATHLEN];
2029         brand_handle_t bh = NULL;
2030         int status, i;
2031 
2032         /*
2033          * Fetch the verify command from the brand configuration.
2034          * "exec" the command so that the returned status is that of
2035          * the command and not the shell.
2036          */
2037         if (handle == NULL) {
2038                 (void) strlcpy(zonepath, "-", sizeof (zonepath));
2039         } else if ((err = zonecfg_get_zonepath(handle, zonepath,
2040             sizeof (zonepath))) != Z_OK) {
2041                 errno = err;
2042                 zperror(cmd_to_str(cmd_num), B_TRUE);
2043                 return (Z_ERR);
2044         }
2045         if ((bh = brand_open(target_brand)) == NULL) {
2046                 zerror(gettext("missing or invalid brand"));
2047                 return (Z_ERR);
2048         }
2049 
2050         /*
2051          * If the brand has its own verification routine, execute it now.
2052          * The verification routine validates the intended zoneadm
2053          * operation for the specific brand. The zoneadm subcommand and
2054          * all its arguments are passed to the routine.
2055          */
2056         err = get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_verify_adm,
2057             target_zone, zonepath);
2058         brand_close(bh);
2059         if (err != Z_OK)
2060                 return (Z_BRAND_ERROR);
2061         if (cmdbuf[0] == '\0')
2062                 return (Z_OK);
2063 
2064         if (strlcat(cmdbuf, cmd_to_str(cmd_num),
2065             sizeof (cmdbuf)) >= sizeof (cmdbuf))
2066                 return (Z_ERR);
2067 
2068         /* Build the argv string */
2069         i = 0;
2070         while (argv[i] != NULL) {
2071                 if ((strlcat(cmdbuf, " ",
2072                     sizeof (cmdbuf)) >= sizeof (cmdbuf)) ||
2073                     (strlcat(cmdbuf, argv[i++],
2074                     sizeof (cmdbuf)) >= sizeof (cmdbuf)))
2075                         return (Z_ERR);
2076         }
2077 
2078         status = do_subproc(cmdbuf);
2079         err = subproc_status(gettext("brand-specific verification"),
2080             status, B_FALSE);
2081 
2082         return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR);
2083 }
2084 
2085 static int
2086 verify_rctls(zone_dochandle_t handle)
2087 {
2088         struct zone_rctltab rctltab;
2089         size_t rbs = rctlblk_size();
2090         rctlblk_t *rctlblk;
2091         int error = Z_INVAL;
2092 
2093         if ((rctlblk = malloc(rbs)) == NULL) {
2094                 zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
2095                     strerror(errno));
2096                 return (Z_NOMEM);
2097         }
2098 
2099         if (zonecfg_setrctlent(handle) != Z_OK) {
2100                 zerror(gettext("zonecfg_setrctlent failed"));
2101                 free(rctlblk);
2102                 return (error);
2103         }
2104 
2105         rctltab.zone_rctl_valptr = NULL;
2106         while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2107                 struct zone_rctlvaltab *rctlval;
2108                 const char *name = rctltab.zone_rctl_name;
2109 
2110                 if (!zonecfg_is_rctl(name)) {
2111                         zerror(gettext("WARNING: Ignoring unrecognized rctl "
2112                             "'%s'."),  name);
2113                         zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2114                         rctltab.zone_rctl_valptr = NULL;
2115                         continue;
2116                 }
2117 
2118                 for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
2119                     rctlval = rctlval->zone_rctlval_next) {
2120                         if (zonecfg_construct_rctlblk(rctlval, rctlblk)
2121                             != Z_OK) {
2122                                 zerror(gettext("invalid rctl value: "
2123                                     "(priv=%s,limit=%s,action%s)"),
2124                                     rctlval->zone_rctlval_priv,
2125                                     rctlval->zone_rctlval_limit,
2126                                     rctlval->zone_rctlval_action);
2127                                 goto out;
2128                         }
2129                         if (!zonecfg_valid_rctl(name, rctlblk)) {
2130                                 zerror(gettext("(priv=%s,limit=%s,action=%s) "
2131                                     "is not a valid value for rctl '%s'"),
2132                                     rctlval->zone_rctlval_priv,
2133                                     rctlval->zone_rctlval_limit,
2134                                     rctlval->zone_rctlval_action,
2135                                     name);
2136                                 goto out;
2137                         }
2138                 }
2139                 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2140         }
2141         rctltab.zone_rctl_valptr = NULL;
2142         error = Z_OK;
2143 out:
2144         zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2145         (void) zonecfg_endrctlent(handle);
2146         free(rctlblk);
2147         return (error);
2148 }
2149 
2150 static int
2151 verify_pool(zone_dochandle_t handle)
2152 {
2153         char poolname[MAXPATHLEN];
2154         pool_conf_t *poolconf;
2155         pool_t *pool;
2156         int status;
2157         int error;
2158 
2159         /*
2160          * This ends up being very similar to the check done in zoneadmd.
2161          */
2162         error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
2163         if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
2164                 /*
2165                  * No pool specified.
2166                  */
2167                 return (0);
2168         }
2169         if (error != Z_OK) {
2170                 zperror(gettext("Unable to retrieve pool name from "
2171                     "configuration"), B_TRUE);
2172                 return (error);
2173         }
2174         /*
2175          * Don't do anything if pools aren't enabled.
2176          */
2177         if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
2178                 zerror(gettext("WARNING: pools facility not active; "
2179                     "zone will not be bound to pool '%s'."), poolname);
2180                 return (Z_OK);
2181         }
2182         /*
2183          * Try to provide a sane error message if the requested pool doesn't
2184          * exist.  It isn't clear that pools-related failures should
2185          * necessarily translate to a failure to verify the zone configuration,
2186          * hence they are not considered errors.
2187          */
2188         if ((poolconf = pool_conf_alloc()) == NULL) {
2189                 zerror(gettext("WARNING: pool_conf_alloc failed; "
2190                     "using default pool"));
2191                 return (Z_OK);
2192         }
2193         if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
2194             PO_SUCCESS) {
2195                 zerror(gettext("WARNING: pool_conf_open failed; "
2196                     "using default pool"));
2197                 pool_conf_free(poolconf);
2198                 return (Z_OK);
2199         }
2200         pool = pool_get_pool(poolconf, poolname);
2201         (void) pool_conf_close(poolconf);
2202         pool_conf_free(poolconf);
2203         if (pool == NULL) {
2204                 zerror(gettext("WARNING: pool '%s' not found. "
2205                     "using default pool"), poolname);
2206         }
2207 
2208         return (Z_OK);
2209 }
2210 
2211 /*
2212  * Verify that the special device/file system exists and is valid.
2213  */
2214 static int
2215 verify_fs_special(struct zone_fstab *fstab)
2216 {
2217         struct stat64 st;
2218 
2219         /*
2220          * This validation is really intended for standard zone administration.
2221          * If we are in a mini-root or some other upgrade situation where
2222          * we are using the scratch zone, just by-pass this.
2223          */
2224         if (zonecfg_in_alt_root())
2225                 return (Z_OK);
2226 
2227         if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
2228                 return (verify_fs_zfs(fstab));
2229 
2230         if (stat64(fstab->zone_fs_special, &st) != 0) {
2231                 (void) fprintf(stderr, gettext("could not verify fs "
2232                     "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
2233                     fstab->zone_fs_special, strerror(errno));
2234                 return (Z_ERR);
2235         }
2236 
2237         if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2238                 /*
2239                  * TRANSLATION_NOTE
2240                  * fs and NFS are literals that should
2241                  * not be translated.
2242                  */
2243                 (void) fprintf(stderr, gettext("cannot verify "
2244                     "fs %s: NFS mounted file system.\n"
2245                     "\tA local file system must be used.\n"),
2246                     fstab->zone_fs_special);
2247                 return (Z_ERR);
2248         }
2249 
2250         return (Z_OK);
2251 }
2252 
2253 static int
2254 isregfile(const char *path)
2255 {
2256         struct stat64 st;
2257 
2258         if (stat64(path, &st) == -1)
2259                 return (-1);
2260 
2261         return (S_ISREG(st.st_mode));
2262 }
2263 
2264 static int
2265 verify_filesystems(zone_dochandle_t handle)
2266 {
2267         int return_code = Z_OK;
2268         struct zone_fstab fstab;
2269         char cmdbuf[MAXPATHLEN];
2270         struct stat st;
2271 
2272         /*
2273          * Since the actual mount point is not known until the dependent mounts
2274          * are performed, we don't attempt any path validation here: that will
2275          * happen later when zoneadmd actually does the mounts.
2276          */
2277         if (zonecfg_setfsent(handle) != Z_OK) {
2278                 (void) fprintf(stderr, gettext("could not verify file systems: "
2279                     "unable to enumerate mounts\n"));
2280                 return (Z_ERR);
2281         }
2282         while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2283                 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2284                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2285                             "type %s is not allowed.\n"), fstab.zone_fs_dir,
2286                             fstab.zone_fs_type);
2287                         return_code = Z_ERR;
2288                         goto next_fs;
2289                 }
2290                 /*
2291                  * Verify /usr/lib/fs/<fstype>/mount exists.
2292                  */
2293                 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
2294                     fstab.zone_fs_type) > sizeof (cmdbuf)) {
2295                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2296                             "type %s is too long.\n"), fstab.zone_fs_dir,
2297                             fstab.zone_fs_type);
2298                         return_code = Z_ERR;
2299                         goto next_fs;
2300                 }
2301                 if (stat(cmdbuf, &st) != 0) {
2302                         (void) fprintf(stderr, gettext("could not verify fs "
2303                             "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2304                             cmdbuf, strerror(errno));
2305                         return_code = Z_ERR;
2306                         goto next_fs;
2307                 }
2308                 if (!S_ISREG(st.st_mode)) {
2309                         (void) fprintf(stderr, gettext("could not verify fs "
2310                             "%s: %s is not a regular file\n"),
2311                             fstab.zone_fs_dir, cmdbuf);
2312                         return_code = Z_ERR;
2313                         goto next_fs;
2314                 }
2315                 /*
2316                  * If zone_fs_raw is set, verify that there's an fsck
2317                  * binary for it.  If zone_fs_raw is not set, and it's
2318                  * not a regular file (lofi mount), and there's an fsck
2319                  * binary for it, complain.
2320                  */
2321                 if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
2322                     fstab.zone_fs_type) > sizeof (cmdbuf)) {
2323                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2324                             "type %s is too long.\n"), fstab.zone_fs_dir,
2325                             fstab.zone_fs_type);
2326                         return_code = Z_ERR;
2327                         goto next_fs;
2328                 }
2329                 if (fstab.zone_fs_raw[0] != '\0' &&
2330                     (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2331                         (void) fprintf(stderr, gettext("cannot verify fs %s: "
2332                             "'raw' device specified but "
2333                             "no fsck executable exists for %s\n"),
2334                             fstab.zone_fs_dir, fstab.zone_fs_type);
2335                         return_code = Z_ERR;
2336                         goto next_fs;
2337                 } else if (fstab.zone_fs_raw[0] == '\0' &&
2338                     stat(cmdbuf, &st) == 0 &&
2339                     isregfile(fstab.zone_fs_special) != 1) {
2340                         (void) fprintf(stderr, gettext("could not verify fs "
2341                             "%s: must specify 'raw' device for %s "
2342                             "file systems\n"),
2343                             fstab.zone_fs_dir, fstab.zone_fs_type);
2344                         return_code = Z_ERR;
2345                         goto next_fs;
2346                 }
2347 
2348                 /* Verify fs_special. */
2349                 if ((return_code = verify_fs_special(&fstab)) != Z_OK)
2350                         goto next_fs;
2351 
2352                 /* Verify fs_raw. */
2353                 if (fstab.zone_fs_raw[0] != '\0' &&
2354                     stat(fstab.zone_fs_raw, &st) != 0) {
2355                         /*
2356                          * TRANSLATION_NOTE
2357                          * fs is a literal that should not be translated.
2358                          */
2359                         (void) fprintf(stderr, gettext("could not verify fs "
2360                             "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2361                             fstab.zone_fs_raw, strerror(errno));
2362                         return_code = Z_ERR;
2363                         goto next_fs;
2364                 }
2365 next_fs:
2366                 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2367         }
2368         (void) zonecfg_endfsent(handle);
2369 
2370         return (return_code);
2371 }
2372 
2373 static int
2374 verify_limitpriv(zone_dochandle_t handle)
2375 {
2376         char *privname = NULL;
2377         int err;
2378         priv_set_t *privs;
2379 
2380         if ((privs = priv_allocset()) == NULL) {
2381                 zperror(gettext("failed to allocate privilege set"), B_FALSE);
2382                 return (Z_NOMEM);
2383         }
2384         err = zonecfg_get_privset(handle, privs, &privname);
2385         switch (err) {
2386         case Z_OK:
2387                 break;
2388         case Z_PRIV_PROHIBITED:
2389                 (void) fprintf(stderr, gettext("privilege \"%s\" is not "
2390                     "permitted within the zone's privilege set\n"), privname);
2391                 break;
2392         case Z_PRIV_REQUIRED:
2393                 (void) fprintf(stderr, gettext("required privilege \"%s\" is "
2394                     "missing from the zone's privilege set\n"), privname);
2395                 break;
2396         case Z_PRIV_UNKNOWN:
2397                 (void) fprintf(stderr, gettext("unknown privilege \"%s\" "
2398                     "specified in the zone's privilege set\n"), privname);
2399                 break;
2400         default:
2401                 zperror(
2402                     gettext("failed to determine the zone's privilege set"),
2403                     B_TRUE);
2404                 break;
2405         }
2406         free(privname);
2407         priv_freeset(privs);
2408         return (err);
2409 }
2410 
2411 static void
2412 free_local_netifs(int if_cnt, struct net_if **if_list)
2413 {
2414         int             i;
2415 
2416         for (i = 0; i < if_cnt; i++) {
2417                 free(if_list[i]->name);
2418                 free(if_list[i]);
2419         }
2420         free(if_list);
2421 }
2422 
2423 /*
2424  * Get a list of the network interfaces, along with their address families,
2425  * that are plumbed in the global zone.  See if_tcp(7p) for a description
2426  * of the ioctls used here.
2427  */
2428 static int
2429 get_local_netifs(int *if_cnt, struct net_if ***if_list)
2430 {
2431         int             s;
2432         int             i;
2433         int             res = Z_OK;
2434         int             space_needed;
2435         int             cnt = 0;
2436         struct          lifnum if_num;
2437         struct          lifconf if_conf;
2438         struct          lifreq *if_reqp;
2439         char            *if_buf;
2440         struct net_if   **local_ifs = NULL;
2441 
2442         *if_cnt = 0;
2443         *if_list = NULL;
2444 
2445         if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
2446                 return (Z_ERR);
2447 
2448         /*
2449          * Come back here in the unlikely event that the number of interfaces
2450          * increases between the time we get the count and the time we do the
2451          * SIOCGLIFCONF ioctl.
2452          */
2453 retry:
2454         /* Get the number of interfaces. */
2455         if_num.lifn_family = AF_UNSPEC;
2456         if_num.lifn_flags = LIFC_NOXMIT;
2457         if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
2458                 (void) close(s);
2459                 return (Z_ERR);
2460         }
2461 
2462         /* Get the interface configuration list. */
2463         space_needed = if_num.lifn_count * sizeof (struct lifreq);
2464         if ((if_buf = malloc(space_needed)) == NULL) {
2465                 (void) close(s);
2466                 return (Z_ERR);
2467         }
2468         if_conf.lifc_family = AF_UNSPEC;
2469         if_conf.lifc_flags = LIFC_NOXMIT;
2470         if_conf.lifc_len = space_needed;
2471         if_conf.lifc_buf = if_buf;
2472         if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
2473                 free(if_buf);
2474                 /*
2475                  * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
2476                  * too small.  In this case go back and get the new if cnt.
2477                  */
2478                 if (errno == EINVAL)
2479                         goto retry;
2480 
2481                 (void) close(s);
2482                 return (Z_ERR);
2483         }
2484         (void) close(s);
2485 
2486         /* Get the name and address family for each interface. */
2487         if_reqp = if_conf.lifc_req;
2488         for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
2489                 struct net_if   **p;
2490                 struct lifreq   req;
2491 
2492                 if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
2493                         if_reqp++;
2494                         continue;
2495                 }
2496 
2497                 if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
2498                     SOCK_DGRAM, 0)) == -1) {
2499                         res = Z_ERR;
2500                         break;
2501                 }
2502 
2503                 (void) strncpy(req.lifr_name, if_reqp->lifr_name,
2504                     sizeof (req.lifr_name));
2505                 if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
2506                         (void) close(s);
2507                         if_reqp++;
2508                         continue;
2509                 }
2510 
2511                 if ((p = (struct net_if **)realloc(local_ifs,
2512                     sizeof (struct net_if *) * (cnt + 1))) == NULL) {
2513                         res = Z_ERR;
2514                         break;
2515                 }
2516                 local_ifs = p;
2517 
2518                 if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
2519                         res = Z_ERR;
2520                         break;
2521                 }
2522 
2523                 if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
2524                     == NULL) {
2525                         free(local_ifs[cnt]);
2526                         res = Z_ERR;
2527                         break;
2528                 }
2529                 local_ifs[cnt]->af = req.lifr_addr.ss_family;
2530                 cnt++;
2531 
2532                 (void) close(s);
2533                 if_reqp++;
2534         }
2535 
2536         free(if_buf);
2537 
2538         if (res != Z_OK) {
2539                 free_local_netifs(cnt, local_ifs);
2540         } else {
2541                 *if_cnt = cnt;
2542                 *if_list = local_ifs;
2543         }
2544 
2545         return (res);
2546 }
2547 
2548 static char *
2549 af2str(int af)
2550 {
2551         switch (af) {
2552         case AF_INET:
2553                 return ("IPv4");
2554         case AF_INET6:
2555                 return ("IPv6");
2556         default:
2557                 return ("Unknown");
2558         }
2559 }
2560 
2561 /*
2562  * Cross check the network interface name and address family with the
2563  * interfaces that are set up in the global zone so that we can print the
2564  * appropriate error message.
2565  */
2566 static void
2567 print_net_err(char *phys, char *addr, int af, char *msg)
2568 {
2569         int             i;
2570         int             local_if_cnt = 0;
2571         struct net_if   **local_ifs = NULL;
2572         boolean_t       found_if = B_FALSE;
2573         boolean_t       found_af = B_FALSE;
2574 
2575         if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
2576                 (void) fprintf(stderr,
2577                     gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2578                     "net", "address", addr, "physical", phys, msg);
2579                 return;
2580         }
2581 
2582         for (i = 0; i < local_if_cnt; i++) {
2583                 if (strcmp(phys, local_ifs[i]->name) == 0) {
2584                         found_if = B_TRUE;
2585                         if (af == local_ifs[i]->af) {
2586                                 found_af = B_TRUE;
2587                                 break;
2588                         }
2589                 }
2590         }
2591 
2592         free_local_netifs(local_if_cnt, local_ifs);
2593 
2594         if (!found_if) {
2595                 (void) fprintf(stderr,
2596                     gettext("could not verify %s %s=%s\n\t"
2597                     "network interface %s is not plumbed in the global zone\n"),
2598                     "net", "physical", phys, phys);
2599                 return;
2600         }
2601 
2602         /*
2603          * Print this error if we were unable to find the address family
2604          * for this interface.  If the af variable is not initialized to
2605          * to something meaningful by the caller (not AF_UNSPEC) then we
2606          * also skip this message since it wouldn't be informative.
2607          */
2608         if (!found_af && af != AF_UNSPEC) {
2609                 (void) fprintf(stderr,
2610                     gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
2611                     "family is not configured on this network interface in "
2612                     "the\n\tglobal zone\n"),
2613                     "net", "address", addr, "physical", phys, af2str(af));
2614                 return;
2615         }
2616 
2617         (void) fprintf(stderr,
2618             gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2619             "net", "address", addr, "physical", phys, msg);
2620 }
2621 
2622 static int
2623 verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[])
2624 {
2625         struct zone_nwiftab nwiftab;
2626         int return_code = Z_OK;
2627         int err;
2628         boolean_t in_alt_root;
2629         zone_iptype_t iptype;
2630         dladm_handle_t dh;
2631         dladm_status_t status;
2632         datalink_id_t linkid;
2633         char errmsg[DLADM_STRSIZE];
2634 
2635         in_alt_root = zonecfg_in_alt_root();
2636         if (in_alt_root)
2637                 goto no_net;
2638 
2639         if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
2640                 errno = err;
2641                 zperror(cmd_to_str(cmd_num), B_TRUE);
2642                 zonecfg_fini_handle(handle);
2643                 return (Z_ERR);
2644         }
2645         if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2646                 errno = err;
2647                 zperror(cmd_to_str(cmd_num), B_TRUE);
2648                 zonecfg_fini_handle(handle);
2649                 return (Z_ERR);
2650         }
2651         while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2652                 struct lifreq lifr;
2653                 sa_family_t af = AF_UNSPEC;
2654                 char dl_owner_zname[ZONENAME_MAX];
2655                 zoneid_t dl_owner_zid;
2656                 zoneid_t target_zid;
2657                 int res;
2658 
2659                 /* skip any loopback interfaces */
2660                 if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
2661                         continue;
2662                 switch (iptype) {
2663                 case ZS_SHARED:
2664                         if ((res = zonecfg_valid_net_address(
2665                             nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
2666                                 print_net_err(nwiftab.zone_nwif_physical,
2667                                     nwiftab.zone_nwif_address, af,
2668                                     zonecfg_strerror(res));
2669                                 return_code = Z_ERR;
2670                                 continue;
2671                         }
2672                         af = lifr.lifr_addr.ss_family;
2673                         if (!zonecfg_ifname_exists(af,
2674                             nwiftab.zone_nwif_physical)) {
2675                                 /*
2676                                  * The interface failed to come up. We continue
2677                                  * on anyway for the sake of consistency: a
2678                                  * zone is not shut down if the interface fails
2679                                  * any time after boot, nor does the global zone
2680                                  * fail to boot if an interface fails.
2681                                  */
2682                                 (void) fprintf(stderr,
2683                                     gettext("WARNING: skipping network "
2684                                     "interface '%s' which may not be "
2685                                     "present/plumbed in the global "
2686                                     "zone.\n"),
2687                                     nwiftab.zone_nwif_physical);
2688                         }
2689                         break;
2690                 case ZS_EXCLUSIVE:
2691                         /* Warning if it exists for either IPv4 or IPv6 */
2692 
2693                         if (zonecfg_ifname_exists(AF_INET,
2694                             nwiftab.zone_nwif_physical) ||
2695                             zonecfg_ifname_exists(AF_INET6,
2696                             nwiftab.zone_nwif_physical)) {
2697                                 (void) fprintf(stderr,
2698                                     gettext("WARNING: skipping network "
2699                                     "interface '%s' which is used in the "
2700                                     "global zone.\n"),
2701                                     nwiftab.zone_nwif_physical);
2702                                 break;
2703                         }
2704 
2705                         /*
2706                          * Verify that the datalink exists and that it isn't
2707                          * already assigned to a zone.
2708                          */
2709                         if ((status = dladm_open(&dh)) == DLADM_STATUS_OK) {
2710                                 status = dladm_name2info(dh,
2711                                     nwiftab.zone_nwif_physical, &linkid, NULL,
2712                                     NULL, NULL);
2713                                 dladm_close(dh);
2714                         }
2715                         if (status != DLADM_STATUS_OK) {
2716                                 (void) fprintf(stderr,
2717                                     gettext("WARNING: skipping network "
2718                                     "interface '%s': %s\n"),
2719                                     nwiftab.zone_nwif_physical,
2720                                     dladm_status2str(status, errmsg));
2721                                 break;
2722                         }
2723                         dl_owner_zid = ALL_ZONES;
2724                         if (zone_check_datalink(&dl_owner_zid, linkid) != 0)
2725                                 break;
2726 
2727                         /*
2728                          * If the zone being verified is
2729                          * running and owns the interface
2730                          */
2731                         target_zid = getzoneidbyname(target_zone);
2732                         if (target_zid == dl_owner_zid)
2733                                 break;
2734 
2735                         /* Zone id match failed, use name to check */
2736                         if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
2737                             ZONENAME_MAX) < 0) {
2738                                 /* No name, show ID instead */
2739                                 (void) snprintf(dl_owner_zname, ZONENAME_MAX,
2740                                     "<%d>", dl_owner_zid);
2741                         } else if (strcmp(dl_owner_zname, target_zone) == 0)
2742                                 break;
2743 
2744                         /*
2745                          * Note here we only report a warning that
2746                          * the interface is already in use by another
2747                          * running zone, and the verify process just
2748                          * goes on, if the interface is still in use
2749                          * when this zone really boots up, zoneadmd
2750                          * will find it. If the name of the zone which
2751                          * owns this interface cannot be determined,
2752                          * then it is not possible to determine if there
2753                          * is a conflict so just report it as a warning.
2754                          */
2755                         (void) fprintf(stderr,
2756                             gettext("WARNING: skipping network interface "
2757                             "'%s' which is used by the non-global zone "
2758                             "'%s'.\n"), nwiftab.zone_nwif_physical,
2759                             dl_owner_zname);
2760                         break;
2761                 }
2762         }
2763         (void) zonecfg_endnwifent(handle);
2764 no_net:
2765 
2766         /* verify that lofs has not been excluded from the kernel */
2767         if (!(cmd_num == CMD_DETACH || cmd_num == CMD_ATTACH ||
2768             cmd_num == CMD_MOVE || cmd_num == CMD_CLONE) &&
2769             modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) {
2770                 if (errno == ENXIO)
2771                         (void) fprintf(stderr, gettext("could not verify "
2772                             "lofs(7FS): possibly excluded in /etc/system\n"));
2773                 else
2774                         (void) fprintf(stderr, gettext("could not verify "
2775                             "lofs(7FS): %s\n"), strerror(errno));
2776                 return_code = Z_ERR;
2777         }
2778 
2779         if (verify_filesystems(handle) != Z_OK)
2780                 return_code = Z_ERR;
2781         if (!in_alt_root && verify_rctls(handle) != Z_OK)
2782                 return_code = Z_ERR;
2783         if (!in_alt_root && verify_pool(handle) != Z_OK)
2784                 return_code = Z_ERR;
2785         if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2786                 return_code = Z_ERR;
2787         if (!in_alt_root && verify_datasets(handle) != Z_OK)
2788                 return_code = Z_ERR;
2789 
2790         /*
2791          * As the "mount" command is used for patching/upgrading of zones
2792          * or other maintenance processes, the zone's privilege set is not
2793          * checked in this case.  Instead, the default, safe set of
2794          * privileges will be used when this zone is created in the
2795          * kernel.
2796          */
2797         if (!in_alt_root && cmd_num != CMD_MOUNT &&
2798             verify_limitpriv(handle) != Z_OK)
2799                 return_code = Z_ERR;
2800 
2801         return (return_code);
2802 }
2803 
2804 /*
2805  * Called when readying or booting a zone.  We double check that the zone's
2806  * debug ID is set and is unique.  This covers the case of pre-existing zones
2807  * with no ID.  Also, its possible that a zone was migrated to this host
2808  * and as a result it has a duplicate ID.  In this case we preserve the ID
2809  * of the first zone we match on in the index file (since it was there before
2810  * the current zone) and we assign a new unique ID to the current zone.
2811  * Return true if we assigned a new ID, indicating that the zone configuration
2812  * needs to be saved.
2813  */
2814 static boolean_t
2815 verify_fix_did(zone_dochandle_t handle)
2816 {
2817         zoneid_t mydid;
2818         zone_entry_t zent;
2819         FILE *cookie;
2820         char *name;
2821         boolean_t fix = B_FALSE;
2822 
2823         mydid = zonecfg_get_did(handle);
2824         if (mydid == -1) {
2825                 zonecfg_set_did(handle);
2826                 return (B_TRUE);
2827         }
2828 
2829         /* Get the full list of zones from the configuration. */
2830         cookie = setzoneent();
2831         while ((name = getzoneent(cookie)) != NULL) {
2832                 if (strcmp(target_zone, name) == 0) {
2833                         free(name);
2834                         break;  /* Once we find our entry, stop. */
2835                 }
2836 
2837                 if (strcmp(name, "global") == 0 ||
2838                     lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
2839                         free(name);
2840                         continue;
2841                 }
2842 
2843                 free(name);
2844                 if (zent.zdid == mydid) {
2845                         fix = B_TRUE;
2846                         break;
2847                 }
2848         }
2849         endzoneent(cookie);
2850 
2851         if (fix) {
2852                 zonecfg_set_did(handle);
2853                 return (B_TRUE);
2854         }
2855 
2856         return (B_FALSE);
2857 }
2858 
2859 static int
2860 verify_details(int cmd_num, char *argv[])
2861 {
2862         zone_dochandle_t handle;
2863         char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2864         int return_code = Z_OK;
2865         int err;
2866 
2867         if ((handle = zonecfg_init_handle()) == NULL) {
2868                 zperror(cmd_to_str(cmd_num), B_TRUE);
2869                 return (Z_ERR);
2870         }
2871         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2872                 errno = err;
2873                 zperror(cmd_to_str(cmd_num), B_TRUE);
2874                 zonecfg_fini_handle(handle);
2875                 return (Z_ERR);
2876         }
2877         if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2878             Z_OK) {
2879                 errno = err;
2880                 zperror(cmd_to_str(cmd_num), B_TRUE);
2881                 zonecfg_fini_handle(handle);
2882                 return (Z_ERR);
2883         }
2884         /*
2885          * zonecfg_get_zonepath() gets its data from the XML repository.
2886          * Verify this against the index file, which is checked first by
2887          * zone_get_zonepath().  If they don't match, bail out.
2888          */
2889         if ((err = zone_get_zonepath(target_zone, checkpath,
2890             sizeof (checkpath))) != Z_OK) {
2891                 errno = err;
2892                 zperror2(target_zone, gettext("could not get zone path"));
2893                 zonecfg_fini_handle(handle);
2894                 return (Z_ERR);
2895         }
2896         if (strcmp(zonepath, checkpath) != 0) {
2897                 /*
2898                  * TRANSLATION_NOTE
2899                  * XML and zonepath are literals that should not be translated.
2900                  */
2901                 (void) fprintf(stderr, gettext("The XML repository has "
2902                     "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2903                     "These must match, so fix the incorrect entry.\n"),
2904                     zonepath, checkpath);
2905                 zonecfg_fini_handle(handle);
2906                 return (Z_ERR);
2907         }
2908         if (cmd_num != CMD_ATTACH &&
2909             validate_zonepath(zonepath, cmd_num) != Z_OK) {
2910                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2911                     "because of the above errors.\n"), zonepath);
2912                 return_code = Z_ERR;
2913         }
2914 
2915         if (verify_handle(cmd_num, handle, argv) != Z_OK)
2916                 return_code = Z_ERR;
2917 
2918         if (cmd_num == CMD_READY || cmd_num == CMD_BOOT)
2919                 if (verify_fix_did(handle))
2920                         if (zonecfg_save(handle) != Z_OK)
2921                                 (void) fprintf(stderr, gettext("Could not save "
2922                                     "debug ID.\n"));
2923 
2924         zonecfg_fini_handle(handle);
2925         if (return_code == Z_ERR)
2926                 (void) fprintf(stderr,
2927                     gettext("%s: zone %s failed to verify\n"),
2928                     execname, target_zone);
2929         return (return_code);
2930 }
2931 
2932 static int
2933 verify_func(int argc, char *argv[])
2934 {
2935         int arg;
2936 
2937         optind = 0;
2938         if ((arg = getopt(argc, argv, "?")) != EOF) {
2939                 switch (arg) {
2940                 case '?':
2941                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2942                         return (optopt == '?' ? Z_OK : Z_USAGE);
2943                 default:
2944                         sub_usage(SHELP_VERIFY, CMD_VERIFY);
2945                         return (Z_USAGE);
2946                 }
2947         }
2948         if (argc > optind) {
2949                 sub_usage(SHELP_VERIFY, CMD_VERIFY);
2950                 return (Z_USAGE);
2951         }
2952         if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE, B_FALSE)
2953             != Z_OK)
2954                 return (Z_ERR);
2955         return (verify_details(CMD_VERIFY, argv));
2956 }
2957 
2958 static int
2959 addoptions(char *buf, char *argv[], size_t len)
2960 {
2961         int i = 0;
2962 
2963         if (buf[0] == '\0')
2964                 return (Z_OK);
2965 
2966         while (argv[i] != NULL) {
2967                 if (strlcat(buf, " ", len) >= len ||
2968                     strlcat(buf, argv[i++], len) >= len) {
2969                         zerror("Command line too long");
2970                         return (Z_ERR);
2971                 }
2972         }
2973 
2974         return (Z_OK);
2975 }
2976 
2977 static int
2978 addopt(char *buf, int opt, char *optarg, size_t bufsize)
2979 {
2980         char optstring[4];
2981 
2982         if (opt > 0)
2983                 (void) sprintf(optstring, " -%c", opt);
2984         else
2985                 (void) strcpy(optstring, " ");
2986 
2987         if ((strlcat(buf, optstring, bufsize) > bufsize))
2988                 return (Z_ERR);
2989 
2990         if ((optarg != NULL) && (strlcat(buf, optarg, bufsize) > bufsize))
2991                 return (Z_ERR);
2992 
2993         return (Z_OK);
2994 }
2995 
2996 /* ARGSUSED */
2997 static int
2998 install_func(int argc, char *argv[])
2999 {
3000         char cmdbuf[MAXPATHLEN];
3001         char postcmdbuf[MAXPATHLEN];
3002         int lockfd;
3003         int arg, err, subproc_err;
3004         char zonepath[MAXPATHLEN];
3005         brand_handle_t bh = NULL;
3006         int status;
3007         boolean_t do_postinstall = B_FALSE;
3008         boolean_t brand_help = B_FALSE;
3009         char opts[128];
3010 
3011         if (target_zone == NULL) {
3012                 sub_usage(SHELP_INSTALL, CMD_INSTALL);
3013                 return (Z_USAGE);
3014         }
3015 
3016         if (zonecfg_in_alt_root()) {
3017                 zerror(gettext("cannot install zone in alternate root"));
3018                 return (Z_ERR);
3019         }
3020 
3021         if ((err = zone_get_zonepath(target_zone, zonepath,
3022             sizeof (zonepath))) != Z_OK) {
3023                 errno = err;
3024                 zperror2(target_zone, gettext("could not get zone path"));
3025                 return (Z_ERR);
3026         }
3027 
3028         /* Fetch the install command from the brand configuration.  */
3029         if ((bh = brand_open(target_brand)) == NULL) {
3030                 zerror(gettext("missing or invalid brand"));
3031                 return (Z_ERR);
3032         }
3033 
3034         if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_install,
3035             target_zone, zonepath) != Z_OK) {
3036                 zerror("invalid brand configuration: missing install resource");
3037                 brand_close(bh);
3038                 return (Z_ERR);
3039         }
3040 
3041         if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postinstall,
3042             target_zone, zonepath) != Z_OK) {
3043                 zerror("invalid brand configuration: missing postinstall "
3044                     "resource");
3045                 brand_close(bh);
3046                 return (Z_ERR);
3047         }
3048 
3049         if (postcmdbuf[0] != '\0')
3050                 do_postinstall = B_TRUE;
3051 
3052         (void) strcpy(opts, "?x:");
3053         /*
3054          * Fetch the list of recognized command-line options from
3055          * the brand configuration file.
3056          */
3057         if (brand_get_installopts(bh, opts + strlen(opts),
3058             sizeof (opts) - strlen(opts)) != 0) {
3059                 zerror("invalid brand configuration: missing "
3060                     "install options resource");
3061                 brand_close(bh);
3062                 return (Z_ERR);
3063         }
3064 
3065         brand_close(bh);
3066 
3067         if (cmdbuf[0] == '\0') {
3068                 zerror("Missing brand install command");
3069                 return (Z_ERR);
3070         }
3071 
3072         /* Check the argv string for args we handle internally */
3073         optind = 0;
3074         opterr = 0;
3075         while ((arg = getopt(argc, argv, opts)) != EOF) {
3076                 switch (arg) {
3077                 case '?':
3078                         if (optopt == '?') {
3079                                 sub_usage(SHELP_INSTALL, CMD_INSTALL);
3080                                 brand_help = B_TRUE;
3081                         }
3082                         /* Ignore unknown options - may be brand specific. */
3083                         break;
3084                 default:
3085                         /* Ignore unknown options - may be brand specific. */
3086                         break;
3087                 }
3088 
3089                 /*
3090                  * Append the option to the command line passed to the
3091                  * brand-specific install and postinstall routines.
3092                  */
3093                 if (addopt(cmdbuf, optopt, optarg, sizeof (cmdbuf)) != Z_OK) {
3094                         zerror("Install command line too long");
3095                         return (Z_ERR);
3096                 }
3097                 if (addopt(postcmdbuf, optopt, optarg, sizeof (postcmdbuf))
3098                     != Z_OK) {
3099                         zerror("Post-Install command line too long");
3100                         return (Z_ERR);
3101                 }
3102         }
3103 
3104         for (; optind < argc; optind++) {
3105                 if (addopt(cmdbuf, 0, argv[optind], sizeof (cmdbuf)) != Z_OK) {
3106                         zerror("Install command line too long");
3107                         return (Z_ERR);
3108                 }
3109 
3110                 if (addopt(postcmdbuf, 0, argv[optind], sizeof (postcmdbuf))
3111                     != Z_OK) {
3112                         zerror("Post-Install command line too long");
3113                         return (Z_ERR);
3114                 }
3115         }
3116 
3117         if (!brand_help) {
3118                 if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE,
3119                     B_FALSE) != Z_OK)
3120                         return (Z_ERR);
3121                 if (verify_details(CMD_INSTALL, argv) != Z_OK)
3122                         return (Z_ERR);
3123 
3124                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
3125                         zerror(gettext("another %s may have an operation in "
3126                             "progress."), "zoneadm");
3127                         return (Z_ERR);
3128                 }
3129                 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3130                 if (err != Z_OK) {
3131                         errno = err;
3132                         zperror2(target_zone, gettext("could not set state"));
3133                         goto done;
3134                 }
3135 
3136                 create_zfs_zonepath(zonepath);
3137         }
3138 
3139         status = do_subproc(cmdbuf);
3140         if ((subproc_err =
3141             subproc_status(gettext("brand-specific installation"), status,
3142             B_FALSE)) != ZONE_SUBPROC_OK) {
3143                 if (subproc_err == ZONE_SUBPROC_USAGE && !brand_help) {
3144                         sub_usage(SHELP_INSTALL, CMD_INSTALL);
3145                         zonecfg_release_lock_file(target_zone, lockfd);
3146                         return (Z_ERR);
3147                 }
3148                 errno = subproc_err;
3149                 err = Z_ERR;
3150                 goto done;
3151         }
3152 
3153         if (brand_help)
3154                 return (Z_OK);
3155 
3156         if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3157                 errno = err;
3158                 zperror2(target_zone, gettext("could not set state"));
3159                 goto done;
3160         }
3161 
3162         if (do_postinstall) {
3163                 status = do_subproc(postcmdbuf);
3164 
3165                 if ((subproc_err =
3166                     subproc_status(gettext("brand-specific post-install"),
3167                     status, B_FALSE)) != ZONE_SUBPROC_OK) {
3168                         errno = subproc_err;
3169                         err = Z_ERR;
3170                         (void) zone_set_state(target_zone,
3171                             ZONE_STATE_INCOMPLETE);
3172                 }
3173         }
3174 
3175 done:
3176         /*
3177          * If the install script exited with ZONE_SUBPROC_NOTCOMPLETE, try to
3178          * clean up the zone and leave the zone in the CONFIGURED state so that
3179          * another install can be attempted without requiring an uninstall
3180          * first.
3181          */
3182         if (subproc_err == ZONE_SUBPROC_NOTCOMPLETE) {
3183                 int temp_err;
3184 
3185                 if ((temp_err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
3186                         errno = err = temp_err;
3187                         zperror2(target_zone,
3188                             gettext("cleaning up zonepath failed"));
3189                 } else if ((temp_err = zone_set_state(target_zone,
3190                     ZONE_STATE_CONFIGURED)) != Z_OK) {
3191                         errno = err = temp_err;
3192                         zperror2(target_zone, gettext("could not set state"));
3193                 }
3194         }
3195 
3196         if (!brand_help)
3197                 zonecfg_release_lock_file(target_zone, lockfd);
3198         return ((err == Z_OK) ? Z_OK : Z_ERR);
3199 }
3200 
3201 static void
3202 warn_dev_match(zone_dochandle_t s_handle, char *source_zone,
3203     zone_dochandle_t t_handle, char *target_zone)
3204 {
3205         int err;
3206         struct zone_devtab s_devtab;
3207         struct zone_devtab t_devtab;
3208 
3209         if ((err = zonecfg_setdevent(t_handle)) != Z_OK) {
3210                 errno = err;
3211                 zperror2(target_zone, gettext("could not enumerate devices"));
3212                 return;
3213         }
3214 
3215         while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) {
3216                 if ((err = zonecfg_setdevent(s_handle)) != Z_OK) {
3217                         errno = err;
3218                         zperror2(source_zone,
3219                             gettext("could not enumerate devices"));
3220                         (void) zonecfg_enddevent(t_handle);
3221                         return;
3222                 }
3223 
3224                 while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) {
3225                         /*
3226                          * Use fnmatch to catch the case where wildcards
3227                          * were used in one zone and the other has an
3228                          * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs.
3229                          * /dev/\*dsk/c0t0d0s6).
3230                          */
3231                         if (fnmatch(t_devtab.zone_dev_match,
3232                             s_devtab.zone_dev_match, FNM_PATHNAME) == 0 ||
3233                             fnmatch(s_devtab.zone_dev_match,
3234                             t_devtab.zone_dev_match, FNM_PATHNAME) == 0) {
3235                                 (void) fprintf(stderr,
3236                                     gettext("WARNING: device '%s' "
3237                                     "is configured in both zones.\n"),
3238                                     t_devtab.zone_dev_match);
3239                                 break;
3240                         }
3241                 }
3242                 (void) zonecfg_enddevent(s_handle);
3243         }
3244 
3245         (void) zonecfg_enddevent(t_handle);
3246 }
3247 
3248 /*
3249  * Check if the specified mount option (opt) is contained within the
3250  * options string.
3251  */
3252 static boolean_t
3253 opt_match(char *opt, char *options)
3254 {
3255         char *p;
3256         char *lastp;
3257 
3258         if ((p = strtok_r(options, ",", &lastp)) != NULL) {
3259                 if (strcmp(p, opt) == 0)
3260                         return (B_TRUE);
3261                 while ((p = strtok_r(NULL, ",", &lastp)) != NULL) {
3262                         if (strcmp(p, opt) == 0)
3263                                 return (B_TRUE);
3264                 }
3265         }
3266 
3267         return (B_FALSE);
3268 }
3269 
3270 #define RW_LOFS "WARNING: read-write lofs file system on '%s' is configured " \
3271         "in both zones.\n"
3272 
3273 static void
3274 print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
3275 {
3276         /*
3277          * It is ok to have shared lofs mounted fs but we want to warn if
3278          * either is rw since this will effect the other zone.
3279          */
3280         if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) {
3281                 zone_fsopt_t *optp;
3282 
3283                 /* The default is rw so no options means rw */
3284                 if (t_fstab->zone_fs_options == NULL ||
3285                     s_fstab->zone_fs_options == NULL) {
3286                         (void) fprintf(stderr, gettext(RW_LOFS),
3287                             t_fstab->zone_fs_special);
3288                         return;
3289                 }
3290 
3291                 for (optp = s_fstab->zone_fs_options; optp != NULL;
3292                     optp = optp->zone_fsopt_next) {
3293                         if (opt_match("rw", optp->zone_fsopt_opt)) {
3294                                 (void) fprintf(stderr, gettext(RW_LOFS),
3295                                     s_fstab->zone_fs_special);
3296                                 return;
3297                         }
3298                 }
3299 
3300                 for (optp = t_fstab->zone_fs_options; optp != NULL;
3301                     optp = optp->zone_fsopt_next) {
3302                         if (opt_match("rw", optp->zone_fsopt_opt)) {
3303                                 (void) fprintf(stderr, gettext(RW_LOFS),
3304                                     t_fstab->zone_fs_special);
3305                                 return;
3306                         }
3307                 }
3308 
3309                 return;
3310         }
3311 
3312         /*
3313          * TRANSLATION_NOTE
3314          * The first variable is the file system type and the second is
3315          * the file system special device.  For example,
3316          * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
3317          */
3318         (void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
3319             "is configured in both zones.\n"), t_fstab->zone_fs_type,
3320             t_fstab->zone_fs_special);
3321 }
3322 
3323 static void
3324 warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
3325     zone_dochandle_t t_handle, char *target_zone)
3326 {
3327         int err;
3328         struct zone_fstab s_fstab;
3329         struct zone_fstab t_fstab;
3330 
3331         if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
3332                 errno = err;
3333                 zperror2(target_zone,
3334                     gettext("could not enumerate file systems"));
3335                 return;
3336         }
3337 
3338         while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
3339                 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
3340                         errno = err;
3341                         zperror2(source_zone,
3342                             gettext("could not enumerate file systems"));
3343                         (void) zonecfg_endfsent(t_handle);
3344                         return;
3345                 }
3346 
3347                 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
3348                         if (strcmp(t_fstab.zone_fs_special,
3349                             s_fstab.zone_fs_special) == 0) {
3350                                 print_fs_warnings(&s_fstab, &t_fstab);
3351                                 break;
3352                         }
3353                 }
3354                 (void) zonecfg_endfsent(s_handle);
3355         }
3356 
3357         (void) zonecfg_endfsent(t_handle);
3358 }
3359 
3360 /*
3361  * We don't catch the case where you used the same IP address but
3362  * it is not an exact string match.  For example, 192.9.0.128 vs. 192.09.0.128.
3363  * However, we're not going to worry about that but we will check for
3364  * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24)
3365  * and handle that case as a match.
3366  */
3367 static void
3368 warn_ip_match(zone_dochandle_t s_handle, char *source_zone,
3369     zone_dochandle_t t_handle, char *target_zone)
3370 {
3371         int err;
3372         struct zone_nwiftab s_nwiftab;
3373         struct zone_nwiftab t_nwiftab;
3374 
3375         if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) {
3376                 errno = err;
3377                 zperror2(target_zone,
3378                     gettext("could not enumerate network interfaces"));
3379                 return;
3380         }
3381 
3382         while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) {
3383                 char *p;
3384 
3385                 /* remove an (optional) netmask from the address */
3386                 if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL)
3387                         *p = '\0';
3388 
3389                 if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) {
3390                         errno = err;
3391                         zperror2(source_zone,
3392                             gettext("could not enumerate network interfaces"));
3393                         (void) zonecfg_endnwifent(t_handle);
3394                         return;
3395                 }
3396 
3397                 while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) {
3398                         /* remove an (optional) netmask from the address */
3399                         if ((p = strchr(s_nwiftab.zone_nwif_address, '/'))
3400                             != NULL)
3401                                 *p = '\0';
3402 
3403                         /* For exclusive-IP zones, address is not specified. */
3404                         if (strlen(s_nwiftab.zone_nwif_address) == 0)
3405                                 continue;
3406 
3407                         if (strcmp(t_nwiftab.zone_nwif_address,
3408                             s_nwiftab.zone_nwif_address) == 0) {
3409                                 (void) fprintf(stderr,
3410                                     gettext("WARNING: network address '%s' "
3411                                     "is configured in both zones.\n"),
3412                                     t_nwiftab.zone_nwif_address);
3413                                 break;
3414                         }
3415                 }
3416                 (void) zonecfg_endnwifent(s_handle);
3417         }
3418 
3419         (void) zonecfg_endnwifent(t_handle);
3420 }
3421 
3422 static void
3423 warn_dataset_match(zone_dochandle_t s_handle, char *source,
3424     zone_dochandle_t t_handle, char *target)
3425 {
3426         int err;
3427         struct zone_dstab s_dstab;
3428         struct zone_dstab t_dstab;
3429 
3430         if ((err = zonecfg_setdsent(t_handle)) != Z_OK) {
3431                 errno = err;
3432                 zperror2(target, gettext("could not enumerate datasets"));
3433                 return;
3434         }
3435 
3436         while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) {
3437                 if ((err = zonecfg_setdsent(s_handle)) != Z_OK) {
3438                         errno = err;
3439                         zperror2(source,
3440                             gettext("could not enumerate datasets"));
3441                         (void) zonecfg_enddsent(t_handle);
3442                         return;
3443                 }
3444 
3445                 while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) {
3446                         if (strcmp(t_dstab.zone_dataset_name,
3447                             s_dstab.zone_dataset_name) == 0) {
3448                                 target_zone = source;
3449                                 zerror(gettext("WARNING: dataset '%s' "
3450                                     "is configured in both zones.\n"),
3451                                     t_dstab.zone_dataset_name);
3452                                 break;
3453                         }
3454                 }
3455                 (void) zonecfg_enddsent(s_handle);
3456         }
3457 
3458         (void) zonecfg_enddsent(t_handle);
3459 }
3460 
3461 /*
3462  * Check that the clone and its source have the same brand type.
3463  */
3464 static int
3465 valid_brand_clone(char *source_zone, char *target_zone)
3466 {
3467         brand_handle_t bh;
3468         char source_brand[MAXNAMELEN];
3469 
3470         if ((zone_get_brand(source_zone, source_brand,
3471             sizeof (source_brand))) != Z_OK) {
3472                 (void) fprintf(stderr, "%s: zone '%s': %s\n",
3473                     execname, source_zone, gettext("missing or invalid brand"));
3474                 return (Z_ERR);
3475         }
3476 
3477         if (strcmp(source_brand, target_brand) != 0) {
3478                 (void) fprintf(stderr,
3479                     gettext("%s: Zones '%s' and '%s' have different brand "
3480                     "types.\n"), execname, source_zone, target_zone);
3481                 return (Z_ERR);
3482         }
3483 
3484         if ((bh = brand_open(target_brand)) == NULL) {
3485                 zerror(gettext("missing or invalid brand"));
3486                 return (Z_ERR);
3487         }
3488         brand_close(bh);
3489         return (Z_OK);
3490 }
3491 
3492 static int
3493 validate_clone(char *source_zone, char *target_zone)
3494 {
3495         int err = Z_OK;
3496         zone_dochandle_t s_handle;
3497         zone_dochandle_t t_handle;
3498 
3499         if ((t_handle = zonecfg_init_handle()) == NULL) {
3500                 zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3501                 return (Z_ERR);
3502         }
3503         if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) {
3504                 errno = err;
3505                 zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3506                 zonecfg_fini_handle(t_handle);
3507                 return (Z_ERR);
3508         }
3509 
3510         if ((s_handle = zonecfg_init_handle()) == NULL) {
3511                 zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3512                 zonecfg_fini_handle(t_handle);
3513                 return (Z_ERR);
3514         }
3515         if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) {
3516                 errno = err;
3517                 zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3518                 goto done;
3519         }
3520 
3521         /* verify new zone has same brand type */
3522         err = valid_brand_clone(source_zone, target_zone);
3523         if (err != Z_OK)
3524                 goto done;
3525 
3526         /* warn about imported fs's which are the same */
3527         warn_fs_match(s_handle, source_zone, t_handle, target_zone);
3528 
3529         /* warn about imported IP addresses which are the same */
3530         warn_ip_match(s_handle, source_zone, t_handle, target_zone);
3531 
3532         /* warn about imported devices which are the same */
3533         warn_dev_match(s_handle, source_zone, t_handle, target_zone);
3534 
3535         /* warn about imported datasets which are the same */
3536         warn_dataset_match(s_handle, source_zone, t_handle, target_zone);
3537 
3538 done:
3539         zonecfg_fini_handle(t_handle);
3540         zonecfg_fini_handle(s_handle);
3541 
3542         return ((err == Z_OK) ? Z_OK : Z_ERR);
3543 }
3544 
3545 static int
3546 copy_zone(char *src, char *dst)
3547 {
3548         boolean_t out_null = B_FALSE;
3549         int status;
3550         char *outfile;
3551         char cmdbuf[MAXPATHLEN * 2 + 128];
3552 
3553         if ((outfile = tempnam("/var/log", "zone")) == NULL) {
3554                 outfile = "/dev/null";
3555                 out_null = B_TRUE;
3556         }
3557 
3558         /*
3559          * Use find to get the list of files to copy.  We need to skip
3560          * files of type "socket" since cpio can't handle those but that
3561          * should be ok since the app will recreate the socket when it runs.
3562          * We also need to filter out anything under the .zfs subdir.  Since
3563          * find is running depth-first, we need the extra egrep to filter .zfs.
3564          */
3565         (void) snprintf(cmdbuf, sizeof (cmdbuf),
3566             "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
3567             "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
3568             "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
3569             src, dst, outfile);
3570 
3571         status = do_subproc(cmdbuf);
3572 
3573         if (subproc_status("copy", status, B_TRUE) != ZONE_SUBPROC_OK) {
3574                 if (!out_null)
3575                         (void) fprintf(stderr, gettext("\nThe copy failed.\n"
3576                             "More information can be found in %s\n"), outfile);
3577                 return (Z_ERR);
3578         }
3579 
3580         if (!out_null)
3581                 (void) unlink(outfile);
3582 
3583         return (Z_OK);
3584 }
3585 
3586 /* ARGSUSED */
3587 int
3588 zfm_print(const struct mnttab *p, void *r)
3589 {
3590         zerror("  %s\n", p->mnt_mountp);
3591         return (0);
3592 }
3593 
3594 int
3595 clone_copy(char *source_zonepath, char *zonepath)
3596 {
3597         int err;
3598 
3599         /* Don't clone the zone if anything is still mounted there */
3600         if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
3601                 zerror(gettext("These file systems are mounted on "
3602                     "subdirectories of %s.\n"), source_zonepath);
3603                 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
3604                 return (Z_ERR);
3605         }
3606 
3607         /*
3608          * Attempt to create a ZFS fs for the zonepath.  As usual, we don't
3609          * care if this works or not since we always have the default behavior
3610          * of a simple directory for the zonepath.
3611          */
3612         create_zfs_zonepath(zonepath);
3613 
3614         (void) printf(gettext("Copying %s..."), source_zonepath);
3615         (void) fflush(stdout);
3616 
3617         err = copy_zone(source_zonepath, zonepath);
3618 
3619         (void) printf("\n");
3620 
3621         return (err);
3622 }
3623 
3624 static int
3625 clone_func(int argc, char *argv[])
3626 {
3627         char *source_zone = NULL;
3628         int lockfd;
3629         int err, arg;
3630         char zonepath[MAXPATHLEN];
3631         char source_zonepath[MAXPATHLEN];
3632         zone_state_t state;
3633         zone_entry_t *zent;
3634         char *method = NULL;
3635         char *snapshot = NULL;
3636         char cmdbuf[MAXPATHLEN];
3637         char postcmdbuf[MAXPATHLEN];
3638         char presnapbuf[MAXPATHLEN];
3639         char postsnapbuf[MAXPATHLEN];
3640         char validsnapbuf[MAXPATHLEN];
3641         brand_handle_t bh = NULL;
3642         int status;
3643         boolean_t brand_help = B_FALSE;
3644 
3645         if (zonecfg_in_alt_root()) {
3646                 zerror(gettext("cannot clone zone in alternate root"));
3647                 return (Z_ERR);
3648         }
3649 
3650         /* Check the argv string for args we handle internally */
3651         optind = 0;
3652         opterr = 0;
3653         while ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
3654                 switch (arg) {
3655                 case '?':
3656                         if (optopt == '?') {
3657                                 sub_usage(SHELP_CLONE, CMD_CLONE);
3658                                 brand_help = B_TRUE;
3659                         }
3660                         /* Ignore unknown options - may be brand specific. */
3661                         break;
3662                 case 'm':
3663                         method = optarg;
3664                         break;
3665                 case 's':
3666                         snapshot = optarg;
3667                         break;
3668                 default:
3669                         /* Ignore unknown options - may be brand specific. */
3670                         break;
3671                 }
3672         }
3673 
3674         if (argc != (optind + 1)) {
3675                 sub_usage(SHELP_CLONE, CMD_CLONE);
3676                 return (Z_USAGE);
3677         }
3678 
3679         source_zone = argv[optind];
3680 
3681         if (!brand_help) {
3682                 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE,
3683                     B_FALSE) != Z_OK)
3684                         return (Z_ERR);
3685                 if (verify_details(CMD_CLONE, argv) != Z_OK)
3686                         return (Z_ERR);
3687 
3688                 /*
3689                  * We also need to do some extra validation on the source zone.
3690                  */
3691                 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3692                         zerror(gettext("%s operation is invalid for the "
3693                             "global zone."), cmd_to_str(CMD_CLONE));
3694                         return (Z_ERR);
3695                 }
3696 
3697                 if (strncmp(source_zone, "SUNW", 4) == 0) {
3698                         zerror(gettext("%s operation is invalid for zones "
3699                             "starting with SUNW."), cmd_to_str(CMD_CLONE));
3700                         return (Z_ERR);
3701                 }
3702 
3703                 if (auth_check(username, source_zone, SOURCE_ZONE) == Z_ERR) {
3704                         zerror(gettext("%s operation is invalid because "
3705                             "user is not authorized to read source zone."),
3706                             cmd_to_str(CMD_CLONE));
3707                         return (Z_ERR);
3708                 }
3709 
3710                 zent = lookup_running_zone(source_zone);
3711                 if (zent != NULL) {
3712                         /* check whether the zone is ready or running */
3713                         if ((err = zone_get_state(zent->zname,
3714                             &zent->zstate_num)) != Z_OK) {
3715                                 errno = err;
3716                                 zperror2(zent->zname, gettext("could not get "
3717                                     "state"));
3718                                 /* can't tell, so hedge */
3719                                 zent->zstate_str = "ready/running";
3720                         } else {
3721                                 zent->zstate_str =
3722                                     zone_state_str(zent->zstate_num);
3723                         }
3724                         zerror(gettext("%s operation is invalid for %s zones."),
3725                             cmd_to_str(CMD_CLONE), zent->zstate_str);
3726                         return (Z_ERR);
3727                 }
3728 
3729                 if ((err = zone_get_state(source_zone, &state)) != Z_OK) {
3730                         errno = err;
3731                         zperror2(source_zone, gettext("could not get state"));
3732                         return (Z_ERR);
3733                 }
3734                 if (state != ZONE_STATE_INSTALLED) {
3735                         (void) fprintf(stderr,
3736                             gettext("%s: zone %s is %s; %s is required.\n"),
3737                             execname, source_zone, zone_state_str(state),
3738                             zone_state_str(ZONE_STATE_INSTALLED));
3739                         return (Z_ERR);
3740                 }
3741 
3742                 /*
3743                  * The source zone checks out ok, continue with the clone.
3744                  */
3745 
3746                 if (validate_clone(source_zone, target_zone) != Z_OK)
3747                         return (Z_ERR);
3748 
3749                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
3750                         zerror(gettext("another %s may have an operation in "
3751                             "progress."), "zoneadm");
3752                         return (Z_ERR);
3753                 }
3754         }
3755 
3756         if ((err = zone_get_zonepath(source_zone, source_zonepath,
3757             sizeof (source_zonepath))) != Z_OK) {
3758                 errno = err;
3759                 zperror2(source_zone, gettext("could not get zone path"));
3760                 goto done;
3761         }
3762 
3763         if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3764             != Z_OK) {
3765                 errno = err;
3766                 zperror2(target_zone, gettext("could not get zone path"));
3767                 goto done;
3768         }
3769 
3770         /*
3771          * Fetch the clone and postclone hooks from the brand configuration.
3772          */
3773         if ((bh = brand_open(target_brand)) == NULL) {
3774                 zerror(gettext("missing or invalid brand"));
3775                 err = Z_ERR;
3776                 goto done;
3777         }
3778 
3779         if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_clone, target_zone,
3780             zonepath) != Z_OK) {
3781                 zerror("invalid brand configuration: missing clone resource");
3782                 brand_close(bh);
3783                 err = Z_ERR;
3784                 goto done;
3785         }
3786 
3787         if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postclone,
3788             target_zone, zonepath) != Z_OK) {
3789                 zerror("invalid brand configuration: missing postclone "
3790                     "resource");
3791                 brand_close(bh);
3792                 err = Z_ERR;
3793                 goto done;
3794         }
3795 
3796         if (get_hook(bh, presnapbuf, sizeof (presnapbuf), brand_get_presnap,
3797             source_zone, source_zonepath) != Z_OK) {
3798                 zerror("invalid brand configuration: missing presnap "
3799                     "resource");
3800                 brand_close(bh);
3801                 err = Z_ERR;
3802                 goto done;
3803         }
3804 
3805         if (get_hook(bh, postsnapbuf, sizeof (postsnapbuf), brand_get_postsnap,
3806             source_zone, source_zonepath) != Z_OK) {
3807                 zerror("invalid brand configuration: missing postsnap "
3808                     "resource");
3809                 brand_close(bh);
3810                 err = Z_ERR;
3811                 goto done;
3812         }
3813 
3814         if (get_hook(bh, validsnapbuf, sizeof (validsnapbuf),
3815             brand_get_validatesnap, target_zone, zonepath) != Z_OK) {
3816                 zerror("invalid brand configuration: missing validatesnap "
3817                     "resource");
3818                 brand_close(bh);
3819                 err = Z_ERR;
3820                 goto done;
3821         }
3822         brand_close(bh);
3823 
3824         /* Append all options to clone hook. */
3825         if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK) {
3826                 err = Z_ERR;
3827                 goto done;
3828         }
3829 
3830         /* Append all options to postclone hook. */
3831         if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK) {
3832                 err = Z_ERR;
3833                 goto done;
3834         }
3835 
3836         if (!brand_help) {
3837                 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3838                     != Z_OK) {
3839                         errno = err;
3840                         zperror2(target_zone, gettext("could not set state"));
3841                         goto done;
3842                 }
3843         }
3844 
3845         /*
3846          * The clone hook is optional.  If it exists, use the hook for
3847          * cloning, otherwise use the built-in clone support
3848          */
3849         if (cmdbuf[0] != '\0') {
3850                 /* Run the clone hook */
3851                 status = do_subproc(cmdbuf);
3852                 if ((status = subproc_status(gettext("brand-specific clone"),
3853                     status, B_FALSE)) != ZONE_SUBPROC_OK) {
3854                         if (status == ZONE_SUBPROC_USAGE && !brand_help)
3855                                 sub_usage(SHELP_CLONE, CMD_CLONE);
3856                         err = Z_ERR;
3857                         goto done;
3858                 }
3859 
3860                 if (brand_help)
3861                         return (Z_OK);
3862 
3863         } else {
3864                 /* If just help, we're done since there is no brand help. */
3865                 if (brand_help)
3866                         return (Z_OK);
3867 
3868                 /* Run the built-in clone support. */
3869 
3870                 /* The only explicit built-in method is "copy". */
3871                 if (method != NULL && strcmp(method, "copy") != 0) {
3872                         sub_usage(SHELP_CLONE, CMD_CLONE);
3873                         err = Z_USAGE;
3874                         goto done;
3875                 }
3876 
3877                 if (snapshot != NULL) {
3878                         err = clone_snapshot_zfs(snapshot, zonepath,
3879                             validsnapbuf);
3880                 } else {
3881                         /*
3882                          * We always copy the clone unless the source is ZFS
3883                          * and a ZFS clone worked.  We fallback to copying if
3884                          * the ZFS clone fails for some reason.
3885                          */
3886                         err = Z_ERR;
3887                         if (method == NULL && is_zonepath_zfs(source_zonepath))
3888                                 err = clone_zfs(source_zonepath, zonepath,
3889                                     presnapbuf, postsnapbuf);
3890 
3891                         if (err != Z_OK)
3892                                 err = clone_copy(source_zonepath, zonepath);
3893                 }
3894         }
3895 
3896         if (err == Z_OK && postcmdbuf[0] != '\0') {
3897                 status = do_subproc(postcmdbuf);
3898                 if ((err = subproc_status("postclone", status, B_FALSE))
3899                     != ZONE_SUBPROC_OK) {
3900                         zerror(gettext("post-clone configuration failed."));
3901                         err = Z_ERR;
3902                 }
3903         }
3904 
3905 done:
3906         /*
3907          * If everything went well, we mark the zone as installed.
3908          */
3909         if (err == Z_OK) {
3910                 err = zone_set_state(target_zone, ZONE_STATE_INSTALLED);
3911                 if (err != Z_OK) {
3912                         errno = err;
3913                         zperror2(target_zone, gettext("could not set state"));
3914                 }
3915         }
3916         if (!brand_help)
3917                 zonecfg_release_lock_file(target_zone, lockfd);
3918         return ((err == Z_OK) ? Z_OK : Z_ERR);
3919 }
3920 
3921 /*
3922  * Used when removing a zonepath after uninstalling or cleaning up after
3923  * the move subcommand.  This handles a zonepath that has non-standard
3924  * contents so that we will only cleanup the stuff we know about and leave
3925  * any user data alone.
3926  *
3927  * If the "all" parameter is true then we should remove the whole zonepath
3928  * even if it has non-standard files/directories in it.  This can be used when
3929  * we need to cleanup after moving the zonepath across file systems.
3930  *
3931  * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
3932  * and not the shell.
3933  */
3934 static int
3935 cleanup_zonepath(char *zonepath, boolean_t all)
3936 {
3937         int             status;
3938         int             i;
3939         boolean_t       non_std = B_FALSE;
3940         struct dirent   *dp;
3941         DIR             *dirp;
3942                         /*
3943                          * The SUNWattached.xml file is expected since it might
3944                          * exist if the zone was force-attached after a
3945                          * migration.
3946                          */
3947         char            *std_entries[] = {"dev", "lu", "root",
3948                             "SUNWattached.xml", NULL};
3949                         /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
3950         char            cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
3951 
3952         /*
3953          * We shouldn't need these checks but lets be paranoid since we
3954          * could blow away the whole system here if we got the wrong zonepath.
3955          */
3956         if (*zonepath == '\0' || strcmp(zonepath, "/") == 0) {
3957                 (void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
3958                 return (Z_INVAL);
3959         }
3960 
3961         /*
3962          * If the dirpath is already gone (maybe it was manually removed) then
3963          * we just return Z_OK so that the cleanup is successful.
3964          */
3965         if ((dirp = opendir(zonepath)) == NULL)
3966                 return (Z_OK);
3967 
3968         /*
3969          * Look through the zonepath directory to see if there are any
3970          * non-standard files/dirs.  Also skip .zfs since that might be
3971          * there but we'll handle ZFS file systems as a special case.
3972          */
3973         while ((dp = readdir(dirp)) != NULL) {
3974                 if (strcmp(dp->d_name, ".") == 0 ||
3975                     strcmp(dp->d_name, "..") == 0 ||
3976                     strcmp(dp->d_name, ".zfs") == 0)
3977                         continue;
3978 
3979                 for (i = 0; std_entries[i] != NULL; i++)
3980                         if (strcmp(dp->d_name, std_entries[i]) == 0)
3981                                 break;
3982 
3983                 if (std_entries[i] == NULL)
3984                         non_std = B_TRUE;
3985         }
3986         (void) closedir(dirp);
3987 
3988         if (!all && non_std) {
3989                 /*
3990                  * There are extra, non-standard directories/files in the
3991                  * zonepath so we don't want to remove the zonepath.  We
3992                  * just want to remove the standard directories and leave
3993                  * the user data alone.
3994                  */
3995                 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
3996 
3997                 for (i = 0; std_entries[i] != NULL; i++) {
3998                         char tmpbuf[MAXPATHLEN];
3999 
4000                         if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
4001                             zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
4002                             strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
4003                             sizeof (cmdbuf)) {
4004                                 (void) fprintf(stderr,
4005                                     gettext("path is too long\n"));
4006                                 return (Z_INVAL);
4007                         }
4008                 }
4009 
4010                 status = do_subproc(cmdbuf);
4011 
4012                 (void) fprintf(stderr, gettext("WARNING: Unable to completely "
4013                     "remove %s\nbecause it contains additional user data.  "
4014                     "Only the standard directory\nentries have been "
4015                     "removed.\n"),
4016                     zonepath);
4017 
4018                 return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4019                     ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4020         }
4021 
4022         /*
4023          * There is nothing unexpected in the zonepath, try to get rid of the
4024          * whole zonepath directory.
4025          *
4026          * If the zonepath is its own zfs file system, try to destroy the
4027          * file system.  If that fails for some reason (e.g. it has clones)
4028          * then we'll just remove the contents of the zonepath.
4029          */
4030         if (is_zonepath_zfs(zonepath)) {
4031                 if (destroy_zfs(zonepath) == Z_OK)
4032                         return (Z_OK);
4033                 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
4034                     " %s/*", zonepath);
4035                 status = do_subproc(cmdbuf);
4036                 return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4037                     ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4038         }
4039 
4040         (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
4041             zonepath);
4042         status = do_subproc(cmdbuf);
4043 
4044         return ((subproc_status(RMCOMMAND, status, B_TRUE) == ZONE_SUBPROC_OK)
4045             ? Z_OK : Z_ERR);
4046 }
4047 
4048 static int
4049 move_func(int argc, char *argv[])
4050 {
4051         char *new_zonepath = NULL;
4052         int lockfd;
4053         int err, arg;
4054         char zonepath[MAXPATHLEN];
4055         zone_dochandle_t handle;
4056         boolean_t fast;
4057         boolean_t is_zfs = B_FALSE;
4058         boolean_t root_fs_mounted = B_FALSE;
4059         struct dirent *dp;
4060         DIR *dirp;
4061         boolean_t empty = B_TRUE;
4062         boolean_t revert;
4063         struct stat zonepath_buf;
4064         struct stat new_zonepath_buf;
4065         zone_mounts_t mounts;
4066 
4067         if (zonecfg_in_alt_root()) {
4068                 zerror(gettext("cannot move zone in alternate root"));
4069                 return (Z_ERR);
4070         }
4071 
4072         optind = 0;
4073         if ((arg = getopt(argc, argv, "?")) != EOF) {
4074                 switch (arg) {
4075                 case '?':
4076                         sub_usage(SHELP_MOVE, CMD_MOVE);
4077                         return (optopt == '?' ? Z_OK : Z_USAGE);
4078                 default:
4079                         sub_usage(SHELP_MOVE, CMD_MOVE);
4080                         return (Z_USAGE);
4081                 }
4082         }
4083         if (argc != (optind + 1)) {
4084                 sub_usage(SHELP_MOVE, CMD_MOVE);
4085                 return (Z_USAGE);
4086         }
4087         new_zonepath = argv[optind];
4088         if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE, B_FALSE)
4089             != Z_OK)
4090                 return (Z_ERR);
4091         if (verify_details(CMD_MOVE, argv) != Z_OK)
4092                 return (Z_ERR);
4093 
4094         /*
4095          * Check out the new zonepath.  This has the side effect of creating
4096          * a directory for the new zonepath.  We depend on this later when we
4097          * stat to see if we are doing a cross file system move or not.
4098          */
4099         if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
4100                 return (Z_ERR);
4101 
4102         if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4103             != Z_OK) {
4104                 errno = err;
4105                 zperror2(target_zone, gettext("could not get zone path"));
4106                 return (Z_ERR);
4107         }
4108 
4109         if (stat(zonepath, &zonepath_buf) == -1) {
4110                 zperror(gettext("could not stat zone path"), B_FALSE);
4111                 return (Z_ERR);
4112         }
4113 
4114         if (stat(new_zonepath, &new_zonepath_buf) == -1) {
4115                 zperror(gettext("could not stat new zone path"), B_FALSE);
4116                 return (Z_ERR);
4117         }
4118 
4119         /*
4120          * Check if the destination directory is empty.
4121          */
4122         if ((dirp = opendir(new_zonepath)) == NULL) {
4123                 zperror(gettext("could not open new zone path"), B_FALSE);
4124                 return (Z_ERR);
4125         }
4126         while ((dp = readdir(dirp)) != (struct dirent *)0) {
4127                 if (strcmp(dp->d_name, ".") == 0 ||
4128                     strcmp(dp->d_name, "..") == 0)
4129                         continue;
4130                 empty = B_FALSE;
4131                 break;
4132         }
4133         (void) closedir(dirp);
4134 
4135         /* Error if there is anything in the destination directory. */
4136         if (!empty) {
4137                 (void) fprintf(stderr, gettext("could not move zone to %s: "
4138                     "directory not empty\n"), new_zonepath);
4139                 return (Z_ERR);
4140         }
4141 
4142         /*
4143          * Collect information about mounts within the zone's zonepath.
4144          * Overlay mounts on the zone's root directory are erroneous.
4145          * Bail if we encounter any unexpected mounts.
4146          */
4147         if (zone_mounts_init(&mounts, zonepath) != 0)
4148                 return (Z_ERR);
4149         if (mounts.num_root_overlay_mounts != 0) {
4150                 zerror(gettext("%d overlay mount(s) detected on %s/root."),
4151                     mounts.num_root_overlay_mounts, zonepath);
4152                 goto err_and_mounts_destroy;
4153         }
4154         if (mounts.num_unexpected_mounts != 0)
4155                 goto err_and_mounts_destroy;
4156 
4157         /*
4158          * Check if we are moving in the same file system and can do a fast
4159          * move or if we are crossing file systems and have to copy the data.
4160          */
4161         fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
4162 
4163         if ((handle = zonecfg_init_handle()) == NULL) {
4164                 zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4165                 goto err_and_mounts_destroy;
4166         }
4167 
4168         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4169                 errno = err;
4170                 zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4171                 goto err_and_fini_handle;
4172         }
4173 
4174         if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4175                 zerror(gettext("another %s may have an operation in progress."),
4176                     "zoneadm");
4177                 goto err_and_fini_handle;
4178         }
4179 
4180         /*
4181          * Unmount the zone's root filesystem before we move the zone's
4182          * zonepath.
4183          */
4184         if (zone_unmount_rootfs(&mounts, zonepath, B_FALSE) != 0)
4185                 goto err_and_rele_lockfile;
4186 
4187         /*
4188          * We're making some file system changes now so we have to clean up
4189          * the file system before we are done.  This will either clean up the
4190          * new zonepath if the zonecfg update failed or it will clean up the
4191          * old zonepath if everything is ok.
4192          */
4193         revert = B_TRUE;
4194 
4195         if (is_zonepath_zfs(zonepath) &&
4196             move_zfs(zonepath, new_zonepath) != Z_ERR) {
4197                 is_zfs = B_TRUE;
4198 
4199         } else if (fast) {
4200                 /* same file system, use rename for a quick move */
4201 
4202                 /*
4203                  * Remove the new_zonepath directory that got created above
4204                  * during the validation.  It gets in the way of the rename.
4205                  */
4206                 if (rmdir(new_zonepath) != 0) {
4207                         zperror(gettext("could not rmdir new zone path"),
4208                             B_FALSE);
4209                         (void) zone_mount_rootfs(&mounts, zonepath);
4210                         goto err_and_rele_lockfile;
4211                 }
4212 
4213                 if (rename(zonepath, new_zonepath) != 0) {
4214                         /*
4215                          * If this fails we don't need to do all of the
4216                          * cleanup that happens for the rest of the code
4217                          * so just return from this error.
4218                          */
4219                         zperror(gettext("could not move zone"), B_FALSE);
4220                         (void) zone_mount_rootfs(&mounts, zonepath);
4221                         goto err_and_rele_lockfile;
4222                 }
4223 
4224         } else {
4225                 /*
4226                  * Attempt to create a ZFS fs for the new zonepath.  As usual,
4227                  * we don't care if this works or not since we always have the
4228                  * default behavior of a simple directory for the zonepath.
4229                  */
4230                 create_zfs_zonepath(new_zonepath);
4231 
4232                 (void) printf(gettext(
4233                     "Moving across file systems; copying zonepath %s..."),
4234                     zonepath);
4235                 (void) fflush(stdout);
4236 
4237                 err = copy_zone(zonepath, new_zonepath);
4238 
4239                 (void) printf("\n");
4240                 if (err != Z_OK)
4241                         goto done;
4242         }
4243 
4244         /*
4245          * Mount the zone's root filesystem in the new zonepath if there was
4246          * a root mount prior to the move.
4247          */
4248         if (zone_mount_rootfs(&mounts, new_zonepath) != 0) {
4249                 err = Z_ERR;
4250                 goto done;
4251         }
4252         root_fs_mounted = B_TRUE;
4253 
4254         if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
4255                 errno = err;
4256                 zperror(gettext("could not set new zonepath"), B_TRUE);
4257                 goto done;
4258         }
4259 
4260         if ((err = zonecfg_save(handle)) != Z_OK) {
4261                 errno = err;
4262                 zperror(gettext("zonecfg save failed"), B_TRUE);
4263                 goto done;
4264         }
4265 
4266         revert = B_FALSE;
4267 
4268 done:
4269         zonecfg_fini_handle(handle);
4270         zonecfg_release_lock_file(target_zone, lockfd);
4271 
4272         /*
4273          * Clean up the file system based on how things went.  We either
4274          * clean up the new zonepath if the operation failed for some reason
4275          * or we clean up the old zonepath if everything is ok.
4276          */
4277         if (revert) {
4278                 /*
4279                  * Check for the unlikely scenario in which the zone's
4280                  * zonepath and its root file system moved but libzonecfg
4281                  * couldn't save the new zonepath to the zone's configuration
4282                  * file.  The mounted root filesystem must be unmounted before
4283                  * zoneadm restores the zone's zonepath.
4284                  */
4285                 if (root_fs_mounted && zone_unmount_rootfs(&mounts,
4286                     new_zonepath, B_TRUE) != 0) {
4287                         /*
4288                          * We can't forcibly unmount the zone's root file system
4289                          * from the new zonepath.  Bail!
4290                          */
4291                         zerror(gettext("fatal error: cannot unmount %s/root\n"),
4292                             new_zonepath);
4293                         goto err_and_mounts_destroy;
4294                 }
4295 
4296                 /* The zonecfg update failed, cleanup the new zonepath. */
4297                 if (is_zfs) {
4298                         if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
4299                                 (void) fprintf(stderr, gettext("could not "
4300                                     "restore zonepath, the zfs mountpoint is "
4301                                     "set as:\n%s\n"), new_zonepath);
4302                                 /*
4303                                  * err is already != Z_OK since we're reverting
4304                                  */
4305                         } else {
4306                                 (void) zone_mount_rootfs(&mounts, zonepath);
4307                         }
4308                 } else if (fast) {
4309                         if (rename(new_zonepath, zonepath) != 0) {
4310                                 zperror(gettext("could not restore zonepath"),
4311                                     B_FALSE);
4312                                 /*
4313                                  * err is already != Z_OK since we're reverting
4314                                  */
4315                         } else {
4316                                 (void) zone_mount_rootfs(&mounts, zonepath);
4317                         }
4318                 } else {
4319                         (void) printf(gettext("Cleaning up zonepath %s..."),
4320                             new_zonepath);
4321                         (void) fflush(stdout);
4322                         err = cleanup_zonepath(new_zonepath, B_TRUE);
4323                         (void) printf("\n");
4324 
4325                         if (err != Z_OK) {
4326                                 errno = err;
4327                                 zperror(gettext("could not remove new "
4328                                     "zonepath"), B_TRUE);
4329                         } else {
4330                                 /*
4331                                  * Because we're reverting we know the mainline
4332                                  * code failed but we just reused the err
4333                                  * variable so we reset it back to Z_ERR.
4334                                  */
4335                                 err = Z_ERR;
4336                         }
4337 
4338                         (void) zone_mount_rootfs(&mounts, zonepath);
4339                 }
4340         } else {
4341                 /* The move was successful, cleanup the old zonepath. */
4342                 if (!is_zfs && !fast) {
4343                         (void) printf(
4344                             gettext("Cleaning up zonepath %s..."), zonepath);
4345                         (void) fflush(stdout);
4346                         err = cleanup_zonepath(zonepath, B_TRUE);
4347                         (void) printf("\n");
4348 
4349                         if (err != Z_OK) {
4350                                 errno = err;
4351                                 zperror(gettext("could not remove zonepath"),
4352                                     B_TRUE);
4353                         }
4354                 }
4355         }
4356 
4357         zone_mounts_destroy(&mounts);
4358         return ((err == Z_OK) ? Z_OK : Z_ERR);
4359 
4360 err_and_rele_lockfile:
4361         zonecfg_release_lock_file(target_zone, lockfd);
4362 err_and_fini_handle:
4363         zonecfg_fini_handle(handle);
4364 err_and_mounts_destroy:
4365         zone_mounts_destroy(&mounts);
4366         return (Z_ERR);
4367 }
4368 
4369 /* ARGSUSED */
4370 static int
4371 detach_func(int argc, char *argv[])
4372 {
4373         int lockfd = -1;
4374         int err, arg;
4375         char zonepath[MAXPATHLEN];
4376         char cmdbuf[MAXPATHLEN];
4377         char precmdbuf[MAXPATHLEN];
4378         boolean_t execute = B_TRUE;
4379         boolean_t brand_help = B_FALSE;
4380         brand_handle_t bh = NULL;
4381         int status;
4382 
4383         if (zonecfg_in_alt_root()) {
4384                 zerror(gettext("cannot detach zone in alternate root"));
4385                 return (Z_ERR);
4386         }
4387 
4388         /* Check the argv string for args we handle internally */
4389         optind = 0;
4390         opterr = 0;
4391         while ((arg = getopt(argc, argv, "?n")) != EOF) {
4392                 switch (arg) {
4393                 case '?':
4394                         if (optopt == '?') {
4395                                 sub_usage(SHELP_DETACH, CMD_DETACH);
4396                                 brand_help = B_TRUE;
4397                         }
4398                         /* Ignore unknown options - may be brand specific. */
4399                         break;
4400                 case 'n':
4401                         execute = B_FALSE;
4402                         break;
4403                 default:
4404                         /* Ignore unknown options - may be brand specific. */
4405                         break;
4406                 }
4407         }
4408 
4409         if (brand_help)
4410                 execute = B_FALSE;
4411 
4412         if (execute) {
4413                 if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE,
4414                     B_FALSE) != Z_OK)
4415                         return (Z_ERR);
4416                 if (verify_details(CMD_DETACH, argv) != Z_OK)
4417                         return (Z_ERR);
4418         } else {
4419                 /*
4420                  * We want a dry-run to work for a non-privileged user so we
4421                  * only do minimal validation.
4422                  */
4423                 if (target_zone == NULL) {
4424                         zerror(gettext("no zone specified"));
4425                         return (Z_ERR);
4426                 }
4427 
4428                 if (strcmp(target_zone, GLOBAL_ZONENAME) == 0) {
4429                         zerror(gettext("%s operation is invalid for the "
4430                             "global zone."), cmd_to_str(CMD_DETACH));
4431                         return (Z_ERR);
4432                 }
4433         }
4434 
4435         if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4436             != Z_OK) {
4437                 errno = err;
4438                 zperror2(target_zone, gettext("could not get zone path"));
4439                 return (Z_ERR);
4440         }
4441 
4442         /* Fetch the detach and predetach hooks from the brand configuration. */
4443         if ((bh = brand_open(target_brand)) == NULL) {
4444                 zerror(gettext("missing or invalid brand"));
4445                 return (Z_ERR);
4446         }
4447 
4448         if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_detach, target_zone,
4449             zonepath) != Z_OK) {
4450                 zerror("invalid brand configuration: missing detach resource");
4451                 brand_close(bh);
4452                 return (Z_ERR);
4453         }
4454 
4455         if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_predetach,
4456             target_zone, zonepath) != Z_OK) {
4457                 zerror("invalid brand configuration: missing predetach "
4458                     "resource");
4459                 brand_close(bh);
4460                 return (Z_ERR);
4461         }
4462         brand_close(bh);
4463 
4464         /* Append all options to predetach hook. */
4465         if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK)
4466                 return (Z_ERR);
4467 
4468         /* Append all options to detach hook. */
4469         if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
4470                 return (Z_ERR);
4471 
4472         if (execute && zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4473                 zerror(gettext("another %s may have an operation in progress."),
4474                     "zoneadm");
4475                 return (Z_ERR);
4476         }
4477 
4478         /* If we have a brand predetach hook, run it. */
4479         if (!brand_help && precmdbuf[0] != '\0') {
4480                 status = do_subproc(precmdbuf);
4481                 if (subproc_status(gettext("brand-specific predetach"),
4482                     status, B_FALSE) != ZONE_SUBPROC_OK) {
4483 
4484                         if (execute) {
4485                                 assert(lockfd >= 0);
4486                                 zonecfg_release_lock_file(target_zone, lockfd);
4487                                 lockfd = -1;
4488                         }
4489 
4490                         assert(lockfd == -1);
4491                         return (Z_ERR);
4492                 }
4493         }
4494 
4495         if (cmdbuf[0] != '\0') {
4496                 /* Run the detach hook */
4497                 status = do_subproc(cmdbuf);
4498                 if ((status = subproc_status(gettext("brand-specific detach"),
4499                     status, B_FALSE)) != ZONE_SUBPROC_OK) {
4500                         if (status == ZONE_SUBPROC_USAGE && !brand_help)
4501                                 sub_usage(SHELP_DETACH, CMD_DETACH);
4502 
4503                         if (execute) {
4504                                 assert(lockfd >= 0);
4505                                 zonecfg_release_lock_file(target_zone, lockfd);
4506                                 lockfd = -1;
4507                         }
4508 
4509                         assert(lockfd == -1);
4510                         return (Z_ERR);
4511                 }
4512 
4513         } else {
4514                 zone_dochandle_t handle;
4515 
4516                 /* If just help, we're done since there is no brand help. */
4517                 if (brand_help) {
4518                         assert(lockfd == -1);
4519                         return (Z_OK);
4520                 }
4521 
4522                 /*
4523                  * Run the built-in detach support.  Just generate a simple
4524                  * zone definition XML file and detach.
4525                  */
4526 
4527                 /* Don't detach the zone if anything is still mounted there */
4528                 if (execute && zonecfg_find_mounts(zonepath, NULL, NULL)) {
4529                         (void) fprintf(stderr, gettext("These file systems are "
4530                             "mounted on subdirectories of %s.\n"), zonepath);
4531                         (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
4532                         err = ZONE_SUBPROC_NOTCOMPLETE;
4533                         goto done;
4534                 }
4535 
4536                 if ((handle = zonecfg_init_handle()) == NULL) {
4537                         zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4538                         err = ZONE_SUBPROC_NOTCOMPLETE;
4539                         goto done;
4540                 }
4541 
4542                 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4543                         errno = err;
4544                         zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4545 
4546                 } else if ((err = zonecfg_detach_save(handle,
4547                     (execute ? 0 : ZONE_DRY_RUN))) != Z_OK) {
4548                         errno = err;
4549                         zperror(gettext("saving the detach manifest failed"),
4550                             B_TRUE);
4551                 }
4552 
4553                 zonecfg_fini_handle(handle);
4554                 if (err != Z_OK)
4555                         goto done;
4556         }
4557 
4558         /*
4559          * Set the zone state back to configured unless we are running with the
4560          * no-execute option.
4561          */
4562         if (execute && (err = zone_set_state(target_zone,
4563             ZONE_STATE_CONFIGURED)) != Z_OK) {
4564                 errno = err;
4565                 zperror(gettext("could not reset state"), B_TRUE);
4566         }
4567 
4568 done:
4569         if (execute) {
4570                 assert(lockfd >= 0);
4571                 zonecfg_release_lock_file(target_zone, lockfd);
4572                 lockfd = -1;
4573         }
4574 
4575         assert(lockfd == -1);
4576         return ((err == Z_OK) ? Z_OK : Z_ERR);
4577 }
4578 
4579 /*
4580  * Determine the brand when doing a dry-run attach.  The zone does not have to
4581  * exist, so we have to read the incoming manifest to determine the zone's
4582  * brand.
4583  *
4584  * Because the manifest has to be processed twice; once to determine the brand
4585  * and once to do the brand-specific attach logic, we always read it into a tmp
4586  * file.  This handles the manifest coming from stdin or a regular file.  The
4587  * tmpname parameter returns the name of the temporary file that the manifest
4588  * was read into.
4589  */
4590 static int
4591 dryrun_get_brand(char *manifest_path, char *tmpname, int size)
4592 {
4593         int fd;
4594         int err;
4595         int res = Z_OK;
4596         zone_dochandle_t local_handle;
4597         zone_dochandle_t rem_handle = NULL;
4598         int len;
4599         int ofd;
4600         char buf[512];
4601 
4602         if (strcmp(manifest_path, "-") == 0) {
4603                 fd = STDIN_FILENO;
4604         } else {
4605                 if ((fd = open(manifest_path, O_RDONLY)) < 0) {
4606                         if (getcwd(buf, sizeof (buf)) == NULL)
4607                                 (void) strlcpy(buf, "/", sizeof (buf));
4608                         zerror(gettext("could not open manifest path %s%s: %s"),
4609                             (*manifest_path == '/' ? "" : buf), manifest_path,
4610                             strerror(errno));
4611                         return (Z_ERR);
4612                 }
4613         }
4614 
4615         (void) snprintf(tmpname, size, "/var/run/zone.%d", getpid());
4616 
4617         if ((ofd = open(tmpname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
4618                 zperror(gettext("could not save manifest"), B_FALSE);
4619                 (void) close(fd);
4620                 return (Z_ERR);
4621         }
4622 
4623         while ((len = read(fd, buf, sizeof (buf))) > 0) {
4624                 if (write(ofd, buf, len) == -1) {
4625                         zperror(gettext("could not save manifest"), B_FALSE);
4626                         (void) close(ofd);
4627                         (void) close(fd);
4628                         return (Z_ERR);
4629                 }
4630         }
4631 
4632         if (close(ofd) != 0) {
4633                 zperror(gettext("could not save manifest"), B_FALSE);
4634                 (void) close(fd);
4635                 return (Z_ERR);
4636         }
4637 
4638         (void) close(fd);
4639 
4640         if ((fd = open(tmpname, O_RDONLY)) < 0) {
4641                 zperror(gettext("could not open manifest path"), B_FALSE);
4642                 return (Z_ERR);
4643         }
4644 
4645         if ((local_handle = zonecfg_init_handle()) == NULL) {
4646                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4647                 res = Z_ERR;
4648                 goto done;
4649         }
4650 
4651         if ((rem_handle = zonecfg_init_handle()) == NULL) {
4652                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4653                 res = Z_ERR;
4654                 goto done;
4655         }
4656 
4657         if ((err = zonecfg_attach_manifest(fd, local_handle, rem_handle))
4658             != Z_OK) {
4659                 res = Z_ERR;
4660 
4661                 if (err == Z_INVALID_DOCUMENT) {
4662                         struct stat st;
4663                         char buf[6];
4664 
4665                         if (strcmp(manifest_path, "-") == 0) {
4666                                 zerror(gettext("Input is not a valid XML "
4667                                     "file"));
4668                                 goto done;
4669                         }
4670 
4671                         if (fstat(fd, &st) == -1 || !S_ISREG(st.st_mode)) {
4672                                 zerror(gettext("%s is not an XML file"),
4673                                     manifest_path);
4674                                 goto done;
4675                         }
4676 
4677                         bzero(buf, sizeof (buf));
4678                         (void) lseek(fd, 0L, SEEK_SET);
4679                         if (read(fd, buf, sizeof (buf) - 1) < 0 ||
4680                             strncmp(buf, "<?xml", 5) != 0)
4681                                 zerror(gettext("%s is not an XML file"),
4682                                     manifest_path);
4683                         else
4684                                 zerror(gettext("Cannot attach to an earlier "
4685                                     "release of the operating system"));
4686                 } else {
4687                         zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4688                 }
4689                 goto done;
4690         }
4691 
4692         /* Retrieve remote handle brand type. */
4693         if (zonecfg_get_brand(rem_handle, target_brand, sizeof (target_brand))
4694             != Z_OK) {
4695                 zerror(gettext("missing or invalid brand"));
4696                 exit(Z_ERR);
4697         }
4698 
4699 done:
4700         zonecfg_fini_handle(local_handle);
4701         zonecfg_fini_handle(rem_handle);
4702         (void) close(fd);
4703 
4704         return ((res == Z_OK) ? Z_OK : Z_ERR);
4705 }
4706 
4707 /* ARGSUSED */
4708 static int
4709 attach_func(int argc, char *argv[])
4710 {
4711         int lockfd = -1;
4712         int err, arg;
4713         boolean_t force = B_FALSE;
4714         zone_dochandle_t handle;
4715         char zonepath[MAXPATHLEN];
4716         char cmdbuf[MAXPATHLEN];
4717         char postcmdbuf[MAXPATHLEN];
4718         boolean_t execute = B_TRUE;
4719         boolean_t brand_help = B_FALSE;
4720         char *manifest_path;
4721         char tmpmanifest[80];
4722         int manifest_pos;
4723         brand_handle_t bh = NULL;
4724         int status;
4725         int last_index = 0;
4726         int offset;
4727         char *up;
4728         boolean_t forced_update = B_FALSE;
4729 
4730         if (zonecfg_in_alt_root()) {
4731                 zerror(gettext("cannot attach zone in alternate root"));
4732                 return (Z_ERR);
4733         }
4734 
4735         /* Check the argv string for args we handle internally */
4736         optind = 0;
4737         opterr = 0;
4738         while ((arg = getopt(argc, argv, "?Fn:U")) != EOF) {
4739                 switch (arg) {
4740                 case '?':
4741                         if (optopt == '?') {
4742                                 sub_usage(SHELP_ATTACH, CMD_ATTACH);
4743                                 brand_help = B_TRUE;
4744                         }
4745                         /* Ignore unknown options - may be brand specific. */
4746                         break;
4747                 case 'F':
4748                         force = B_TRUE;
4749                         break;
4750                 case 'n':
4751                         execute = B_FALSE;
4752                         manifest_path = optarg;
4753                         manifest_pos = optind - 1;
4754                         break;
4755                 case 'U':
4756                         /*
4757                          * Undocumented 'force update' option for p2v update on
4758                          * attach when zone is in the incomplete state.  Change
4759                          * the option back to 'u' and set forced_update flag.
4760                          */
4761                         if (optind == last_index)
4762                                 offset = optind;
4763                         else
4764                                 offset = optind - 1;
4765                         if ((up = index(argv[offset], 'U')) != NULL)
4766                                 *up = 'u';
4767                         forced_update = B_TRUE;
4768                         break;
4769                 default:
4770                         /* Ignore unknown options - may be brand specific. */
4771                         break;
4772                 }
4773                 last_index = optind;
4774         }
4775 
4776         if (brand_help) {
4777                 force = B_FALSE;
4778                 execute = B_TRUE;
4779         }
4780 
4781         /* dry-run and force flags are mutually exclusive */
4782         if (!execute && force) {
4783                 zerror(gettext("-F and -n flags are mutually exclusive"));
4784                 return (Z_ERR);
4785         }
4786 
4787         /*
4788          * If the no-execute option was specified, we don't do validation and
4789          * need to figure out the brand, since there is no zone required to be
4790          * configured for this option.
4791          */
4792         if (execute) {
4793                 if (!brand_help) {
4794                         if (sanity_check(target_zone, CMD_ATTACH, B_FALSE,
4795                             B_TRUE, forced_update) != Z_OK)
4796                                 return (Z_ERR);
4797                         if (verify_details(CMD_ATTACH, argv) != Z_OK)
4798                                 return (Z_ERR);
4799                 }
4800 
4801                 if ((err = zone_get_zonepath(target_zone, zonepath,
4802                     sizeof (zonepath))) != Z_OK) {
4803                         errno = err;
4804                         zperror2(target_zone,
4805                             gettext("could not get zone path"));
4806                         return (Z_ERR);
4807                 }
4808         } else {
4809                 if (dryrun_get_brand(manifest_path, tmpmanifest,
4810                     sizeof (tmpmanifest)) != Z_OK)
4811                         return (Z_ERR);
4812 
4813                 argv[manifest_pos] = tmpmanifest;
4814                 target_zone = "-";
4815                 (void) strlcpy(zonepath, "-", sizeof (zonepath));
4816 
4817                 /* Run the brand's verify_adm hook. */
4818                 if (verify_brand(NULL, CMD_ATTACH, argv) != Z_OK)
4819                         return (Z_ERR);
4820         }
4821 
4822         /*
4823          * Fetch the attach and postattach hooks from the brand configuration.
4824          */
4825         if ((bh = brand_open(target_brand)) == NULL) {
4826                 zerror(gettext("missing or invalid brand"));
4827                 return (Z_ERR);
4828         }
4829 
4830         if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_attach, target_zone,
4831             zonepath) != Z_OK) {
4832                 zerror("invalid brand configuration: missing attach resource");
4833                 brand_close(bh);
4834                 return (Z_ERR);
4835         }
4836 
4837         if (get_hook(bh, postcmdbuf, sizeof (postcmdbuf), brand_get_postattach,
4838             target_zone, zonepath) != Z_OK) {
4839                 zerror("invalid brand configuration: missing postattach "
4840                     "resource");
4841                 brand_close(bh);
4842                 return (Z_ERR);
4843         }
4844         brand_close(bh);
4845 
4846         /* Append all options to attach hook. */
4847         if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
4848                 return (Z_ERR);
4849 
4850         /* Append all options to postattach hook. */
4851         if (addoptions(postcmdbuf, argv, sizeof (postcmdbuf)) != Z_OK)
4852                 return (Z_ERR);
4853 
4854         if (execute && !brand_help) {
4855                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
4856                         zerror(gettext("another %s may have an operation in "
4857                             "progress."), "zoneadm");
4858                         return (Z_ERR);
4859                 }
4860         }
4861 
4862         if (!force) {
4863                 /*
4864                  * Not a force-attach, so we need to actually do the work.
4865                  */
4866                 if (cmdbuf[0] != '\0') {
4867                         /* Run the attach hook */
4868                         status = do_subproc(cmdbuf);
4869                         if ((status = subproc_status(gettext("brand-specific "
4870                             "attach"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
4871                                 if (status == ZONE_SUBPROC_USAGE && !brand_help)
4872                                         sub_usage(SHELP_ATTACH, CMD_ATTACH);
4873 
4874                                 if (execute && !brand_help) {
4875                                         assert(zonecfg_lock_file_held(&lockfd));
4876                                         zonecfg_release_lock_file(target_zone,
4877                                             lockfd);
4878                                         lockfd = -1;
4879                                 }
4880 
4881                                 assert(lockfd == -1);
4882                                 return (Z_ERR);
4883                         }
4884                 }
4885 
4886                 /*
4887                  * Else run the built-in attach support.
4888                  * This is a no-op since there is nothing to validate.
4889                  */
4890 
4891                 /* If dry-run or help, then we're done. */
4892                 if (!execute || brand_help) {
4893                         if (!execute)
4894                                 (void) unlink(tmpmanifest);
4895                         assert(lockfd == -1);
4896                         return (Z_OK);
4897                 }
4898         }
4899 
4900         /* Now we can validate that the zonepath exists. */
4901         if (validate_zonepath(zonepath, CMD_ATTACH) != Z_OK) {
4902                 (void) fprintf(stderr, gettext("could not verify zonepath %s "
4903                     "because of the above errors.\n"), zonepath);
4904 
4905                 assert(zonecfg_lock_file_held(&lockfd));
4906                 zonecfg_release_lock_file(target_zone, lockfd);
4907                 return (Z_ERR);
4908         }
4909 
4910         if ((handle = zonecfg_init_handle()) == NULL) {
4911                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4912                 err = Z_ERR;
4913         } else if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4914                 errno = err;
4915                 zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4916                 zonecfg_fini_handle(handle);
4917         } else {
4918                 zonecfg_rm_detached(handle, force);
4919                 zonecfg_fini_handle(handle);
4920         }
4921 
4922         if (err == Z_OK &&
4923             (err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4924                 errno = err;
4925                 zperror(gettext("could not reset state"), B_TRUE);
4926         }
4927 
4928         assert(zonecfg_lock_file_held(&lockfd));
4929         zonecfg_release_lock_file(target_zone, lockfd);
4930         lockfd = -1;
4931 
4932         /* If we have a brand postattach hook, run it. */
4933         if (err == Z_OK && !force && postcmdbuf[0] != '\0') {
4934                 status = do_subproc(postcmdbuf);
4935                 if (subproc_status(gettext("brand-specific postattach"),
4936                     status, B_FALSE) != ZONE_SUBPROC_OK) {
4937                         if ((err = zone_set_state(target_zone,
4938                             ZONE_STATE_CONFIGURED)) != Z_OK) {
4939                                 errno = err;
4940                                 zperror(gettext("could not reset state"),
4941                                     B_TRUE);
4942                         }
4943                 }
4944         }
4945 
4946         assert(lockfd == -1);
4947         return ((err == Z_OK) ? Z_OK : Z_ERR);
4948 }
4949 
4950 /*
4951  * On input, TRUE => yes, FALSE => no.
4952  * On return, TRUE => 1, FALSE => 0, could not ask => -1.
4953  */
4954 
4955 static int
4956 ask_yesno(boolean_t default_answer, const char *question)
4957 {
4958         char line[64];  /* should be large enough to answer yes or no */
4959 
4960         if (!isatty(STDIN_FILENO))
4961                 return (-1);
4962         for (;;) {
4963                 (void) printf("%s (%s)? ", question,
4964                     default_answer ? "[y]/n" : "y/[n]");
4965                 if (fgets(line, sizeof (line), stdin) == NULL ||
4966                     line[0] == '\n')
4967                         return (default_answer ? 1 : 0);
4968                 if (tolower(line[0]) == 'y')
4969                         return (1);
4970                 if (tolower(line[0]) == 'n')
4971                         return (0);
4972         }
4973 }
4974 
4975 /* ARGSUSED */
4976 static int
4977 uninstall_func(int argc, char *argv[])
4978 {
4979         char line[ZONENAME_MAX + 128];  /* Enough for "Are you sure ..." */
4980         char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
4981         char cmdbuf[MAXPATHLEN];
4982         char precmdbuf[MAXPATHLEN];
4983         boolean_t force = B_FALSE;
4984         int lockfd, answer;
4985         int err, arg;
4986         boolean_t brand_help = B_FALSE;
4987         brand_handle_t bh = NULL;
4988         int status;
4989 
4990         if (zonecfg_in_alt_root()) {
4991                 zerror(gettext("cannot uninstall zone in alternate root"));
4992                 return (Z_ERR);
4993         }
4994 
4995         /* Check the argv string for args we handle internally */
4996         optind = 0;
4997         opterr = 0;
4998         while ((arg = getopt(argc, argv, "?F")) != EOF) {
4999                 switch (arg) {
5000                 case '?':
5001                         if (optopt == '?') {
5002                                 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
5003                                 brand_help = B_TRUE;
5004                         }
5005                         /* Ignore unknown options - may be brand specific. */
5006                         break;
5007                 case 'F':
5008                         force = B_TRUE;
5009                         break;
5010                 default:
5011                         /* Ignore unknown options - may be brand specific. */
5012                         break;
5013                 }
5014         }
5015 
5016         if (!brand_help) {
5017                 if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE,
5018                     B_FALSE) != Z_OK)
5019                         return (Z_ERR);
5020 
5021                 /*
5022                  * Invoke brand-specific handler.
5023                  */
5024                 if (invoke_brand_handler(CMD_UNINSTALL, argv) != Z_OK)
5025                         return (Z_ERR);
5026 
5027                 if (!force) {
5028                         (void) snprintf(line, sizeof (line),
5029                             gettext("Are you sure you want to %s zone %s"),
5030                             cmd_to_str(CMD_UNINSTALL), target_zone);
5031                         if ((answer = ask_yesno(B_FALSE, line)) == 0) {
5032                                 return (Z_OK);
5033                         } else if (answer == -1) {
5034                                 zerror(gettext("Input not from terminal and -F "
5035                                     "not specified: %s not done."),
5036                                     cmd_to_str(CMD_UNINSTALL));
5037                                 return (Z_ERR);
5038                         }
5039                 }
5040         }
5041 
5042         if ((err = zone_get_zonepath(target_zone, zonepath,
5043             sizeof (zonepath))) != Z_OK) {
5044                 errno = err;
5045                 zperror2(target_zone, gettext("could not get zone path"));
5046                 return (Z_ERR);
5047         }
5048 
5049         /*
5050          * Fetch the uninstall and preuninstall hooks from the brand
5051          * configuration.
5052          */
5053         if ((bh = brand_open(target_brand)) == NULL) {
5054                 zerror(gettext("missing or invalid brand"));
5055                 return (Z_ERR);
5056         }
5057 
5058         if (get_hook(bh, cmdbuf, sizeof (cmdbuf), brand_get_uninstall,
5059             target_zone, zonepath) != Z_OK) {
5060                 zerror("invalid brand configuration: missing uninstall "
5061                     "resource");
5062                 brand_close(bh);
5063                 return (Z_ERR);
5064         }
5065 
5066         if (get_hook(bh, precmdbuf, sizeof (precmdbuf), brand_get_preuninstall,
5067             target_zone, zonepath) != Z_OK) {
5068                 zerror("invalid brand configuration: missing preuninstall "
5069                     "resource");
5070                 brand_close(bh);
5071                 return (Z_ERR);
5072         }
5073         brand_close(bh);
5074 
5075         /* Append all options to preuninstall hook. */
5076         if (addoptions(precmdbuf, argv, sizeof (precmdbuf)) != Z_OK)
5077                 return (Z_ERR);
5078 
5079         /* Append all options to uninstall hook. */
5080         if (addoptions(cmdbuf, argv, sizeof (cmdbuf)) != Z_OK)
5081                 return (Z_ERR);
5082 
5083         if (!brand_help) {
5084                 if ((err = zone_get_rootpath(target_zone, rootpath,
5085                     sizeof (rootpath))) != Z_OK) {
5086                         errno = err;
5087                         zperror2(target_zone, gettext("could not get root "
5088                             "path"));
5089                         return (Z_ERR);
5090                 }
5091 
5092                 /*
5093                  * If there seems to be a zoneadmd running for this zone, call
5094                  * it to tell it that an uninstall is happening; if all goes
5095                  * well it will then shut itself down.
5096                  */
5097                 if (zonecfg_ping_zoneadmd(target_zone) == Z_OK) {
5098                         zone_cmd_arg_t zarg;
5099                         zarg.cmd = Z_NOTE_UNINSTALLING;
5100                         /* we don't care too much if this fails, just plow on */
5101                         (void) zonecfg_call_zoneadmd(target_zone, &zarg, locale,
5102                             B_TRUE);
5103                 }
5104 
5105                 if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5106                         zerror(gettext("another %s may have an operation in "
5107                             "progress."), "zoneadm");
5108                         return (Z_ERR);
5109                 }
5110 
5111                 /* Don't uninstall the zone if anything is mounted there */
5112                 err = zonecfg_find_mounts(rootpath, NULL, NULL);
5113                 if (err) {
5114                         zerror(gettext("These file systems are mounted on "
5115                             "subdirectories of %s.\n"), rootpath);
5116                         (void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
5117                         zonecfg_release_lock_file(target_zone, lockfd);
5118                         return (Z_ERR);
5119                 }
5120         }
5121 
5122         /* If we have a brand preuninstall hook, run it. */
5123         if (!brand_help && precmdbuf[0] != '\0') {
5124                 status = do_subproc(precmdbuf);
5125                 if (subproc_status(gettext("brand-specific preuninstall"),
5126                     status, B_FALSE) != ZONE_SUBPROC_OK) {
5127                         zonecfg_release_lock_file(target_zone, lockfd);
5128                         return (Z_ERR);
5129                 }
5130         }
5131 
5132         if (!brand_help) {
5133                 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
5134                 if (err != Z_OK) {
5135                         errno = err;
5136                         zperror2(target_zone, gettext("could not set state"));
5137                         goto bad;
5138                 }
5139         }
5140 
5141         /*
5142          * If there is a brand uninstall hook, use it, otherwise use the
5143          * built-in uninstall code.
5144          */
5145         if (cmdbuf[0] != '\0') {
5146                 /* Run the uninstall hook */
5147                 status = do_subproc(cmdbuf);
5148                 if ((status = subproc_status(gettext("brand-specific "
5149                     "uninstall"), status, B_FALSE)) != ZONE_SUBPROC_OK) {
5150                         if (status == ZONE_SUBPROC_USAGE && !brand_help)
5151                                 sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
5152                         if (!brand_help)
5153                                 zonecfg_release_lock_file(target_zone, lockfd);
5154                         return (Z_ERR);
5155                 }
5156 
5157                 if (brand_help)
5158                         return (Z_OK);
5159         } else {
5160                 /* If just help, we're done since there is no brand help. */
5161                 if (brand_help)
5162                         return (Z_OK);
5163 
5164                 /* Run the built-in uninstall support. */
5165                 if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
5166                         errno = err;
5167                         zperror2(target_zone, gettext("cleaning up zonepath "
5168                             "failed"));
5169                         goto bad;
5170                 }
5171         }
5172 
5173         err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
5174         if (err != Z_OK) {
5175                 errno = err;
5176                 zperror2(target_zone, gettext("could not reset state"));
5177         }
5178 bad:
5179         zonecfg_release_lock_file(target_zone, lockfd);
5180         return (err);
5181 }
5182 
5183 /* ARGSUSED */
5184 static int
5185 mount_func(int argc, char *argv[])
5186 {
5187         zone_cmd_arg_t zarg;
5188         boolean_t force = B_FALSE;
5189         int arg;
5190 
5191         /*
5192          * The only supported subargument to the "mount" subcommand is
5193          * "-f", which forces us to mount a zone in the INCOMPLETE state.
5194          */
5195         optind = 0;
5196         if ((arg = getopt(argc, argv, "f")) != EOF) {
5197                 switch (arg) {
5198                 case 'f':
5199                         force = B_TRUE;
5200                         break;
5201                 default:
5202                         return (Z_USAGE);
5203                 }
5204         }
5205         if (argc > optind)
5206                 return (Z_USAGE);
5207 
5208         if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
5209             != Z_OK)
5210                 return (Z_ERR);
5211         if (verify_details(CMD_MOUNT, argv) != Z_OK)
5212                 return (Z_ERR);
5213 
5214         zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
5215         zarg.bootbuf[0] = '\0';
5216         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5217                 zerror(gettext("call to %s failed"), "zoneadmd");
5218                 return (Z_ERR);
5219         }
5220         return (Z_OK);
5221 }
5222 
5223 /* ARGSUSED */
5224 static int
5225 unmount_func(int argc, char *argv[])
5226 {
5227         zone_cmd_arg_t zarg;
5228 
5229         if (argc > 0)
5230                 return (Z_USAGE);
5231         if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5232             != Z_OK)
5233                 return (Z_ERR);
5234 
5235         zarg.cmd = Z_UNMOUNT;
5236         if (zonecfg_call_zoneadmd(target_zone, &zarg, locale, B_TRUE) != 0) {
5237                 zerror(gettext("call to %s failed"), "zoneadmd");
5238                 return (Z_ERR);
5239         }
5240         return (Z_OK);
5241 }
5242 
5243 static int
5244 mark_func(int argc, char *argv[])
5245 {
5246         int err, lockfd;
5247         int arg;
5248         boolean_t force = B_FALSE;
5249         int state;
5250 
5251         optind = 0;
5252         opterr = 0;
5253         while ((arg = getopt(argc, argv, "F")) != EOF) {
5254                 switch (arg) {
5255                 case 'F':
5256                         force = B_TRUE;
5257                         break;
5258                 default:
5259                         return (Z_USAGE);
5260                 }
5261         }
5262 
5263         if (argc != (optind + 1))
5264                 return (Z_USAGE);
5265 
5266         if (strcmp(argv[optind], "configured") == 0)
5267                 state = ZONE_STATE_CONFIGURED;
5268         else if (strcmp(argv[optind], "incomplete") == 0)
5269                 state = ZONE_STATE_INCOMPLETE;
5270         else if (strcmp(argv[optind], "installed") == 0)
5271                 state = ZONE_STATE_INSTALLED;
5272         else
5273                 return (Z_USAGE);
5274 
5275         if (state != ZONE_STATE_INCOMPLETE && !force)
5276                 return (Z_USAGE);
5277 
5278         if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_TRUE, B_FALSE)
5279             != Z_OK)
5280                 return (Z_ERR);
5281 
5282         /*
5283          * Invoke brand-specific handler.
5284          */
5285         if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5286                 return (Z_ERR);
5287 
5288         if (zonecfg_grab_lock_file(target_zone, &lockfd) != Z_OK) {
5289                 zerror(gettext("another %s may have an operation in progress."),
5290                     "zoneadm");
5291                 return (Z_ERR);
5292         }
5293 
5294         err = zone_set_state(target_zone, state);
5295         if (err != Z_OK) {
5296                 errno = err;
5297                 zperror2(target_zone, gettext("could not set state"));
5298         }
5299         zonecfg_release_lock_file(target_zone, lockfd);
5300 
5301         return (err);
5302 }
5303 
5304 /*
5305  * Check what scheduling class we're running under and print a warning if
5306  * we're not using FSS.
5307  */
5308 static int
5309 check_sched_fss(zone_dochandle_t handle)
5310 {
5311         char class_name[PC_CLNMSZ];
5312 
5313         if (zonecfg_get_dflt_sched_class(handle, class_name,
5314             sizeof (class_name)) != Z_OK) {
5315                 zerror(gettext("WARNING: unable to determine the zone's "
5316                     "scheduling class"));
5317         } else if (strcmp("FSS", class_name) != 0) {
5318                 zerror(gettext("WARNING: The zone.cpu-shares rctl is set but\n"
5319                     "FSS is not the default scheduling class for this zone.  "
5320                     "FSS will be\nused for processes in the zone but to get "
5321                     "the full benefit of FSS,\nit should be the default "
5322                     "scheduling class.  See dispadmin(1M) for\nmore details."));
5323                 return (Z_SYSTEM);
5324         }
5325 
5326         return (Z_OK);
5327 }
5328 
5329 static int
5330 check_cpu_shares_sched(zone_dochandle_t handle)
5331 {
5332         int err;
5333         int res = Z_OK;
5334         struct zone_rctltab rctl;
5335 
5336         if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
5337                 errno = err;
5338                 zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5339                 return (err);
5340         }
5341 
5342         while (zonecfg_getrctlent(handle, &rctl) == Z_OK) {
5343                 if (strcmp(rctl.zone_rctl_name, "zone.cpu-shares") == 0) {
5344                         if (check_sched_fss(handle) != Z_OK)
5345                                 res = Z_SYSTEM;
5346                         break;
5347                 }
5348         }
5349 
5350         (void) zonecfg_endrctlent(handle);
5351 
5352         return (res);
5353 }
5354 
5355 /*
5356  * Check if there is a mix of processes running in different pools within the
5357  * zone.  This is currently only going to be called for the global zone from
5358  * apply_func but that could be generalized in the future.
5359  */
5360 static boolean_t
5361 mixed_pools(zoneid_t zoneid)
5362 {
5363         DIR *dirp;
5364         dirent_t *dent;
5365         boolean_t mixed = B_FALSE;
5366         boolean_t poolid_set = B_FALSE;
5367         poolid_t last_poolid = 0;
5368 
5369         if ((dirp = opendir("/proc")) == NULL) {
5370                 zerror(gettext("could not open /proc"));
5371                 return (B_FALSE);
5372         }
5373 
5374         while ((dent = readdir(dirp)) != NULL) {
5375                 int procfd;
5376                 psinfo_t ps;
5377                 char procpath[MAXPATHLEN];
5378 
5379                 if (dent->d_name[0] == '.')
5380                         continue;
5381 
5382                 (void) snprintf(procpath, sizeof (procpath), "/proc/%s/psinfo",
5383                     dent->d_name);
5384 
5385                 if ((procfd = open(procpath, O_RDONLY)) == -1)
5386                         continue;
5387 
5388                 if (read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) {
5389                         /* skip processes in other zones and system processes */
5390                         if (zoneid != ps.pr_zoneid || ps.pr_flag & SSYS) {
5391                                 (void) close(procfd);
5392                                 continue;
5393                         }
5394 
5395                         if (poolid_set) {
5396                                 if (ps.pr_poolid != last_poolid)
5397                                         mixed = B_TRUE;
5398                         } else {
5399                                 last_poolid = ps.pr_poolid;
5400                                 poolid_set = B_TRUE;
5401                         }
5402                 }
5403 
5404                 (void) close(procfd);
5405 
5406                 if (mixed)
5407                         break;
5408         }
5409 
5410         (void) closedir(dirp);
5411 
5412         return (mixed);
5413 }
5414 
5415 /*
5416  * Check if a persistent or temporary pool is configured for the zone.
5417  * This is currently only going to be called for the global zone from
5418  * apply_func but that could be generalized in the future.
5419  */
5420 static boolean_t
5421 pool_configured(zone_dochandle_t handle)
5422 {
5423         int err1, err2;
5424         struct zone_psettab pset_tab;
5425         char poolname[MAXPATHLEN];
5426 
5427         err1 = zonecfg_lookup_pset(handle, &pset_tab);
5428         err2 = zonecfg_get_pool(handle, poolname, sizeof (poolname));
5429 
5430         if (err1 == Z_NO_ENTRY &&
5431             (err2 == Z_NO_ENTRY || (err2 == Z_OK && strlen(poolname) == 0)))
5432                 return (B_FALSE);
5433 
5434         return (B_TRUE);
5435 }
5436 
5437 /*
5438  * This is an undocumented interface which is currently only used to apply
5439  * the global zone resource management settings when the system boots.
5440  * This function does not yet properly handle updating a running system so
5441  * any projects running in the zone would be trashed if this function
5442  * were to run after the zone had booted.  It also does not reset any
5443  * rctl settings that were removed from zonecfg.  There is still work to be
5444  * done before we can properly support dynamically updating the resource
5445  * management settings for a running zone (global or non-global).  Thus, this
5446  * functionality is undocumented for now.
5447  */
5448 /* ARGSUSED */
5449 static int
5450 apply_func(int argc, char *argv[])
5451 {
5452         int err;
5453         int res = Z_OK;
5454         priv_set_t *privset;
5455         zoneid_t zoneid;
5456         zone_dochandle_t handle;
5457         struct zone_mcaptab mcap;
5458         char pool_err[128];
5459 
5460         zoneid = getzoneid();
5461 
5462         if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
5463             target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
5464                 return (usage(B_FALSE));
5465 
5466         if ((privset = priv_allocset()) == NULL) {
5467                 zerror(gettext("%s failed"), "priv_allocset");
5468                 return (Z_ERR);
5469         }
5470 
5471         if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5472                 zerror(gettext("%s failed"), "getppriv");
5473                 priv_freeset(privset);
5474                 return (Z_ERR);
5475         }
5476 
5477         if (priv_isfullset(privset) == B_FALSE) {
5478                 (void) usage(B_FALSE);
5479                 priv_freeset(privset);
5480                 return (Z_ERR);
5481         }
5482         priv_freeset(privset);
5483 
5484         if ((handle = zonecfg_init_handle()) == NULL) {
5485                 zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5486                 return (Z_ERR);
5487         }
5488 
5489         if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
5490                 errno = err;
5491                 zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5492                 zonecfg_fini_handle(handle);
5493                 return (Z_ERR);
5494         }
5495 
5496         /* specific error msgs are printed within apply_rctls */
5497         if ((err = zonecfg_apply_rctls(target_zone, handle)) != Z_OK) {
5498                 errno = err;
5499                 zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5500                 res = Z_ERR;
5501         }
5502 
5503         if ((err = check_cpu_shares_sched(handle)) != Z_OK)
5504                 res = Z_ERR;
5505 
5506         if (pool_configured(handle)) {
5507                 if (mixed_pools(zoneid)) {
5508                         zerror(gettext("Zone is using multiple resource "
5509                             "pools.  The pool\nconfiguration cannot be "
5510                             "applied without rebooting."));
5511                         res = Z_ERR;
5512                 } else {
5513 
5514                         /*
5515                          * The next two blocks of code attempt to set up
5516                          * temporary pools as well as persistent pools.  In
5517                          * both cases we call the functions unconditionally.
5518                          * Within each funtion the code will check if the zone
5519                          * is actually configured for a temporary pool or
5520                          * persistent pool and just return if there is nothing
5521                          * to do.
5522                          */
5523                         if ((err = zonecfg_bind_tmp_pool(handle, zoneid,
5524                             pool_err, sizeof (pool_err))) != Z_OK) {
5525                                 if (err == Z_POOL || err == Z_POOL_CREATE ||
5526                                     err == Z_POOL_BIND)
5527                                         zerror("%s: %s", zonecfg_strerror(err),
5528                                             pool_err);
5529                                 else
5530                                         zerror(gettext("could not bind zone to "
5531                                             "temporary pool: %s"),
5532                                             zonecfg_strerror(err));
5533                                 res = Z_ERR;
5534                         }
5535 
5536                         if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
5537                             sizeof (pool_err))) != Z_OK) {
5538                                 if (err == Z_POOL || err == Z_POOL_BIND)
5539                                         zerror("%s: %s", zonecfg_strerror(err),
5540                                             pool_err);
5541                                 else
5542                                         zerror("%s", zonecfg_strerror(err));
5543                         }
5544                 }
5545         }
5546 
5547         /*
5548          * If a memory cap is configured, set the cap in the kernel using
5549          * zone_setattr() and make sure the rcapd SMF service is enabled.
5550          */
5551         if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
5552                 uint64_t num;
5553                 char smf_err[128];
5554 
5555                 num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
5556                 if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
5557                         zerror(gettext("could not set zone memory cap"));
5558                         res = Z_ERR;
5559                 }
5560 
5561                 if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
5562                         zerror(gettext("enabling system/rcap service failed: "
5563                             "%s"), smf_err);
5564                         res = Z_ERR;
5565                 }
5566         }
5567 
5568         zonecfg_fini_handle(handle);
5569 
5570         return (res);
5571 }
5572 
5573 /*
5574  * This is an undocumented interface that is invoked by the zones SMF service
5575  * for installed zones that won't automatically boot.
5576  */
5577 /* ARGSUSED */
5578 static int
5579 sysboot_func(int argc, char *argv[])
5580 {
5581         int err;
5582         zone_dochandle_t zone_handle;
5583         brand_handle_t brand_handle;
5584         char cmdbuf[MAXPATHLEN];
5585         char zonepath[MAXPATHLEN];
5586 
5587         /*
5588          * This subcommand can only be executed in the global zone on non-global
5589          * zones.
5590          */
5591         if (zonecfg_in_alt_root())
5592                 return (usage(B_FALSE));
5593         if (sanity_check(target_zone, CMD_SYSBOOT, B_FALSE, B_TRUE, B_FALSE) !=
5594             Z_OK)
5595                 return (Z_ERR);
5596 
5597         /*
5598          * Fetch the sysboot hook from the target zone's brand.
5599          */
5600         if ((zone_handle = zonecfg_init_handle()) == NULL) {
5601                 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
5602                 return (Z_ERR);
5603         }
5604         if ((err = zonecfg_get_handle(target_zone, zone_handle)) != Z_OK) {
5605                 errno = err;
5606                 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
5607                 zonecfg_fini_handle(zone_handle);
5608                 return (Z_ERR);
5609         }
5610         if ((err = zonecfg_get_zonepath(zone_handle, zonepath,
5611             sizeof (zonepath))) != Z_OK) {
5612                 errno = err;
5613                 zperror(cmd_to_str(CMD_SYSBOOT), B_TRUE);
5614                 zonecfg_fini_handle(zone_handle);
5615                 return (Z_ERR);
5616         }
5617         if ((brand_handle = brand_open(target_brand)) == NULL) {
5618                 zerror(gettext("missing or invalid brand during %s operation: "
5619                     "%s"), cmd_to_str(CMD_SYSBOOT), target_brand);
5620                 zonecfg_fini_handle(zone_handle);
5621                 return (Z_ERR);
5622         }
5623         err = get_hook(brand_handle, cmdbuf, sizeof (cmdbuf), brand_get_sysboot,
5624             target_zone, zonepath);
5625         brand_close(brand_handle);
5626         zonecfg_fini_handle(zone_handle);
5627         if (err != Z_OK) {
5628                 zerror(gettext("unable to get brand hook from brand %s for %s "
5629                     "operation"), target_brand, cmd_to_str(CMD_SYSBOOT));
5630                 return (Z_ERR);
5631         }
5632 
5633         /*
5634          * If the hook wasn't defined (which is OK), then indicate success and
5635          * return.  Otherwise, execute the hook.
5636          */
5637         if (cmdbuf[0] != '\0')
5638                 return ((subproc_status(gettext("brand sysboot operation"),
5639                     do_subproc(cmdbuf), B_FALSE) == ZONE_SUBPROC_OK) ? Z_OK :
5640                     Z_BRAND_ERROR);
5641         return (Z_OK);
5642 }
5643 
5644 static int
5645 help_func(int argc, char *argv[])
5646 {
5647         int arg, cmd_num;
5648 
5649         if (argc == 0) {
5650                 (void) usage(B_TRUE);
5651                 return (Z_OK);
5652         }
5653         optind = 0;
5654         if ((arg = getopt(argc, argv, "?")) != EOF) {
5655                 switch (arg) {
5656                 case '?':
5657                         sub_usage(SHELP_HELP, CMD_HELP);
5658                         return (optopt == '?' ? Z_OK : Z_USAGE);
5659                 default:
5660                         sub_usage(SHELP_HELP, CMD_HELP);
5661                         return (Z_USAGE);
5662                 }
5663         }
5664         while (optind < argc) {
5665                 /* Private commands have NULL short_usage; omit them */
5666                 if ((cmd_num = cmd_match(argv[optind])) < 0 ||
5667                     cmdtab[cmd_num].short_usage == NULL) {
5668                         sub_usage(SHELP_HELP, CMD_HELP);
5669                         return (Z_USAGE);
5670                 }
5671                 sub_usage(cmdtab[cmd_num].short_usage, cmd_num);
5672                 optind++;
5673         }
5674         return (Z_OK);
5675 }
5676 
5677 /*
5678  * Returns: CMD_MIN thru CMD_MAX on success, -1 on error
5679  */
5680 
5681 static int
5682 cmd_match(char *cmd)
5683 {
5684         int i;
5685 
5686         for (i = CMD_MIN; i <= CMD_MAX; i++) {
5687                 /* return only if there is an exact match */
5688                 if (strcmp(cmd, cmdtab[i].cmd_name) == 0)
5689                         return (cmdtab[i].cmd_num);
5690         }
5691         return (-1);
5692 }
5693 
5694 static int
5695 parse_and_run(int argc, char *argv[])
5696 {
5697         int i = cmd_match(argv[0]);
5698 
5699         if (i < 0)
5700                 return (usage(B_FALSE));
5701         return (cmdtab[i].handler(argc - 1, &(argv[1])));
5702 }
5703 
5704 static char *
5705 get_execbasename(char *execfullname)
5706 {
5707         char *last_slash, *execbasename;
5708 
5709         /* guard against '/' at end of command invocation */
5710         for (;;) {
5711                 last_slash = strrchr(execfullname, '/');
5712                 if (last_slash == NULL) {
5713                         execbasename = execfullname;
5714                         break;
5715                 } else {
5716                         execbasename = last_slash + 1;
5717                         if (*execbasename == '\0') {
5718                                 *last_slash = '\0';
5719                                 continue;
5720                         }
5721                         break;
5722                 }
5723         }
5724         return (execbasename);
5725 }
5726 
5727 static char *
5728 get_username()
5729 {
5730         uid_t uid;
5731         struct passwd *nptr;
5732 
5733 
5734         /*
5735          * Authorizations are checked to restrict access based on the
5736          * requested operation and zone name, It is assumed that the
5737          * program is running with all privileges, but that the real
5738          * user ID is that of the user or role on whose behalf we are
5739          * operating. So we start by getting the username that will be
5740          * used for subsequent authorization checks.
5741          */
5742 
5743         uid = getuid();
5744         if ((nptr = getpwuid(uid)) == NULL) {
5745                 zerror(gettext("could not get user name."));
5746                 exit(Z_ERR);
5747         }
5748         return (nptr->pw_name);
5749 }
5750 
5751 int
5752 main(int argc, char **argv)
5753 {
5754         int arg;
5755         zoneid_t zid;
5756         struct stat st;
5757         char *zone_lock_env;
5758         int err;
5759 
5760         if ((locale = setlocale(LC_ALL, "")) == NULL)
5761                 locale = "C";
5762         (void) textdomain(TEXT_DOMAIN);
5763         setbuf(stdout, NULL);
5764         (void) sigset(SIGHUP, SIG_IGN);
5765         execname = get_execbasename(argv[0]);
5766         username = get_username();
5767         target_zone = NULL;
5768         if (chdir("/") != 0) {
5769                 zerror(gettext("could not change directory to /."));
5770                 exit(Z_ERR);
5771         }
5772 
5773         /*
5774          * Use the default system mask rather than anything that may have been
5775          * set by the caller.
5776          */
5777         (void) umask(CMASK);
5778 
5779         if (init_zfs() != Z_OK)
5780                 exit(Z_ERR);
5781 
5782         while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) {
5783                 switch (arg) {
5784                 case '?':
5785                         return (usage(B_TRUE));
5786                 case 'u':
5787                         target_uuid = optarg;
5788                         break;
5789                 case 'z':
5790                         target_zone = optarg;
5791                         break;
5792                 case 'R':       /* private option for admin/install use */
5793                         if (*optarg != '/') {
5794                                 zerror(gettext("root path must be absolute."));
5795                                 exit(Z_ERR);
5796                         }
5797                         if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
5798                                 zerror(
5799                                     gettext("root path must be a directory."));
5800                                 exit(Z_ERR);
5801                         }
5802                         zonecfg_set_root(optarg);
5803                         break;
5804                 default:
5805                         return (usage(B_FALSE));
5806                 }
5807         }
5808 
5809         if (optind >= argc)
5810                 return (usage(B_FALSE));
5811 
5812         if (target_uuid != NULL && *target_uuid != '\0') {
5813                 uuid_t uuid;
5814                 static char newtarget[ZONENAME_MAX];
5815 
5816                 if (uuid_parse(target_uuid, uuid) == -1) {
5817                         zerror(gettext("illegal UUID value specified"));
5818                         exit(Z_ERR);
5819                 }
5820                 if (zonecfg_get_name_by_uuid(uuid, newtarget,
5821                     sizeof (newtarget)) == Z_OK)
5822                         target_zone = newtarget;
5823         }
5824 
5825         if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
5826                 errno = Z_NO_ZONE;
5827                 zperror(target_zone, B_TRUE);
5828                 exit(Z_ERR);
5829         }
5830 
5831         /*
5832          * See if we have inherited the right to manipulate this zone from
5833          * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
5834          * indicate it.  If not, make that explicit in our environment.
5835          */
5836         zonecfg_init_lock_file(target_zone, &zone_lock_env);
5837 
5838         /* Figure out what the system's default brand is */
5839         if (zonecfg_default_brand(default_brand,
5840             sizeof (default_brand)) != Z_OK) {
5841                 zerror(gettext("unable to determine default brand"));
5842                 return (Z_ERR);
5843         }
5844 
5845         /*
5846          * If we are going to be operating on a single zone, retrieve its
5847          * brand type and determine whether it is native or not.
5848          */
5849         if ((target_zone != NULL) &&
5850             (strcmp(target_zone, GLOBAL_ZONENAME) != 0)) {
5851                 if (zone_get_brand(target_zone, target_brand,
5852                     sizeof (target_brand)) != Z_OK) {
5853                         zerror(gettext("missing or invalid brand"));
5854                         exit(Z_ERR);
5855                 }
5856                 /*
5857                  * In the alternate root environment, the only supported
5858                  * operations are mount and unmount.  In this case, just treat
5859                  * the zone as native if it is cluster.  Cluster zones can be
5860                  * native for the purpose of LU or upgrade, and the cluster
5861                  * brand may not exist in the miniroot (such as in net install
5862                  * upgrade).
5863                  */
5864                 if (strcmp(target_brand, CLUSTER_BRAND_NAME) == 0) {
5865                         if (zonecfg_in_alt_root()) {
5866                                 (void) strlcpy(target_brand, default_brand,
5867                                     sizeof (target_brand));
5868                         }
5869                 }
5870         }
5871 
5872         err = parse_and_run(argc - optind, &argv[optind]);
5873 
5874         return (err);
5875 }