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