zoneadm.c revision 3448:aaf16568054b
1139749Simp/*
2119853Scg * CDDL HEADER START
3166426Sjoel *
458756Scg * The contents of this file are subject to the terms of the
558756Scg * Common Development and Distribution License (the "License").
658756Scg * You may not use this file except in compliance with the License.
758756Scg *
858756Scg * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
958756Scg * or http://www.opensolaris.org/os/licensing.
1058756Scg * See the License for the specific language governing permissions
1158756Scg * and limitations under the License.
1258756Scg *
1358756Scg * When distributing Covered Code, include this CDDL HEADER in each
1458756Scg * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1558756Scg * If applicable, add the following below this CDDL HEADER, with the
1658756Scg * fields enclosed by brackets "[]" replaced with your own identifying
1758756Scg * information: Portions Copyright [yyyy] [name of copyright owner]
1858756Scg *
1958756Scg * CDDL HEADER END
2058756Scg */
2158756Scg
2258756Scg/*
2358756Scg * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2458756Scg * Use is subject to license terms.
2558756Scg */
2658756Scg
2758756Scg#pragma ident	"%Z%%M%	%I%	%E% SMI"
2858756Scg
2958756Scg/*
3058756Scg * zoneadm is a command interpreter for zone administration.  It is all in
3158756Scg * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
3258756Scg * main() calls parse_and_run() which calls cmd_match(), then invokes the
3358756Scg * appropriate command's handler function.  The rest of the program is the
3458756Scg * handler functions and their helper functions.
3558756Scg *
3658756Scg * Some of the helper functions are used largely to simplify I18N: reducing
37110499Snyan * the need for translation notes.  This is particularly true of many of
38110499Snyan * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
3970134Scg * than zerror(gettext("foo failed")) with a translation note indicating
4070134Scg * that "foo" need not be translated.
4182180Scg */
4282180Scg
4359323Scg#include <stdio.h>
4458756Scg#include <errno.h>
4558756Scg#include <unistd.h>
4658756Scg#include <signal.h>
4758756Scg#include <stdarg.h>
4858756Scg#include <ctype.h>
4958756Scg#include <stdlib.h>
5058756Scg#include <string.h>
5158756Scg#include <wait.h>
5264881Scg#include <zone.h>
5364881Scg#include <priv.h>
5464881Scg#include <locale.h>
5564881Scg#include <libintl.h>
5664881Scg#include <libzonecfg.h>
5764881Scg#include <bsm/adt.h>
5864881Scg#include <sys/brand.h>
5964881Scg#include <sys/param.h>
6064881Scg#include <sys/types.h>
6164881Scg#include <sys/stat.h>
6258756Scg#include <sys/statvfs.h>
6358756Scg#include <assert.h>
64154438Sariff#include <sys/sockio.h>
6564881Scg#include <sys/mntent.h>
6664881Scg#include <limits.h>
6764881Scg#include <dirent.h>
6864881Scg#include <uuid/uuid.h>
6964881Scg
7064881Scg#include <fcntl.h>
7164881Scg#include <door.h>
7264881Scg#include <macros.h>
7364881Scg#include <libgen.h>
7464881Scg#include <fnmatch.h>
7564881Scg#include <sys/modctl.h>
7658756Scg#include <libbrand.h>
7758756Scg#include <libscf.h>
78154438Sariff#include <procfs.h>
7964881Scg
8058756Scg#include <pool.h>
8158756Scg#include <sys/pool.h>
8258756Scg#include <sys/priocntl.h>
8358756Scg#include <sys/fsspriocntl.h>
8474763Scg
8574763Scg#include "zoneadm.h"
8670134Scg
8770291Scg#define	MAXARGS	8
8858756Scg
8958756Scg/* Reflects kernel zone entries */
9058756Scgtypedef struct zone_entry {
9174763Scg	zoneid_t	zid;
9258756Scg	char		zname[ZONENAME_MAX];
9358756Scg	char		*zstate_str;
9458756Scg	zone_state_t	zstate_num;
9558756Scg	char		zbrand[MAXNAMELEN];
9665644Scg	char		zroot[MAXPATHLEN];
9758756Scg	char		zuuid[UUID_PRINTABLE_STRING_LENGTH];
9858756Scg	zone_iptype_t	ziptype;
9984111Scg} zone_entry_t;
100170032Sariff
101170032Sariffstatic zone_entry_t *zents;
10258756Scgstatic size_t nzents;
10358756Scgstatic boolean_t is_native_zone = B_TRUE;
10458756Scg
10558756Scg#define	LOOPBACK_IF	"lo0"
10684111Scg#define	SOCKET_AF(af)	(((af) == AF_UNSPEC) ? AF_INET : (af))
10758756Scg
10858756Scgstruct net_if {
10958756Scg	char	*name;
11058756Scg	int	af;
11158756Scg};
11258756Scg
11358756Scg/* 0755 is the default directory mode. */
11458756Scg#define	DEFAULT_DIR_MODE \
11558756Scg	(S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
11658756Scg
11758756Scgstruct cmd {
11858756Scg	uint_t	cmd_num;				/* command number */
11958756Scg	char	*cmd_name;				/* command name */
12058756Scg	char	*short_usage;				/* short form help */
12158756Scg	int	(*handler)(int argc, char *argv[]);	/* function to call */
12258756Scg
12358756Scg};
12484111Scg
12558756Scg#define	SHELP_HELP	"help"
12658756Scg#define	SHELP_BOOT	"boot [-- boot_arguments]"
12758756Scg#define	SHELP_HALT	"halt"
12858756Scg#define	SHELP_READY	"ready"
12958756Scg#define	SHELP_REBOOT	"reboot [-- boot_arguments]"
13058756Scg#define	SHELP_LIST	"list [-cipv]"
13158756Scg#define	SHELP_VERIFY	"verify"
13258756Scg#define	SHELP_INSTALL	"install [-x nodataset] [brand-specific args]"
13358756Scg#define	SHELP_UNINSTALL	"uninstall [-F]"
13458756Scg#define	SHELP_CLONE	"clone [-m method] [-s <ZFS snapshot>] zonename"
13558756Scg#define	SHELP_MOVE	"move zonepath"
13658756Scg#define	SHELP_DETACH	"detach [-n]"
13758756Scg#define	SHELP_ATTACH	"attach [-F] [-n <path>]"
13874763Scg#define	SHELP_MARK	"mark incomplete"
13974763Scg
14074763Scg#define	EXEC_PREFIX	"exec "
14174763Scg#define	EXEC_LEN	(strlen(EXEC_PREFIX))
14274763Scg#define	RMCOMMAND	"/usr/bin/rm -rf"
14374763Scg
14474763Scgstatic int cleanup_zonepath(char *, boolean_t);
14574763Scg
14674763Scgextern int ifname_open(char *);
14774763Scg
14874763Scgstatic int help_func(int argc, char *argv[]);
14974763Scgstatic int ready_func(int argc, char *argv[]);
15058756Scgstatic int boot_func(int argc, char *argv[]);
15158756Scgstatic int halt_func(int argc, char *argv[]);
15258756Scgstatic int reboot_func(int argc, char *argv[]);
15358756Scgstatic int list_func(int argc, char *argv[]);
15458756Scgstatic int verify_func(int argc, char *argv[]);
15558756Scgstatic int install_func(int argc, char *argv[]);
15658756Scgstatic int uninstall_func(int argc, char *argv[]);
15758756Scgstatic int mount_func(int argc, char *argv[]);
15858756Scgstatic int unmount_func(int argc, char *argv[]);
15958756Scgstatic int clone_func(int argc, char *argv[]);
16058756Scgstatic int move_func(int argc, char *argv[]);
161108064Ssemenustatic int detach_func(int argc, char *argv[]);
162108064Ssemenustatic int attach_func(int argc, char *argv[]);
163108064Ssemenustatic int mark_func(int argc, char *argv[]);
16458756Scgstatic int apply_func(int argc, char *argv[]);
16558756Scgstatic int sanity_check(char *zone, int cmd_num, boolean_t running,
16658756Scg    boolean_t unsafe_when_running, boolean_t force);
16758756Scgstatic int cmd_match(char *cmd);
16858756Scgstatic int verify_details(int, char *argv[]);
16958756Scgstatic int verify_brand(zone_dochandle_t, int, char *argv[]);
17058756Scgstatic int invoke_brand_handler(int, char *argv[]);
17158756Scg
17258756Scgstatic struct cmd cmdtab[] = {
17358756Scg	{ CMD_HELP,		"help",		SHELP_HELP,	help_func },
17458756Scg	{ CMD_BOOT,		"boot",		SHELP_BOOT,	boot_func },
17558756Scg	{ CMD_HALT,		"halt",		SHELP_HALT,	halt_func },
17658756Scg	{ CMD_READY,		"ready",	SHELP_READY,	ready_func },
17758756Scg	{ CMD_REBOOT,		"reboot",	SHELP_REBOOT,	reboot_func },
17858756Scg	{ CMD_LIST,		"list",		SHELP_LIST,	list_func },
17958756Scg	{ CMD_VERIFY,		"verify",	SHELP_VERIFY,	verify_func },
18058756Scg	{ CMD_INSTALL,		"install",	SHELP_INSTALL,	install_func },
18158756Scg	{ CMD_UNINSTALL,	"uninstall",	SHELP_UNINSTALL,
18258756Scg	    uninstall_func },
18358756Scg	/* mount and unmount are private commands for admin/install */
18458756Scg	{ CMD_MOUNT,		"mount",	NULL,		mount_func },
18558756Scg	{ CMD_UNMOUNT,		"unmount",	NULL,		unmount_func },
18658756Scg	{ CMD_CLONE,		"clone",	SHELP_CLONE,	clone_func },
18758756Scg	{ CMD_MOVE,		"move",		SHELP_MOVE,	move_func },
18858756Scg	{ CMD_DETACH,		"detach",	SHELP_DETACH,	detach_func },
18958756Scg	{ CMD_ATTACH,		"attach",	SHELP_ATTACH,	attach_func },
19058756Scg	{ CMD_MARK,		"mark",		SHELP_MARK,	mark_func },
19158756Scg	{ CMD_APPLY,		"apply",	NULL,		apply_func }
19258756Scg};
19358756Scg
19458756Scg/* global variables */
19558756Scg
19658756Scg/* set early in main(), never modified thereafter, used all over the place */
19758756Scgstatic char *execname;
19858756Scgstatic char target_brand[MAXNAMELEN];
19958756Scgstatic char *locale;
20058756Scgchar *target_zone;
20158756Scgstatic char *target_uuid;
20258756Scg
20358756Scg/* used in do_subproc() and signal handler */
20458756Scgstatic volatile boolean_t child_killed;
20558756Scgstatic int do_subproc_cnt = 0;
20658756Scg
20758756Scg/*
20858756Scg * Used to indicate whether this zoneadm instance has another zoneadm
20958756Scg * instance in its ancestry.
21058756Scg */
21158756Scgstatic boolean_t zoneadm_is_nested = B_FALSE;
21258756Scg
21358756Scg/* used to track nested zone-lock operations */
21458756Scgstatic int zone_lock_cnt = 0;
21558756Scg
21658756Scg/* used to communicate lock status to children */
21758756Scg#define	LOCK_ENV_VAR	"_ZONEADM_LOCK_HELD"
21858756Scgstatic char zoneadm_lock_held[] = LOCK_ENV_VAR"=1";
21958756Scgstatic char zoneadm_lock_not_held[] = LOCK_ENV_VAR"=0";
22058756Scg
22158756Scgchar *
22258756Scgcmd_to_str(int cmd_num)
22358756Scg{
22458756Scg	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
22558756Scg	return (cmdtab[cmd_num].cmd_name);
22658756Scg}
22758756Scg
22858756Scg/* This is a separate function because of gettext() wrapping. */
22958756Scgstatic char *
23058756Scglong_help(int cmd_num)
23158756Scg{
23258756Scg	assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
23358756Scg	switch (cmd_num) {
23458756Scg	case CMD_HELP:
23558756Scg		return (gettext("Print usage message."));
23658756Scg	case CMD_BOOT:
23758756Scg		return (gettext("Activates (boots) specified zone.  See "
23858756Scg		    "zoneadm(1m) for valid boot\n\targuments."));
23958756Scg	case CMD_HALT:
24058756Scg		return (gettext("Halts specified zone, bypassing shutdown "
24158756Scg		    "scripts and removing runtime\n\tresources of the zone."));
24258756Scg	case CMD_READY:
24358756Scg		return (gettext("Prepares a zone for running applications but "
24458756Scg		    "does not start any user\n\tprocesses in the zone."));
24558756Scg	case CMD_REBOOT:
24658756Scg		return (gettext("Restarts the zone (equivalent to a halt / "
24758756Scg		    "boot sequence).\n\tFails if the zone is not active.  "
24858756Scg		    "See zoneadm(1m) for valid boot\n\targuments."));
24958756Scg	case CMD_LIST:
25058756Scg		return (gettext("Lists the current zones, or a "
25158756Scg		    "specific zone if indicated.  By default,\n\tall "
25258756Scg		    "running zones are listed, though this can be "
25358756Scg		    "expanded to all\n\tinstalled zones with the -i "
25458756Scg		    "option or all configured zones with the\n\t-c "
25558756Scg		    "option.  When used with the general -z <zone> and/or -u "
25658756Scg		    "<uuid-match>\n\toptions, lists only the specified "
25758756Scg		    "matching zone, but lists it\n\tregardless of its state, "
25858756Scg		    "and the -i and -c options are disallowed.  The\n\t-v "
25958756Scg		    "option can be used to display verbose information: zone "
26058756Scg		    "name, id,\n\tcurrent state, root directory and options.  "
26158756Scg		    "The -p option can be used\n\tto request machine-parsable "
26258756Scg		    "output.  The -v and -p options are mutually\n\texclusive."
26358756Scg		    "  If neither -v nor -p is used, just the zone name is "
26458756Scg		    "listed."));
26558756Scg	case CMD_VERIFY:
26658756Scg		return (gettext("Check to make sure the configuration "
26758756Scg		    "can safely be instantiated\n\ton the machine: "
26858756Scg		    "physical network interfaces exist, etc."));
26958756Scg	case CMD_INSTALL:
27058756Scg		return (gettext("Install the configuration on to the system.  "
27158756Scg		    "The -x nodataset option\n\tcan be used to prevent the "
27258756Scg		    "creation of a new ZFS file system for the\n\tzone "
27358756Scg		    "(assuming the zonepath is within a ZFS file system).\n\t"
27458756Scg		    "All other arguments are passed to the brand installation "
27558756Scg		    "function;\n\tsee brand(4) for more information."));
27689774Sscottl	case CMD_UNINSTALL:
27758756Scg		return (gettext("Uninstall the configuration from the system.  "
27858756Scg		    "The -F flag can be used\n\tto force the action."));
27958756Scg	case CMD_CLONE:
28058756Scg		return (gettext("Clone the installation of another zone.  "
28158756Scg		    "The -m option can be used to\n\tspecify 'copy' which "
28258756Scg		    "forces a copy of the source zone.  The -s option\n\t"
28358756Scg		    "can be used to specify the name of a ZFS snapshot "
28458756Scg		    "that was taken from\n\ta previous clone command.  The "
28558756Scg		    "snapshot will be used as the source\n\tinstead of "
28658756Scg		    "creating a new ZFS snapshot."));
28765644Scg	case CMD_MOVE:
28865644Scg		return (gettext("Move the zone to a new zonepath."));
28958756Scg	case CMD_DETACH:
29058756Scg		return (gettext("Detach the zone from the system. The zone "
29158756Scg		    "state is changed to\n\t'configured' (but the files under "
29258756Scg		    "the zonepath are untouched).\n\tThe zone can subsequently "
29384111Scg		    "be attached, or can be moved to another\n\tsystem and "
29458756Scg		    "attached there.  The -n option can be used to specify\n\t"
29558756Scg		    "'no-execute' mode.  When -n is used, the information "
29658756Scg		    "needed to attach\n\tthe zone is sent to standard output "
29758756Scg		    "but the zone is not actually\n\tdetached."));
29884111Scg	case CMD_ATTACH:
29958756Scg		return (gettext("Attach the zone to the system.  The zone "
30058756Scg		    "state must be 'configured'\n\tprior to attach; upon "
30158756Scg		    "successful completion, the zone state will be\n\t"
30258756Scg		    "'installed'.  The system software on the current "
30358756Scg		    "system must be\n\tcompatible with the software on the "
30458756Scg		    "zone's original system.\n\tSpecify -F to force the attach "
30558756Scg		    "and skip software compatibility tests.\n\tThe -n option "
30665644Scg		    "can be used to specify 'no-execute' mode.  When -n is\n\t"
30765644Scg		    "used, the information needed to attach the zone is read "
30865644Scg		    "from the\n\tspecified path and the configuration is only "
30965644Scg		    "validated.  The path can\n\tbe '-' to specify standard "
31065644Scg		    "input."));
31158756Scg	case CMD_MARK:
31258756Scg		return (gettext("Set the state of the zone.  This can be used "
31358756Scg		    "to force the zone\n\tstate to 'incomplete' "
31458756Scg		    "administratively if some activity has rendered\n\tthe "
31558756Scg		    "zone permanently unusable.  The only valid state that "
31658756Scg		    "may be\n\tspecified is 'incomplete'."));
31758756Scg	default:
31858756Scg		return ("");
31958756Scg	}
320127135Snjl	/* NOTREACHED */
321127135Snjl	return (NULL);
32258756Scg}
32358756Scg
324127135Snjl/*
325127135Snjl * Called with explicit B_TRUE when help is explicitly requested, B_FALSE for
32658756Scg * unexpected errors.
32758756Scg */
328127135Snjl
329127135Snjlstatic int
33058756Scgusage(boolean_t explicit)
33158756Scg{
332127135Snjl	int i;
333127135Snjl	FILE *fd = explicit ? stdout : stderr;
33458756Scg
33558756Scg	(void) fprintf(fd, "%s:\t%s help\n", gettext("usage"), execname);
33658756Scg	(void) fprintf(fd, "\t%s [-z <zone>] [-u <uuid-match>] list\n",
33784111Scg	    execname);
33858756Scg	(void) fprintf(fd, "\t%s {-z <zone>|-u <uuid-match>} <%s>\n", execname,
33958756Scg	    gettext("subcommand"));
34058756Scg	(void) fprintf(fd, "\n%s:\n\n", gettext("Subcommands"));
34184111Scg	for (i = CMD_MIN; i <= CMD_MAX; i++) {
34258756Scg		if (cmdtab[i].short_usage == NULL)
34358756Scg			continue;
34458756Scg		(void) fprintf(fd, "%s\n", cmdtab[i].short_usage);
34558756Scg		if (explicit)
34658756Scg			(void) fprintf(fd, "\t%s\n\n", long_help(i));
34758756Scg	}
34858756Scg	if (!explicit)
34958756Scg		(void) fputs("\n", fd);
35058756Scg	return (Z_USAGE);
35158756Scg}
35258756Scg
35358756Scgstatic void
35474763Scgsub_usage(char *short_usage, int cmd_num)
35558756Scg{
35658756Scg	(void) fprintf(stderr, "%s:\t%s\n", gettext("usage"), short_usage);
35758756Scg	(void) fprintf(stderr, "\t%s\n", long_help(cmd_num));
35858756Scg}
35958756Scg
36058756Scg/*
36158756Scg * zperror() is like perror(3c) except that this also prints the executable
36258756Scg * name at the start of the message, and takes a boolean indicating whether
36358756Scg * to call libc'c strerror() or that from libzonecfg.
36458756Scg */
365148598Snetchild
366148598Snetchildvoid
36770392Scgzperror(const char *str, boolean_t zonecfg_error)
368148598Snetchild{
369148598Snetchild	(void) fprintf(stderr, "%s: %s: %s\n", execname, str,
37058756Scg	    zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
37170134Scg}
372110499Snyan
37358756Scg/*
37458756Scg * zperror2() is very similar to zperror() above, except it also prints a
37558756Scg * supplied zone name after the executable.
37658756Scg *
37758756Scg * All current consumers of this function want libzonecfg's strerror() rather
37858756Scg * than libc's; if this ever changes, this function can be made more generic
37958756Scg * like zperror() above.
38058756Scg */
38158756Scg
382148598Snetchildvoid
383148598Snetchildzperror2(const char *zone, const char *str)
38470392Scg{
385148598Snetchild	(void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
386148598Snetchild	    zonecfg_strerror(errno));
38758756Scg}
38870134Scg
389110499Snyan/* PRINTFLIKE1 */
39058756Scgvoid
39158756Scgzerror(const char *fmt, ...)
39258756Scg{
39358756Scg	va_list alist;
39458756Scg
39558756Scg	va_start(alist, fmt);
39658756Scg	(void) fprintf(stderr, "%s: ", execname);
39758756Scg	if (target_zone != NULL)
39858756Scg		(void) fprintf(stderr, "zone '%s': ", target_zone);
39958756Scg	(void) vfprintf(stderr, fmt, alist);
40074763Scg	(void) fprintf(stderr, "\n");
40158756Scg	va_end(alist);
40258756Scg}
40358756Scg
40458756Scgstatic void *
40558756Scgsafe_calloc(size_t nelem, size_t elsize)
40658756Scg{
40758756Scg	void *r = calloc(nelem, elsize);
40858756Scg
40958756Scg	if (r == NULL) {
41058756Scg		zerror(gettext("failed to allocate %lu bytes: %s"),
41158756Scg		    (ulong_t)nelem * elsize, strerror(errno));
41258756Scg		exit(Z_ERR);
41358756Scg	}
41458756Scg	return (r);
41558756Scg}
41658756Scg
41758756Scgstatic void
41858756Scgzone_print(zone_entry_t *zent, boolean_t verbose, boolean_t parsable)
41958756Scg{
42058756Scg	static boolean_t firsttime = B_TRUE;
42158756Scg	char *ip_type_str;
42258756Scg
42358756Scg	if (zent->ziptype == ZS_EXCLUSIVE)
42458756Scg		ip_type_str = "excl";
42558756Scg	else
42658756Scg		ip_type_str = "shared";
42758756Scg
42858756Scg	assert(!(verbose && parsable));
42958756Scg	if (firsttime && verbose) {
43058756Scg		firsttime = B_FALSE;
43158756Scg		(void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
43260571Scg		    ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
43360571Scg		    "IP");
43458756Scg	}
43560571Scg	if (!verbose) {
43660571Scg		char *cp, *clim;
43760571Scg
43858756Scg		if (!parsable) {
43958756Scg			(void) printf("%s\n", zent->zname);
44058756Scg			return;
44158756Scg		}
44258756Scg		if (zent->zid == ZONE_ID_UNDEFINED)
44358756Scg			(void) printf("-");
44458756Scg		else
44558756Scg			(void) printf("%lu", zent->zid);
44658756Scg		(void) printf(":%s:%s:", zent->zname, zent->zstate_str);
44758756Scg		cp = zent->zroot;
44858756Scg		while ((clim = strchr(cp, ':')) != NULL) {
44958756Scg			(void) printf("%.*s\\:", clim - cp, cp);
45058756Scg			cp = clim + 1;
45158756Scg		}
45258756Scg		(void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
45358756Scg		    ip_type_str);
45458756Scg		return;
45558756Scg	}
45658756Scg	if (zent->zstate_str != NULL) {
45758756Scg		if (zent->zid == ZONE_ID_UNDEFINED)
45858756Scg			(void) printf("%*s", ZONEID_WIDTH, "-");
45958756Scg		else
46058756Scg			(void) printf("%*lu", ZONEID_WIDTH, zent->zid);
46158756Scg		(void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
46258756Scg		    zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
46358756Scg	}
46458756Scg}
46558756Scg
46658756Scgstatic int
46758756Scglookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
46858756Scg{
46958756Scg	char root[MAXPATHLEN], *cp;
47058756Scg	int err;
47158756Scg	uuid_t uuid;
47258756Scg
47358756Scg	(void) strlcpy(zent->zname, zone_name, sizeof (zent->zname));
47458756Scg	(void) strlcpy(zent->zroot, "???", sizeof (zent->zroot));
47558756Scg	(void) strlcpy(zent->zbrand, "???", sizeof (zent->zbrand));
47658756Scg	zent->zstate_str = "???";
47758756Scg
47858756Scg	zent->zid = zid;
47958756Scg
48058756Scg	if (zonecfg_get_uuid(zone_name, uuid) == Z_OK &&
48158756Scg	    !uuid_is_null(uuid))
48258756Scg		uuid_unparse(uuid, zent->zuuid);
48358756Scg	else
48458756Scg		zent->zuuid[0] = '\0';
48558756Scg
48658756Scg	/*
48758756Scg	 * For labeled zones which query the zone path of lower-level
48858756Scg	 * zones, the path needs to be adjusted to drop the final
48958756Scg	 * "/root" component. This adjusted path is then useful
49058756Scg	 * for reading down any exported directories from the
49158756Scg	 * lower-level zone.
49258756Scg	 */
49358756Scg	if (is_system_labeled() && zent->zid != ZONE_ID_UNDEFINED) {
49458756Scg		if (zone_getattr(zent->zid, ZONE_ATTR_ROOT, zent->zroot,
49558756Scg		    sizeof (zent->zroot)) == -1) {
49658756Scg			zperror2(zent->zname,
49758756Scg			    gettext("could not get zone path."));
49858756Scg			return (Z_ERR);
49958756Scg		}
50058756Scg		cp = zent->zroot + strlen(zent->zroot) - 5;
50158756Scg		if (cp > zent->zroot && strcmp(cp, "/root") == 0)
50258756Scg			*cp = 0;
50358756Scg	} else {
50458756Scg		if ((err = zone_get_zonepath(zent->zname, root,
50558756Scg		    sizeof (root))) != Z_OK) {
50658756Scg			errno = err;
50758756Scg			zperror2(zent->zname,
50858756Scg			    gettext("could not get zone path."));
50958756Scg			return (Z_ERR);
51058756Scg		}
51158756Scg		(void) strlcpy(zent->zroot, root, sizeof (zent->zroot));
51258756Scg	}
51358756Scg
51458756Scg	if ((err = zone_get_state(zent->zname, &zent->zstate_num)) != Z_OK) {
51574763Scg		errno = err;
51658756Scg		zperror2(zent->zname, gettext("could not get state"));
51758756Scg		return (Z_ERR);
51858756Scg	}
51958756Scg	zent->zstate_str = zone_state_str(zent->zstate_num);
52058756Scg
52158756Scg	/*
52258756Scg	 * A zone's brand is only available in the .xml file describing it,
52358756Scg	 * which is only visible to the global zone.  This causes
52458756Scg	 * zone_get_brand() to fail when called from within a non-global
52574763Scg	 * zone.  Fortunately we only do this on labeled systems, where we
52670291Scg	 * know all zones are native.
52758756Scg	 */
52858756Scg	if (getzoneid() != GLOBAL_ZONEID) {
52958756Scg		assert(is_system_labeled() != 0);
53058756Scg		(void) strlcpy(zent->zbrand, NATIVE_BRAND_NAME,
53158756Scg		    sizeof (zent->zbrand));
53258756Scg	} else if (zone_get_brand(zent->zname, zent->zbrand,
53358756Scg	    sizeof (zent->zbrand)) != Z_OK) {
53474763Scg		zperror2(zent->zname, gettext("could not get brand name"));
53558756Scg		return (Z_ERR);
53658756Scg	}
53758756Scg
53858756Scg	/*
53958756Scg	 * Get ip type of the zone.
54058756Scg	 * Note for global zone, ZS_SHARED is set always.
54158756Scg	 */
54258756Scg	if (zid == GLOBAL_ZONEID) {
54358756Scg		zent->ziptype = ZS_SHARED;
54474763Scg	} else {
54558756Scg
54658756Scg		if (zent->zstate_num == ZONE_STATE_RUNNING) {
54758756Scg			ushort_t flags;
54858756Scg
54958756Scg			if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
55058756Scg			    sizeof (flags)) < 0) {
55158756Scg				zperror2(zent->zname,
55274763Scg				    gettext("could not get zone flags"));
55358756Scg				return (Z_ERR);
55458756Scg			}
55558756Scg			if (flags & ZF_NET_EXCL)
55670134Scg				zent->ziptype = ZS_EXCLUSIVE;
55758756Scg			else
55858756Scg				zent->ziptype = ZS_SHARED;
55974763Scg		} else {
56058756Scg			zone_dochandle_t handle;
56158756Scg
56258756Scg			if ((handle = zonecfg_init_handle()) == NULL) {
56358756Scg				zperror2(zent->zname,
56458756Scg				    gettext("could not init handle"));
56558756Scg				return (Z_ERR);
56658756Scg			}
567168847Sariff			if ((err = zonecfg_get_handle(zent->zname, handle))
56858756Scg			    != Z_OK) {
56965644Scg				zperror2(zent->zname,
57058756Scg				    gettext("could not get handle"));
57158756Scg				zonecfg_fini_handle(handle);
57258756Scg				return (Z_ERR);
573110499Snyan			}
57458756Scg
57558756Scg			if ((err = zonecfg_get_iptype(handle, &zent->ziptype))
57658756Scg			    != Z_OK) {
57758756Scg				zperror2(zent->zname,
57870134Scg				    gettext("could not get ip-type"));
57958756Scg				zonecfg_fini_handle(handle);
58058756Scg				return (Z_ERR);
58158756Scg			}
58258756Scg			zonecfg_fini_handle(handle);
58358756Scg		}
58458756Scg	}
58558756Scg
58658756Scg	return (Z_OK);
58770134Scg}
58858756Scg
58958756Scg/*
59058756Scg * fetch_zents() calls zone_list(2) to find out how many zones are running
59158756Scg * (which is stored in the global nzents), then calls zone_list(2) again
59258756Scg * to fetch the list of running zones (stored in the global zents).  This
59358756Scg * function may be called multiple times, so if zents is already set, we
59458756Scg * return immediately to save work.
59558756Scg */
59658756Scg
59758756Scgstatic int
59858756Scgfetch_zents(void)
59958756Scg{
60058756Scg	zoneid_t *zids = NULL;
60170134Scg	uint_t nzents_saved;
60258756Scg	int i, retv;
60370291Scg	FILE *fp;
60470291Scg	boolean_t inaltroot;
60570291Scg	zone_entry_t *zentp;
60670291Scg
60758756Scg	if (nzents > 0)
60858756Scg		return (Z_OK);
60958756Scg
61070134Scg	if (zone_list(NULL, &nzents) != 0) {
61158756Scg		zperror(gettext("failed to get zoneid list"), B_FALSE);
61258756Scg		return (Z_ERR);
61358756Scg	}
61460958Scg
61558756Scgagain:
61658756Scg	if (nzents == 0)
61758756Scg		return (Z_OK);
61858756Scg
61970134Scg	zids = safe_calloc(nzents, sizeof (zoneid_t));
620110499Snyan	nzents_saved = nzents;
62158756Scg
62258756Scg	if (zone_list(zids, &nzents) != 0) {
62358756Scg		zperror(gettext("failed to get zone list"), B_FALSE);
62458756Scg		free(zids);
62558756Scg		return (Z_ERR);
62658756Scg	}
62758756Scg	if (nzents != nzents_saved) {
62858756Scg		/* list changed, try again */
62958756Scg		free(zids);
63058756Scg		goto again;
63158756Scg	}
63258756Scg
63358756Scg	zents = safe_calloc(nzents, sizeof (zone_entry_t));
63470134Scg
63558756Scg	inaltroot = zonecfg_in_alt_root();
63658756Scg	if (inaltroot)
63758756Scg		fp = zonecfg_open_scratch("", B_FALSE);
638110499Snyan	else
63958756Scg		fp = NULL;
64058756Scg	zentp = zents;
64174763Scg	retv = Z_OK;
64270134Scg	for (i = 0; i < nzents; i++) {
64358756Scg		char name[ZONENAME_MAX];
64458756Scg		char altname[ZONENAME_MAX];
64558756Scg
64658756Scg		if (getzonenamebyid(zids[i], name, sizeof (name)) < 0) {
64758756Scg			zperror(gettext("failed to get zone name"), B_FALSE);
64858756Scg			retv = Z_ERR;
64970134Scg			continue;
65070134Scg		}
65170134Scg		if (zonecfg_is_scratch(name)) {
65270134Scg			/* Ignore scratch zones by default */
65370134Scg			if (!inaltroot)
65470134Scg				continue;
65570134Scg			if (fp == NULL ||
65670134Scg			    zonecfg_reverse_scratch(fp, name, altname,
65770134Scg			    sizeof (altname), NULL, 0) == -1) {
65870134Scg				zerror(gettext("could not resolve scratch "
65970134Scg				    "zone %s"), name);
66070134Scg				retv = Z_ERR;
66158756Scg				continue;
66258756Scg			}
66358756Scg			(void) strcpy(name, altname);
66474763Scg		} else {
66558756Scg			/* Ignore non-scratch when in an alternate root */
66658756Scg			if (inaltroot && strcmp(name, GLOBAL_ZONENAME) != 0)
66758756Scg				continue;
66858756Scg		}
66958756Scg		if (lookup_zone_info(name, zids[i], zentp) != Z_OK) {
67058756Scg			zerror(gettext("failed to get zone data"));
67158756Scg			retv = Z_ERR;
67258756Scg			continue;
67373151Scg		}
67458756Scg		zentp++;
67558756Scg	}
67658756Scg	nzents = zentp - zents;
67758756Scg	if (fp != NULL)
67858756Scg		zonecfg_close_scratch(fp);
67958756Scg
68058756Scg	free(zids);
68174763Scg	return (retv);
68258756Scg}
68358756Scg
68458756Scgstatic int
68558756Scgzone_print_list(zone_state_t min_state, boolean_t verbose, boolean_t parsable)
68658756Scg{
68758756Scg	int i;
68858756Scg	zone_entry_t zent;
68958756Scg	FILE *cookie;
69058756Scg	char *name;
69158756Scg
69258756Scg	/*
69358756Scg	 * First get the list of running zones from the kernel and print them.
69458756Scg	 * If that is all we need, then return.
69558756Scg	 */
69658756Scg	if ((i = fetch_zents()) != Z_OK) {
69758756Scg		/*
69858756Scg		 * No need for error messages; fetch_zents() has already taken
69958756Scg		 * care of this.
70058756Scg		 */
70158756Scg		return (i);
70258756Scg	}
70358756Scg	for (i = 0; i < nzents; i++)
70458756Scg		zone_print(&zents[i], verbose, parsable);
70558756Scg	if (min_state >= ZONE_STATE_RUNNING)
70658756Scg		return (Z_OK);
70758756Scg	/*
70858756Scg	 * Next, get the full list of zones from the configuration, skipping
70958756Scg	 * any we have already printed.
71058756Scg	 */
71158756Scg	cookie = setzoneent();
71258756Scg	while ((name = getzoneent(cookie)) != NULL) {
71358756Scg		for (i = 0; i < nzents; i++) {
71458756Scg			if (strcmp(zents[i].zname, name) == 0)
71558756Scg				break;
71658756Scg		}
71758756Scg		if (i < nzents) {
71858756Scg			free(name);
71973151Scg			continue;
72073151Scg		}
72173151Scg		if (lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
72273151Scg			free(name);
72373151Scg			continue;
72458756Scg		}
72558756Scg		free(name);
72658756Scg		if (zent.zstate_num >= min_state)
72758756Scg			zone_print(&zent, verbose, parsable);
72858756Scg	}
72958756Scg	endzoneent(cookie);
73058756Scg	return (Z_OK);
73158756Scg}
73258756Scg
73358756Scgstatic zone_entry_t *
73458756Scglookup_running_zone(char *str)
73558756Scg{
73658756Scg	zoneid_t zoneid;
73758756Scg	char *cp;
73858756Scg	int i;
73958756Scg
74058756Scg	if (fetch_zents() != Z_OK)
74158756Scg		return (NULL);
74258756Scg
74358756Scg	for (i = 0; i < nzents; i++) {
74458756Scg		if (strcmp(str, zents[i].zname) == 0)
74574763Scg			return (&zents[i]);
74658756Scg	}
74758756Scg	errno = 0;
74858756Scg	zoneid = strtol(str, &cp, 0);
74958756Scg	if (zoneid < MIN_ZONEID || zoneid > MAX_ZONEID ||
75058756Scg	    errno != 0 || *cp != '\0')
75158756Scg		return (NULL);
75258756Scg	for (i = 0; i < nzents; i++) {
75358756Scg		if (zoneid == zents[i].zid)
75458756Scg			return (&zents[i]);
75558756Scg	}
75658756Scg	return (NULL);
75758756Scg}
75858756Scg
75958756Scg/*
76058756Scg * Check a bit in a mode_t: if on is B_TRUE, that bit should be on; if
76158756Scg * B_FALSE, it should be off.  Return B_TRUE if the mode is bad (incorrect).
76258756Scg */
76358756Scgstatic boolean_t
76458756Scgbad_mode_bit(mode_t mode, mode_t bit, boolean_t on, char *file)
76558756Scg{
76658756Scg	char *str;
76758756Scg
76858756Scg	assert(bit == S_IRUSR || bit == S_IWUSR || bit == S_IXUSR ||
76958756Scg	    bit == S_IRGRP || bit == S_IWGRP || bit == S_IXGRP ||
77058756Scg	    bit == S_IROTH || bit == S_IWOTH || bit == S_IXOTH);
77158756Scg	/*
77258756Scg	 * TRANSLATION_NOTE
77358756Scg	 * The strings below will be used as part of a larger message,
77458756Scg	 * either:
77570134Scg	 * (file name) must be (owner|group|world) (read|writ|execut)able
77670134Scg	 * or
77770134Scg	 * (file name) must not be (owner|group|world) (read|writ|execut)able
77870134Scg	 */
77970134Scg	switch (bit) {
78070134Scg	case S_IRUSR:
78170134Scg		str = gettext("owner readable");
78270134Scg		break;
78370134Scg	case S_IWUSR:
78470134Scg		str = gettext("owner writable");
78558756Scg		break;
78658756Scg	case S_IXUSR:
78758756Scg		str = gettext("owner executable");
78858756Scg		break;
78958756Scg	case S_IRGRP:
79058756Scg		str = gettext("group readable");
79158756Scg		break;
79258756Scg	case S_IWGRP:
79358756Scg		str = gettext("group writable");
79458756Scg		break;
79558756Scg	case S_IXGRP:
79658756Scg		str = gettext("group executable");
79758756Scg		break;
79858756Scg	case S_IROTH:
79958756Scg		str = gettext("world readable");
80058756Scg		break;
80158756Scg	case S_IWOTH:
80258756Scg		str = gettext("world writable");
80358756Scg		break;
80458756Scg	case S_IXOTH:
80558756Scg		str = gettext("world executable");
80658756Scg		break;
80758756Scg	}
80858756Scg	if ((mode & bit) == (on ? 0 : bit)) {
80970134Scg		/*
81070134Scg		 * TRANSLATION_NOTE
81158756Scg		 * The first parameter below is a file name; the second
81278564Sgreid		 * is one of the "(owner|group|world) (read|writ|execut)able"
81358756Scg		 * strings from above.
81458756Scg		 */
81558756Scg		/*
81674763Scg		 * The code below could be simplified but not in a way
81784111Scg		 * that would easily translate to non-English locales.
81870134Scg		 */
81970134Scg		if (on) {
82070134Scg			(void) fprintf(stderr, gettext("%s must be %s.\n"),
82170134Scg			    file, str);
82270134Scg		} else {
82370134Scg			(void) fprintf(stderr, gettext("%s must not be %s.\n"),
82470134Scg			    file, str);
82570134Scg		}
82670134Scg		return (B_TRUE);
82770134Scg	}
82870134Scg	return (B_FALSE);
82970134Scg}
83070134Scg
83170134Scg/*
83270134Scg * We want to make sure that no zone has its zone path as a child node
83370134Scg * (in the directory sense) of any other.  We do that by comparing this
83470134Scg * zone's path to the path of all other (non-global) zones.  The comparison
83570134Scg * in each case is simple: add '/' to the end of the path, then do a
83670134Scg * strncmp() of the two paths, using the length of the shorter one.
83770134Scg */
83870134Scg
83970134Scgstatic int
84070134Scgcrosscheck_zonepaths(char *path)
84170134Scg{
84270134Scg	char rpath[MAXPATHLEN];		/* resolved path */
84370134Scg	char path_copy[MAXPATHLEN];	/* copy of original path */
84470134Scg	char rpath_copy[MAXPATHLEN];	/* copy of original rpath */
84570134Scg	struct zoneent *ze;
84670134Scg	int res, err;
84770134Scg	FILE *cookie;
84870134Scg
84970134Scg	cookie = setzoneent();
85070134Scg	while ((ze = getzoneent_private(cookie)) != NULL) {
851128232Sgreen		/* Skip zones which are not installed. */
85270134Scg		if (ze->zone_state < ZONE_STATE_INSTALLED) {
85370134Scg			free(ze);
85470134Scg			continue;
855166904Snetchild		}
856166904Snetchild		/* Skip the global zone and the current target zone. */
85770134Scg		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0 ||
85870134Scg		    strcmp(ze->zone_name, target_zone) == 0) {
85970134Scg			free(ze);
86084111Scg			continue;
86170134Scg		}
862117126Sscottl		if (strlen(ze->zone_path) == 0) {
863117126Sscottl			/* old index file without path, fall back */
86470134Scg			if ((err = zone_get_zonepath(ze->zone_name,
86570134Scg			    ze->zone_path, sizeof (ze->zone_path))) != Z_OK) {
86670134Scg				errno = err;
86770134Scg				zperror2(ze->zone_name,
86870134Scg				    gettext("could not get zone path"));
86984111Scg				free(ze);
87084111Scg				continue;
87184111Scg			}
87270134Scg		}
873126695Smatk		(void) snprintf(path_copy, sizeof (path_copy), "%s%s",
87484111Scg		    zonecfg_get_root(), ze->zone_path);
875126695Smatk		res = resolvepath(path_copy, rpath, sizeof (rpath));
876126695Smatk		if (res == -1) {
87784111Scg			if (errno != ENOENT) {
87870134Scg				zperror(path_copy, B_FALSE);
87970134Scg				free(ze);
88070134Scg				return (Z_ERR);
88170134Scg			}
88270134Scg			(void) printf(gettext("WARNING: zone %s is installed, "
88370134Scg			    "but its %s %s does not exist.\n"), ze->zone_name,
88470134Scg			    "zonepath", path_copy);
88570134Scg			free(ze);
88670134Scg			continue;
88770134Scg		}
88870134Scg		rpath[res] = '\0';
88958756Scg		(void) snprintf(path_copy, sizeof (path_copy), "%s/", path);
89058756Scg		(void) snprintf(rpath_copy, sizeof (rpath_copy), "%s/", rpath);
89170134Scg		if (strncmp(path_copy, rpath_copy,
89270134Scg		    min(strlen(path_copy), strlen(rpath_copy))) == 0) {
89370134Scg			/*
89470134Scg			 * TRANSLATION_NOTE
89570134Scg			 * zonepath is a literal that should not be translated.
89670134Scg			 */
89770134Scg			(void) fprintf(stderr, gettext("%s zonepath (%s) and "
89870134Scg			    "%s zonepath (%s) overlap.\n"),
89970134Scg			    target_zone, path, ze->zone_name, rpath);
90070134Scg			free(ze);
90170134Scg			return (Z_ERR);
90270134Scg		}
90370134Scg		free(ze);
90470134Scg	}
90570134Scg	endzoneent(cookie);
90675326Sgreid	return (Z_OK);
90775326Sgreid}
90875326Sgreid
90975326Sgreidstatic int
91075326Sgreidvalidate_zonepath(char *path, int cmd_num)
91175326Sgreid{
91275326Sgreid	int res;			/* result of last library/system call */
91375326Sgreid	boolean_t err = B_FALSE;	/* have we run into an error? */
91475326Sgreid	struct stat stbuf;
91575326Sgreid	struct statvfs64 vfsbuf;
91675326Sgreid	char rpath[MAXPATHLEN];		/* resolved path */
91775326Sgreid	char ppath[MAXPATHLEN];		/* parent path */
91875326Sgreid	char rppath[MAXPATHLEN];	/* resolved parent path */
91975326Sgreid	char rootpath[MAXPATHLEN];	/* root path */
92075326Sgreid	zone_state_t state;
92175326Sgreid
92275326Sgreid	if (path[0] != '/') {
92375326Sgreid		(void) fprintf(stderr,
92475326Sgreid		    gettext("%s is not an absolute path.\n"), path);
92575326Sgreid		return (Z_ERR);
92658756Scg	}
92758756Scg	if ((res = resolvepath(path, rpath, sizeof (rpath))) == -1) {
92858756Scg		if ((errno != ENOENT) ||
92958756Scg		    (cmd_num != CMD_VERIFY && cmd_num != CMD_INSTALL &&
93065644Scg		    cmd_num != CMD_CLONE && cmd_num != CMD_MOVE)) {
93175326Sgreid			zperror(path, B_FALSE);
93258756Scg			return (Z_ERR);
93358756Scg		}
93458756Scg		if (cmd_num == CMD_VERIFY) {
93558756Scg			/*
93658756Scg			 * TRANSLATION_NOTE
93758756Scg			 * zoneadm is a literal that should not be translated.
93858756Scg			 */
93982180Scg			(void) fprintf(stderr, gettext("WARNING: %s does not "
94058756Scg			    "exist, so it could not be verified.\nWhen "
94158756Scg			    "'zoneadm %s' is run, '%s' will try to create\n%s, "
94262483Scg			    "and '%s' will be tried again,\nbut the '%s' may "
943132236Stanimura			    "fail if:\nthe parent directory of %s is group- or "
94474763Scg			    "other-writable\nor\n%s overlaps with any other "
94562483Scg			    "installed zones.\n"), path,
94658756Scg			    cmd_to_str(CMD_INSTALL), cmd_to_str(CMD_INSTALL),
94770134Scg			    path, cmd_to_str(CMD_VERIFY),
94862483Scg			    cmd_to_str(CMD_VERIFY), path, path);
94958756Scg			return (Z_OK);
95058756Scg		}
95158756Scg		/*
95258756Scg		 * The zonepath is supposed to be mode 700 but its
95358756Scg		 * parent(s) 755.  So use 755 on the mkdirp() then
95458756Scg		 * chmod() the zonepath itself to 700.
95558756Scg		 */
95658756Scg		if (mkdirp(path, DEFAULT_DIR_MODE) < 0) {
95758756Scg			zperror(path, B_FALSE);
95858756Scg			return (Z_ERR);
95971932Scg		}
96071932Scg		/*
96171932Scg		 * If the chmod() fails, report the error, but might
96271932Scg		 * as well continue the verify procedure.
96371932Scg		 */
96471932Scg		if (chmod(path, S_IRWXU) != 0)
96558756Scg			zperror(path, B_FALSE);
96658756Scg		/*
96758756Scg		 * Since the mkdir() succeeded, we should not have to
96858756Scg		 * worry about a subsequent ENOENT, thus this should
96958756Scg		 * only recurse once.
97058756Scg		 */
97158756Scg		return (validate_zonepath(path, cmd_num));
97258756Scg	}
97358756Scg	rpath[res] = '\0';
97458756Scg	if (strcmp(path, rpath) != 0) {
975127135Snjl		errno = Z_RESOLVED_PATH;
97658756Scg		zperror(path, B_TRUE);
97758756Scg		return (Z_ERR);
97858756Scg	}
97958756Scg	if ((res = stat(rpath, &stbuf)) != 0) {
98058756Scg		zperror(rpath, B_FALSE);
98158756Scg		return (Z_ERR);
98258756Scg	}
98358756Scg	if (!S_ISDIR(stbuf.st_mode)) {
98458756Scg		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
98558756Scg		    rpath);
98658756Scg		return (Z_ERR);
98758756Scg	}
98858756Scg	if (strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) {
98958756Scg		(void) printf(gettext("WARNING: %s is on a temporary "
99058756Scg		    "file system.\n"), rpath);
99158756Scg	}
99258756Scg	if (crosscheck_zonepaths(rpath) != Z_OK)
99365644Scg		return (Z_ERR);
99465644Scg	/*
99565644Scg	 * Try to collect and report as many minor errors as possible
99665644Scg	 * before returning, so the user can learn everything that needs
99765644Scg	 * to be fixed up front.
99865644Scg	 */
99958756Scg	if (stbuf.st_uid != 0) {
100058756Scg		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
100158756Scg		    rpath);
100258756Scg		err = B_TRUE;
100365644Scg	}
100458756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rpath);
100558756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rpath);
100658756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rpath);
100758756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IRGRP, B_FALSE, rpath);
100858756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rpath);
100958756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IXGRP, B_FALSE, rpath);
101058756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IROTH, B_FALSE, rpath);
101182180Scg	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rpath);
101258756Scg	err |= bad_mode_bit(stbuf.st_mode, S_IXOTH, B_FALSE, rpath);
101358756Scg
101458756Scg	(void) snprintf(ppath, sizeof (ppath), "%s/..", path);
1015136410Snjl	if ((res = resolvepath(ppath, rppath, sizeof (rppath))) == -1) {
1016		zperror(ppath, B_FALSE);
1017		return (Z_ERR);
1018	}
1019	rppath[res] = '\0';
1020	if ((res = stat(rppath, &stbuf)) != 0) {
1021		zperror(rppath, B_FALSE);
1022		return (Z_ERR);
1023	}
1024	/* theoretically impossible */
1025	if (!S_ISDIR(stbuf.st_mode)) {
1026		(void) fprintf(stderr, gettext("%s is not a directory.\n"),
1027		    rppath);
1028		return (Z_ERR);
1029	}
1030	if (stbuf.st_uid != 0) {
1031		(void) fprintf(stderr, gettext("%s is not owned by root.\n"),
1032		    rppath);
1033		err = B_TRUE;
1034	}
1035	err |= bad_mode_bit(stbuf.st_mode, S_IRUSR, B_TRUE, rppath);
1036	err |= bad_mode_bit(stbuf.st_mode, S_IWUSR, B_TRUE, rppath);
1037	err |= bad_mode_bit(stbuf.st_mode, S_IXUSR, B_TRUE, rppath);
1038	err |= bad_mode_bit(stbuf.st_mode, S_IWGRP, B_FALSE, rppath);
1039	err |= bad_mode_bit(stbuf.st_mode, S_IWOTH, B_FALSE, rppath);
1040	if (strcmp(rpath, rppath) == 0) {
1041		(void) fprintf(stderr, gettext("%s is its own parent.\n"),
1042		    rppath);
1043		err = B_TRUE;
1044	}
1045
1046	if (statvfs64(rpath, &vfsbuf) != 0) {
1047		zperror(rpath, B_FALSE);
1048		return (Z_ERR);
1049	}
1050	if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
1051		/*
1052		 * TRANSLATION_NOTE
1053		 * Zonepath and NFS are literals that should not be translated.
1054		 */
1055		(void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
1056		    "mounted file system.\n"
1057		    "\tA local file system must be used.\n"), rpath);
1058		return (Z_ERR);
1059	}
1060	if (vfsbuf.f_flag & ST_NOSUID) {
1061		/*
1062		 * TRANSLATION_NOTE
1063		 * Zonepath and nosuid are literals that should not be
1064		 * translated.
1065		 */
1066		(void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
1067		    "file system.\n"), rpath);
1068		return (Z_ERR);
1069	}
1070
1071	if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
1072		errno = res;
1073		zperror2(target_zone, gettext("could not get state"));
1074		return (Z_ERR);
1075	}
1076	/*
1077	 * The existence of the root path is only bad in the configured state,
1078	 * as it is *supposed* to be there at the installed and later states.
1079	 * However, the root path is expected to be there if the zone is
1080	 * detached.
1081	 * State/command mismatches are caught earlier in verify_details().
1082	 */
1083	if (state == ZONE_STATE_CONFIGURED && cmd_num != CMD_ATTACH) {
1084		if (snprintf(rootpath, sizeof (rootpath), "%s/root", rpath) >=
1085		    sizeof (rootpath)) {
1086			/*
1087			 * TRANSLATION_NOTE
1088			 * Zonepath is a literal that should not be translated.
1089			 */
1090			(void) fprintf(stderr,
1091			    gettext("Zonepath %s is too long.\n"), rpath);
1092			return (Z_ERR);
1093		}
1094		if ((res = stat(rootpath, &stbuf)) == 0) {
1095			if (zonecfg_detached(rpath))
1096				(void) fprintf(stderr,
1097				    gettext("Cannot %s detached "
1098				    "zone.\nUse attach or remove %s "
1099				    "directory.\n"), cmd_to_str(cmd_num),
1100				    rpath);
1101			else
1102				(void) fprintf(stderr,
1103				    gettext("Rootpath %s exists; "
1104				    "remove or move aside prior to %s.\n"),
1105				    rootpath, cmd_to_str(cmd_num));
1106			return (Z_ERR);
1107		}
1108	}
1109
1110	return (err ? Z_ERR : Z_OK);
1111}
1112
1113/*
1114 * The following two routines implement a simple locking mechanism to
1115 * ensure that only one instance of zoneadm at a time is able to manipulate
1116 * a given zone.  The lock is built on top of an fcntl(2) lock of
1117 * [<altroot>]/var/run/zones/<zonename>.zoneadm.lock.  If a zoneadm instance
1118 * can grab that lock, it is allowed to manipulate the zone.
1119 *
1120 * Since zoneadm may call external applications which in turn invoke
1121 * zoneadm again, we introduce the notion of "lock inheritance".  Any
1122 * instance of zoneadm that has another instance in its ancestry is assumed
1123 * to be acting on behalf of the original zoneadm, and is thus allowed to
1124 * manipulate its zone.
1125 *
1126 * This inheritance is implemented via the _ZONEADM_LOCK_HELD environment
1127 * variable.  When zoneadm is granted a lock on its zone, this environment
1128 * variable is set to 1.  When it releases the lock, the variable is set to
1129 * 0.  Since a child process inherits its parent's environment, checking
1130 * the state of this variable indicates whether or not any ancestor owns
1131 * the lock.
1132 */
1133static void
1134release_lock_file(int lockfd)
1135{
1136	/*
1137	 * If we are cleaning up from a failed attempt to lock the zone for
1138	 * the first time, we might have a zone_lock_cnt of 0.  In that
1139	 * error case, we don't want to do anything but close the lock
1140	 * file.
1141	 */
1142	assert(zone_lock_cnt >= 0);
1143	if (zone_lock_cnt > 0) {
1144		assert(getenv(LOCK_ENV_VAR) != NULL);
1145		assert(atoi(getenv(LOCK_ENV_VAR)) == 1);
1146		if (--zone_lock_cnt > 0) {
1147			assert(lockfd == -1);
1148			return;
1149		}
1150		if (putenv(zoneadm_lock_not_held) != 0) {
1151			zperror(target_zone, B_TRUE);
1152			exit(Z_ERR);
1153		}
1154	}
1155	assert(lockfd >= 0);
1156	(void) close(lockfd);
1157}
1158
1159static int
1160grab_lock_file(const char *zone_name, int *lockfd)
1161{
1162	char pathbuf[PATH_MAX];
1163	struct flock flock;
1164
1165	/*
1166	 * If we already have the lock, we can skip this expensive song
1167	 * and dance.
1168	 */
1169	if (zone_lock_cnt > 0) {
1170		zone_lock_cnt++;
1171		*lockfd = -1;
1172		return (Z_OK);
1173	}
1174	assert(getenv(LOCK_ENV_VAR) != NULL);
1175	assert(atoi(getenv(LOCK_ENV_VAR)) == 0);
1176
1177	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s", zonecfg_get_root(),
1178	    ZONES_TMPDIR) >= sizeof (pathbuf)) {
1179		zerror(gettext("alternate root path is too long"));
1180		return (Z_ERR);
1181	}
1182	if (mkdir(pathbuf, S_IRWXU) < 0 && errno != EEXIST) {
1183		zerror(gettext("could not mkdir %s: %s"), pathbuf,
1184		    strerror(errno));
1185		return (Z_ERR);
1186	}
1187	(void) chmod(pathbuf, S_IRWXU);
1188
1189	/*
1190	 * One of these lock files is created for each zone (when needed).
1191	 * The lock files are not cleaned up (except on system reboot),
1192	 * but since there is only one per zone, there is no resource
1193	 * starvation issue.
1194	 */
1195	if (snprintf(pathbuf, sizeof (pathbuf), "%s%s/%s.zoneadm.lock",
1196	    zonecfg_get_root(), ZONES_TMPDIR, zone_name) >= sizeof (pathbuf)) {
1197		zerror(gettext("alternate root path is too long"));
1198		return (Z_ERR);
1199	}
1200	if ((*lockfd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
1201		zerror(gettext("could not open %s: %s"), pathbuf,
1202		    strerror(errno));
1203		return (Z_ERR);
1204	}
1205	/*
1206	 * Lock the file to synchronize with other zoneadmds
1207	 */
1208	flock.l_type = F_WRLCK;
1209	flock.l_whence = SEEK_SET;
1210	flock.l_start = (off_t)0;
1211	flock.l_len = (off_t)0;
1212	if ((fcntl(*lockfd, F_SETLKW, &flock) < 0) ||
1213	    (putenv(zoneadm_lock_held) != 0)) {
1214		zerror(gettext("unable to lock %s: %s"), pathbuf,
1215		    strerror(errno));
1216		release_lock_file(*lockfd);
1217		return (Z_ERR);
1218	}
1219	zone_lock_cnt = 1;
1220	return (Z_OK);
1221}
1222
1223static boolean_t
1224get_doorname(const char *zone_name, char *buffer)
1225{
1226	return (snprintf(buffer, PATH_MAX, "%s" ZONE_DOOR_PATH,
1227	    zonecfg_get_root(), zone_name) < PATH_MAX);
1228}
1229
1230/*
1231 * system daemons are not audited.  For the global zone, this occurs
1232 * "naturally" since init is started with the default audit
1233 * characteristics.  Since zoneadmd is a system daemon and it starts
1234 * init for a zone, it is necessary to clear out the audit
1235 * characteristics inherited from whomever started zoneadmd.  This is
1236 * indicated by the audit id, which is set from the ruid parameter of
1237 * adt_set_user(), below.
1238 */
1239
1240static void
1241prepare_audit_context()
1242{
1243	adt_session_data_t	*ah;
1244	char			*failure = gettext("audit failure: %s");
1245
1246	if (adt_start_session(&ah, NULL, 0)) {
1247		zerror(failure, strerror(errno));
1248		return;
1249	}
1250	if (adt_set_user(ah, ADT_NO_AUDIT, ADT_NO_AUDIT,
1251	    ADT_NO_AUDIT, ADT_NO_AUDIT, NULL, ADT_NEW)) {
1252		zerror(failure, strerror(errno));
1253		(void) adt_end_session(ah);
1254		return;
1255	}
1256	if (adt_set_proc(ah))
1257		zerror(failure, strerror(errno));
1258
1259	(void) adt_end_session(ah);
1260}
1261
1262static int
1263start_zoneadmd(const char *zone_name)
1264{
1265	char doorpath[PATH_MAX];
1266	pid_t child_pid;
1267	int error = Z_ERR;
1268	int doorfd, lockfd;
1269	struct door_info info;
1270
1271	if (!get_doorname(zone_name, doorpath))
1272		return (Z_ERR);
1273
1274	if (grab_lock_file(zone_name, &lockfd) != Z_OK)
1275		return (Z_ERR);
1276
1277	/*
1278	 * Now that we have the lock, re-confirm that the daemon is
1279	 * *not* up and working fine.  If it is still down, we have a green
1280	 * light to start it.
1281	 */
1282	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1283		if (errno != ENOENT) {
1284			zperror(doorpath, B_FALSE);
1285			goto out;
1286		}
1287	} else {
1288		if (door_info(doorfd, &info) == 0 &&
1289		    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1290			error = Z_OK;
1291			(void) close(doorfd);
1292			goto out;
1293		}
1294		(void) close(doorfd);
1295	}
1296
1297	if ((child_pid = fork()) == -1) {
1298		zperror(gettext("could not fork"), B_FALSE);
1299		goto out;
1300	} else if (child_pid == 0) {
1301		const char *argv[6], **ap;
1302
1303		/* child process */
1304		prepare_audit_context();
1305
1306		ap = argv;
1307		*ap++ = "zoneadmd";
1308		*ap++ = "-z";
1309		*ap++ = zone_name;
1310		if (zonecfg_in_alt_root()) {
1311			*ap++ = "-R";
1312			*ap++ = zonecfg_get_root();
1313		}
1314		*ap = NULL;
1315
1316		(void) execv("/usr/lib/zones/zoneadmd", (char * const *)argv);
1317		/*
1318		 * TRANSLATION_NOTE
1319		 * zoneadmd is a literal that should not be translated.
1320		 */
1321		zperror(gettext("could not exec zoneadmd"), B_FALSE);
1322		_exit(Z_ERR);
1323	} else {
1324		/* parent process */
1325		pid_t retval;
1326		int pstatus = 0;
1327
1328		do {
1329			retval = waitpid(child_pid, &pstatus, 0);
1330		} while (retval != child_pid);
1331		if (WIFSIGNALED(pstatus) || (WIFEXITED(pstatus) &&
1332		    WEXITSTATUS(pstatus) != 0)) {
1333			zerror(gettext("could not start %s"), "zoneadmd");
1334			goto out;
1335		}
1336	}
1337	error = Z_OK;
1338out:
1339	release_lock_file(lockfd);
1340	return (error);
1341}
1342
1343static int
1344ping_zoneadmd(const char *zone_name)
1345{
1346	char doorpath[PATH_MAX];
1347	int doorfd;
1348	struct door_info info;
1349
1350	if (!get_doorname(zone_name, doorpath))
1351		return (Z_ERR);
1352
1353	if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1354		return (Z_ERR);
1355	}
1356	if (door_info(doorfd, &info) == 0 &&
1357	    ((info.di_attributes & DOOR_REVOKED) == 0)) {
1358		(void) close(doorfd);
1359		return (Z_OK);
1360	}
1361	(void) close(doorfd);
1362	return (Z_ERR);
1363}
1364
1365static int
1366call_zoneadmd(const char *zone_name, zone_cmd_arg_t *arg)
1367{
1368	char doorpath[PATH_MAX];
1369	int doorfd, result;
1370	door_arg_t darg;
1371
1372	zoneid_t zoneid;
1373	uint64_t uniqid = 0;
1374
1375	zone_cmd_rval_t *rvalp;
1376	size_t rlen;
1377	char *cp, *errbuf;
1378
1379	rlen = getpagesize();
1380	if ((rvalp = malloc(rlen)) == NULL) {
1381		zerror(gettext("failed to allocate %lu bytes: %s"), rlen,
1382		    strerror(errno));
1383		return (-1);
1384	}
1385
1386	if ((zoneid = getzoneidbyname(zone_name)) != ZONE_ID_UNDEFINED) {
1387		(void) zone_getattr(zoneid, ZONE_ATTR_UNIQID, &uniqid,
1388		    sizeof (uniqid));
1389	}
1390	arg->uniqid = uniqid;
1391	(void) strlcpy(arg->locale, locale, sizeof (arg->locale));
1392	if (!get_doorname(zone_name, doorpath)) {
1393		zerror(gettext("alternate root path is too long"));
1394		free(rvalp);
1395		return (-1);
1396	}
1397
1398	/*
1399	 * Loop trying to start zoneadmd; if something goes seriously
1400	 * wrong we break out and fail.
1401	 */
1402	for (;;) {
1403		if (start_zoneadmd(zone_name) != Z_OK)
1404			break;
1405
1406		if ((doorfd = open(doorpath, O_RDONLY)) < 0) {
1407			zperror(gettext("failed to open zone door"), B_FALSE);
1408			break;
1409		}
1410
1411		darg.data_ptr = (char *)arg;
1412		darg.data_size = sizeof (*arg);
1413		darg.desc_ptr = NULL;
1414		darg.desc_num = 0;
1415		darg.rbuf = (char *)rvalp;
1416		darg.rsize = rlen;
1417		if (door_call(doorfd, &darg) != 0) {
1418			(void) close(doorfd);
1419			/*
1420			 * We'll get EBADF if the door has been revoked.
1421			 */
1422			if (errno != EBADF) {
1423				zperror(gettext("door_call failed"), B_FALSE);
1424				break;
1425			}
1426			continue;	/* take another lap */
1427		}
1428		(void) close(doorfd);
1429
1430		if (darg.data_size == 0) {
1431			/* Door server is going away; kick it again. */
1432			continue;
1433		}
1434
1435		errbuf = rvalp->errbuf;
1436		while (*errbuf != '\0') {
1437			/*
1438			 * Remove any newlines since zerror()
1439			 * will append one automatically.
1440			 */
1441			cp = strchr(errbuf, '\n');
1442			if (cp != NULL)
1443				*cp = '\0';
1444			zerror("%s", errbuf);
1445			if (cp == NULL)
1446				break;
1447			errbuf = cp + 1;
1448		}
1449		result = rvalp->rval == 0 ? 0 : -1;
1450		free(rvalp);
1451		return (result);
1452	}
1453
1454	free(rvalp);
1455	return (-1);
1456}
1457
1458static int
1459invoke_brand_handler(int cmd_num, char *argv[])
1460{
1461	zone_dochandle_t handle;
1462	int err;
1463
1464	if ((handle = zonecfg_init_handle()) == NULL) {
1465		zperror(cmd_to_str(cmd_num), B_TRUE);
1466		return (Z_ERR);
1467	}
1468	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
1469		errno = err;
1470		zperror(cmd_to_str(cmd_num), B_TRUE);
1471		zonecfg_fini_handle(handle);
1472		return (Z_ERR);
1473	}
1474	if (verify_brand(handle, cmd_num, argv) != Z_OK) {
1475		zonecfg_fini_handle(handle);
1476		return (Z_ERR);
1477	}
1478	zonecfg_fini_handle(handle);
1479	return (Z_OK);
1480}
1481
1482static int
1483ready_func(int argc, char *argv[])
1484{
1485	zone_cmd_arg_t zarg;
1486	int arg;
1487
1488	if (zonecfg_in_alt_root()) {
1489		zerror(gettext("cannot ready zone in alternate root"));
1490		return (Z_ERR);
1491	}
1492
1493	optind = 0;
1494	if ((arg = getopt(argc, argv, "?")) != EOF) {
1495		switch (arg) {
1496		case '?':
1497			sub_usage(SHELP_READY, CMD_READY);
1498			return (optopt == '?' ? Z_OK : Z_USAGE);
1499		default:
1500			sub_usage(SHELP_READY, CMD_READY);
1501			return (Z_USAGE);
1502		}
1503	}
1504	if (argc > optind) {
1505		sub_usage(SHELP_READY, CMD_READY);
1506		return (Z_USAGE);
1507	}
1508	if (sanity_check(target_zone, CMD_READY, B_FALSE, B_FALSE, B_FALSE)
1509	    != Z_OK)
1510		return (Z_ERR);
1511	if (verify_details(CMD_READY, argv) != Z_OK)
1512		return (Z_ERR);
1513
1514	zarg.cmd = Z_READY;
1515	if (call_zoneadmd(target_zone, &zarg) != 0) {
1516		zerror(gettext("call to %s failed"), "zoneadmd");
1517		return (Z_ERR);
1518	}
1519	return (Z_OK);
1520}
1521
1522static int
1523boot_func(int argc, char *argv[])
1524{
1525	zone_cmd_arg_t zarg;
1526	boolean_t force = B_FALSE;
1527	int arg;
1528
1529	if (zonecfg_in_alt_root()) {
1530		zerror(gettext("cannot boot zone in alternate root"));
1531		return (Z_ERR);
1532	}
1533
1534	zarg.bootbuf[0] = '\0';
1535
1536	/*
1537	 * The following getopt processes arguments to zone boot; that
1538	 * is to say, the [here] portion of the argument string:
1539	 *
1540	 *	zoneadm -z myzone boot [here] -- -v -m verbose
1541	 *
1542	 * Where [here] can either be nothing, -? (in which case we bail
1543	 * and print usage), -f (a private option to indicate that the
1544	 * boot operation should be 'forced'), or -s.  Support for -s is
1545	 * vestigal and obsolete, but is retained because it was a
1546	 * documented interface and there are known consumers including
1547	 * admin/install; the proper way to specify boot arguments like -s
1548	 * is:
1549	 *
1550	 *	zoneadm -z myzone boot -- -s -v -m verbose.
1551	 */
1552	optind = 0;
1553	while ((arg = getopt(argc, argv, "?fs")) != EOF) {
1554		switch (arg) {
1555		case '?':
1556			sub_usage(SHELP_BOOT, CMD_BOOT);
1557			return (optopt == '?' ? Z_OK : Z_USAGE);
1558		case 's':
1559			(void) strlcpy(zarg.bootbuf, "-s",
1560			    sizeof (zarg.bootbuf));
1561			break;
1562		case 'f':
1563			force = B_TRUE;
1564			break;
1565		default:
1566			sub_usage(SHELP_BOOT, CMD_BOOT);
1567			return (Z_USAGE);
1568		}
1569	}
1570
1571	for (; optind < argc; optind++) {
1572		if (strlcat(zarg.bootbuf, argv[optind],
1573		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
1574			zerror(gettext("Boot argument list too long"));
1575			return (Z_ERR);
1576		}
1577		if (optind < argc - 1)
1578			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
1579			    sizeof (zarg.bootbuf)) {
1580				zerror(gettext("Boot argument list too long"));
1581				return (Z_ERR);
1582			}
1583	}
1584	if (sanity_check(target_zone, CMD_BOOT, B_FALSE, B_FALSE, force)
1585	    != Z_OK)
1586		return (Z_ERR);
1587	if (verify_details(CMD_BOOT, argv) != Z_OK)
1588		return (Z_ERR);
1589	zarg.cmd = force ? Z_FORCEBOOT : Z_BOOT;
1590	if (call_zoneadmd(target_zone, &zarg) != 0) {
1591		zerror(gettext("call to %s failed"), "zoneadmd");
1592		return (Z_ERR);
1593	}
1594
1595	return (Z_OK);
1596}
1597
1598static void
1599fake_up_local_zone(zoneid_t zid, zone_entry_t *zeptr)
1600{
1601	ssize_t result;
1602	uuid_t uuid;
1603	FILE *fp;
1604	ushort_t flags;
1605
1606	(void) memset(zeptr, 0, sizeof (*zeptr));
1607
1608	zeptr->zid = zid;
1609
1610	/*
1611	 * Since we're looking up our own (non-global) zone name,
1612	 * we can be assured that it will succeed.
1613	 */
1614	result = getzonenamebyid(zid, zeptr->zname, sizeof (zeptr->zname));
1615	assert(result >= 0);
1616	if (zonecfg_is_scratch(zeptr->zname) &&
1617	    (fp = zonecfg_open_scratch("", B_FALSE)) != NULL) {
1618		(void) zonecfg_reverse_scratch(fp, zeptr->zname, zeptr->zname,
1619		    sizeof (zeptr->zname), NULL, 0);
1620		zonecfg_close_scratch(fp);
1621	}
1622
1623	if (is_system_labeled()) {
1624		(void) zone_getattr(zid, ZONE_ATTR_ROOT, zeptr->zroot,
1625		    sizeof (zeptr->zroot));
1626		(void) strlcpy(zeptr->zbrand, NATIVE_BRAND_NAME,
1627			    sizeof (zeptr->zbrand));
1628	} else {
1629		(void) strlcpy(zeptr->zroot, "/", sizeof (zeptr->zroot));
1630		(void) zone_getattr(zid, ZONE_ATTR_BRAND, zeptr->zbrand,
1631		    sizeof (zeptr->zbrand));
1632	}
1633
1634	zeptr->zstate_str = "running";
1635	if (zonecfg_get_uuid(zeptr->zname, uuid) == Z_OK &&
1636	    !uuid_is_null(uuid))
1637		uuid_unparse(uuid, zeptr->zuuid);
1638
1639	if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, sizeof (flags)) < 0) {
1640		zperror2(zeptr->zname, gettext("could not get zone flags"));
1641		exit(Z_ERR);
1642	}
1643	if (flags & ZF_NET_EXCL)
1644		zeptr->ziptype = ZS_EXCLUSIVE;
1645	else
1646		zeptr->ziptype = ZS_SHARED;
1647}
1648
1649static int
1650list_func(int argc, char *argv[])
1651{
1652	zone_entry_t *zentp, zent;
1653	int arg, retv;
1654	boolean_t output = B_FALSE, verbose = B_FALSE, parsable = B_FALSE;
1655	zone_state_t min_state = ZONE_STATE_RUNNING;
1656	zoneid_t zone_id = getzoneid();
1657
1658	if (target_zone == NULL) {
1659		/* all zones: default view to running but allow override */
1660		optind = 0;
1661		while ((arg = getopt(argc, argv, "?cipv")) != EOF) {
1662			switch (arg) {
1663			case '?':
1664				sub_usage(SHELP_LIST, CMD_LIST);
1665				return (optopt == '?' ? Z_OK : Z_USAGE);
1666				/*
1667				 * The 'i' and 'c' options are not mutually
1668				 * exclusive so if 'c' is given, then min_state
1669				 * is set to 0 (ZONE_STATE_CONFIGURED) which is
1670				 * the lowest possible state.  If 'i' is given,
1671				 * then min_state is set to be the lowest state
1672				 * so far.
1673				 */
1674			case 'c':
1675				min_state = ZONE_STATE_CONFIGURED;
1676				break;
1677			case 'i':
1678				min_state = min(ZONE_STATE_INSTALLED,
1679				    min_state);
1680
1681				break;
1682			case 'p':
1683				parsable = B_TRUE;
1684				break;
1685			case 'v':
1686				verbose = B_TRUE;
1687				break;
1688			default:
1689				sub_usage(SHELP_LIST, CMD_LIST);
1690				return (Z_USAGE);
1691			}
1692		}
1693		if (parsable && verbose) {
1694			zerror(gettext("%s -p and -v are mutually exclusive."),
1695			    cmd_to_str(CMD_LIST));
1696			return (Z_ERR);
1697		}
1698		if (zone_id == GLOBAL_ZONEID || is_system_labeled()) {
1699			retv = zone_print_list(min_state, verbose, parsable);
1700		} else {
1701			fake_up_local_zone(zone_id, &zent);
1702			retv = Z_OK;
1703			zone_print(&zent, verbose, parsable);
1704		}
1705		return (retv);
1706	}
1707
1708	/*
1709	 * Specific target zone: disallow -i/-c suboptions.
1710	 */
1711	optind = 0;
1712	while ((arg = getopt(argc, argv, "?pv")) != EOF) {
1713		switch (arg) {
1714		case '?':
1715			sub_usage(SHELP_LIST, CMD_LIST);
1716			return (optopt == '?' ? Z_OK : Z_USAGE);
1717		case 'p':
1718			parsable = B_TRUE;
1719			break;
1720		case 'v':
1721			verbose = B_TRUE;
1722			break;
1723		default:
1724			sub_usage(SHELP_LIST, CMD_LIST);
1725			return (Z_USAGE);
1726		}
1727	}
1728	if (parsable && verbose) {
1729		zerror(gettext("%s -p and -v are mutually exclusive."),
1730		    cmd_to_str(CMD_LIST));
1731		return (Z_ERR);
1732	}
1733	if (argc > optind) {
1734		sub_usage(SHELP_LIST, CMD_LIST);
1735		return (Z_USAGE);
1736	}
1737	if (zone_id != GLOBAL_ZONEID) {
1738		fake_up_local_zone(zone_id, &zent);
1739		/*
1740		 * main() will issue a Z_NO_ZONE error if it cannot get an
1741		 * id for target_zone, which in a non-global zone should
1742		 * happen for any zone name except `zonename`.  Thus we
1743		 * assert() that here but don't otherwise check.
1744		 */
1745		assert(strcmp(zent.zname, target_zone) == 0);
1746		zone_print(&zent, verbose, parsable);
1747		output = B_TRUE;
1748	} else if ((zentp = lookup_running_zone(target_zone)) != NULL) {
1749		zone_print(zentp, verbose, parsable);
1750		output = B_TRUE;
1751	} else if (lookup_zone_info(target_zone, ZONE_ID_UNDEFINED,
1752	    &zent) == Z_OK) {
1753		zone_print(&zent, verbose, parsable);
1754		output = B_TRUE;
1755	}
1756
1757	/*
1758	 * Invoke brand-specific handler. Note that we do this
1759	 * only if we're in the global zone, and target_zone is specified.
1760	 */
1761	if (zone_id == GLOBAL_ZONEID && target_zone != NULL)
1762		if (invoke_brand_handler(CMD_LIST, argv) != Z_OK)
1763			return (Z_ERR);
1764
1765	return (output ? Z_OK : Z_ERR);
1766}
1767
1768static void
1769sigterm(int sig)
1770{
1771	/*
1772	 * Ignore SIG{INT,TERM}, so we don't end up in an infinite loop,
1773	 * then propagate the signal to our process group.
1774	 */
1775	assert(sig == SIGINT || sig == SIGTERM);
1776	(void) sigset(SIGINT, SIG_IGN);
1777	(void) sigset(SIGTERM, SIG_IGN);
1778	(void) kill(0, sig);
1779	child_killed = B_TRUE;
1780}
1781
1782static int
1783do_subproc(char *cmdbuf)
1784{
1785	char inbuf[1024];	/* arbitrary large amount */
1786	FILE *file;
1787
1788	do_subproc_cnt++;
1789	child_killed = B_FALSE;
1790	/*
1791	 * We use popen(3c) to launch child processes for [un]install;
1792	 * this library call does not return a PID, so we have to kill
1793	 * the whole process group.  To avoid killing our parent, we
1794	 * become a process group leader here.  But doing so can wreak
1795	 * havoc with reading from stdin when launched by a non-job-control
1796	 * shell, so we close stdin and reopen it as /dev/null first.
1797	 */
1798	(void) close(STDIN_FILENO);
1799	(void) openat(STDIN_FILENO, "/dev/null", O_RDONLY);
1800	if (!zoneadm_is_nested)
1801		(void) setpgid(0, 0);
1802	(void) sigset(SIGINT, sigterm);
1803	(void) sigset(SIGTERM, sigterm);
1804	file = popen(cmdbuf, "r");
1805	for (;;) {
1806		if (child_killed || fgets(inbuf, sizeof (inbuf), file) == NULL)
1807			break;
1808		(void) fputs(inbuf, stdout);
1809	}
1810	(void) sigset(SIGINT, SIG_DFL);
1811	(void) sigset(SIGTERM, SIG_DFL);
1812	return (pclose(file));
1813}
1814
1815static int
1816do_subproc_interactive(char *cmdbuf)
1817{
1818	void (*saveint)(int);
1819	void (*saveterm)(int);
1820	void (*savequit)(int);
1821	void (*savehup)(int);
1822	int pid, child, status;
1823
1824	/*
1825	 * do_subproc() links stdin to /dev/null, which would break any
1826	 * interactive subprocess we try to launch here.  Similarly, we
1827	 * can't have been launched as a subprocess ourselves.
1828	 */
1829	assert(do_subproc_cnt == 0 && !zoneadm_is_nested);
1830
1831	if ((child = vfork()) == 0) {
1832		(void) execl("/bin/sh", "sh", "-c", cmdbuf, (char *)NULL);
1833	}
1834
1835	if (child == -1)
1836		return (-1);
1837
1838	saveint = sigset(SIGINT, SIG_IGN);
1839	saveterm = sigset(SIGTERM, SIG_IGN);
1840	savequit = sigset(SIGQUIT, SIG_IGN);
1841	savehup = sigset(SIGHUP, SIG_IGN);
1842
1843	while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
1844		;
1845
1846	(void) sigset(SIGINT, saveint);
1847	(void) sigset(SIGTERM, saveterm);
1848	(void) sigset(SIGQUIT, savequit);
1849	(void) sigset(SIGHUP, savehup);
1850
1851	return (pid == -1 ? -1 : status);
1852}
1853
1854static int
1855subproc_status(const char *cmd, int status, boolean_t verbose_failure)
1856{
1857	if (WIFEXITED(status)) {
1858		int exit_code = WEXITSTATUS(status);
1859
1860		if ((verbose_failure) && (exit_code != ZONE_SUBPROC_OK))
1861			zerror(gettext("'%s' failed with exit code %d."), cmd,
1862			    exit_code);
1863
1864		return (exit_code);
1865	} else if (WIFSIGNALED(status)) {
1866		int signal = WTERMSIG(status);
1867		char sigstr[SIG2STR_MAX];
1868
1869		if (sig2str(signal, sigstr) == 0) {
1870			zerror(gettext("'%s' terminated by signal SIG%s."), cmd,
1871			    sigstr);
1872		} else {
1873			zerror(gettext("'%s' terminated by an unknown signal."),
1874			    cmd);
1875		}
1876	} else {
1877		zerror(gettext("'%s' failed for unknown reasons."), cmd);
1878	}
1879
1880	/*
1881	 * Assume a subprocess that died due to a signal or an unknown error
1882	 * should be considered an exit code of ZONE_SUBPROC_FATAL, as the
1883	 * user will likely need to do some manual cleanup.
1884	 */
1885	return (ZONE_SUBPROC_FATAL);
1886}
1887
1888/*
1889 * Various sanity checks; make sure:
1890 * 1. We're in the global zone.
1891 * 2. The calling user has sufficient privilege.
1892 * 3. The target zone is neither the global zone nor anything starting with
1893 *    "SUNW".
1894 * 4a. If we're looking for a 'not running' (i.e., configured or installed)
1895 *     zone, the name service knows about it.
1896 * 4b. For some operations which expect a zone not to be running, that it is
1897 *     not already running (or ready).
1898 */
1899static int
1900sanity_check(char *zone, int cmd_num, boolean_t running,
1901    boolean_t unsafe_when_running, boolean_t force)
1902{
1903	zone_entry_t *zent;
1904	priv_set_t *privset;
1905	zone_state_t state, min_state;
1906	char kernzone[ZONENAME_MAX];
1907	FILE *fp;
1908
1909	if (getzoneid() != GLOBAL_ZONEID) {
1910		switch (cmd_num) {
1911		case CMD_HALT:
1912			zerror(gettext("use %s to %s this zone."), "halt(1M)",
1913			    cmd_to_str(cmd_num));
1914			break;
1915		case CMD_REBOOT:
1916			zerror(gettext("use %s to %s this zone."),
1917			    "reboot(1M)", cmd_to_str(cmd_num));
1918			break;
1919		default:
1920			zerror(gettext("must be in the global zone to %s a "
1921			    "zone."), cmd_to_str(cmd_num));
1922			break;
1923		}
1924		return (Z_ERR);
1925	}
1926
1927	if ((privset = priv_allocset()) == NULL) {
1928		zerror(gettext("%s failed"), "priv_allocset");
1929		return (Z_ERR);
1930	}
1931
1932	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1933		zerror(gettext("%s failed"), "getppriv");
1934		priv_freeset(privset);
1935		return (Z_ERR);
1936	}
1937
1938	if (priv_isfullset(privset) == B_FALSE) {
1939		zerror(gettext("only a privileged user may %s a zone."),
1940		    cmd_to_str(cmd_num));
1941		priv_freeset(privset);
1942		return (Z_ERR);
1943	}
1944	priv_freeset(privset);
1945
1946	if (zone == NULL) {
1947		zerror(gettext("no zone specified"));
1948		return (Z_ERR);
1949	}
1950
1951	if (strcmp(zone, GLOBAL_ZONENAME) == 0) {
1952		zerror(gettext("%s operation is invalid for the global zone."),
1953		    cmd_to_str(cmd_num));
1954		return (Z_ERR);
1955	}
1956
1957	if (strncmp(zone, "SUNW", 4) == 0) {
1958		zerror(gettext("%s operation is invalid for zones starting "
1959		    "with SUNW."), cmd_to_str(cmd_num));
1960		return (Z_ERR);
1961	}
1962
1963	if (!is_native_zone && cmd_num == CMD_MOUNT) {
1964		zerror(gettext("%s operation is invalid for branded zones."),
1965		    cmd_to_str(cmd_num));
1966			return (Z_ERR);
1967	}
1968
1969	if (!zonecfg_in_alt_root()) {
1970		zent = lookup_running_zone(zone);
1971	} else if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
1972		zent = NULL;
1973	} else {
1974		if (zonecfg_find_scratch(fp, zone, zonecfg_get_root(),
1975		    kernzone, sizeof (kernzone)) == 0)
1976			zent = lookup_running_zone(kernzone);
1977		else
1978			zent = NULL;
1979		zonecfg_close_scratch(fp);
1980	}
1981
1982	/*
1983	 * Look up from the kernel for 'running' zones.
1984	 */
1985	if (running && !force) {
1986		if (zent == NULL) {
1987			zerror(gettext("not running"));
1988			return (Z_ERR);
1989		}
1990	} else {
1991		int err;
1992
1993		if (unsafe_when_running && zent != NULL) {
1994			/* check whether the zone is ready or running */
1995			if ((err = zone_get_state(zent->zname,
1996			    &zent->zstate_num)) != Z_OK) {
1997				errno = err;
1998				zperror2(zent->zname,
1999				    gettext("could not get state"));
2000				/* can't tell, so hedge */
2001				zent->zstate_str = "ready/running";
2002			} else {
2003				zent->zstate_str =
2004				    zone_state_str(zent->zstate_num);
2005			}
2006			zerror(gettext("%s operation is invalid for %s zones."),
2007			    cmd_to_str(cmd_num), zent->zstate_str);
2008			return (Z_ERR);
2009		}
2010		if ((err = zone_get_state(zone, &state)) != Z_OK) {
2011			errno = err;
2012			zperror2(zone, gettext("could not get state"));
2013			return (Z_ERR);
2014		}
2015		switch (cmd_num) {
2016		case CMD_UNINSTALL:
2017			if (state == ZONE_STATE_CONFIGURED) {
2018				zerror(gettext("is already in state '%s'."),
2019				    zone_state_str(ZONE_STATE_CONFIGURED));
2020				return (Z_ERR);
2021			}
2022			break;
2023		case CMD_ATTACH:
2024		case CMD_CLONE:
2025		case CMD_INSTALL:
2026			if (state == ZONE_STATE_INSTALLED) {
2027				zerror(gettext("is already %s."),
2028				    zone_state_str(ZONE_STATE_INSTALLED));
2029				return (Z_ERR);
2030			} else if (state == ZONE_STATE_INCOMPLETE) {
2031				zerror(gettext("zone is %s; %s required."),
2032				    zone_state_str(ZONE_STATE_INCOMPLETE),
2033				    cmd_to_str(CMD_UNINSTALL));
2034				return (Z_ERR);
2035			}
2036			break;
2037		case CMD_DETACH:
2038		case CMD_MOVE:
2039		case CMD_READY:
2040		case CMD_BOOT:
2041		case CMD_MOUNT:
2042		case CMD_MARK:
2043			if ((cmd_num == CMD_BOOT || cmd_num == CMD_MOUNT) &&
2044			    force)
2045				min_state = ZONE_STATE_INCOMPLETE;
2046			else
2047				min_state = ZONE_STATE_INSTALLED;
2048
2049			if (force && cmd_num == CMD_BOOT && is_native_zone) {
2050				zerror(gettext("Only branded zones may be "
2051				    "force-booted."));
2052				return (Z_ERR);
2053			}
2054
2055			if (state < min_state) {
2056				zerror(gettext("must be %s before %s."),
2057				    zone_state_str(min_state),
2058				    cmd_to_str(cmd_num));
2059				return (Z_ERR);
2060			}
2061			break;
2062		case CMD_VERIFY:
2063			if (state == ZONE_STATE_INCOMPLETE) {
2064				zerror(gettext("zone is %s; %s required."),
2065				    zone_state_str(ZONE_STATE_INCOMPLETE),
2066				    cmd_to_str(CMD_UNINSTALL));
2067				return (Z_ERR);
2068			}
2069			break;
2070		case CMD_UNMOUNT:
2071			if (state != ZONE_STATE_MOUNTED) {
2072				zerror(gettext("must be %s before %s."),
2073				    zone_state_str(ZONE_STATE_MOUNTED),
2074				    cmd_to_str(cmd_num));
2075				return (Z_ERR);
2076			}
2077			break;
2078		}
2079	}
2080	return (Z_OK);
2081}
2082
2083static int
2084halt_func(int argc, char *argv[])
2085{
2086	zone_cmd_arg_t zarg;
2087	int arg;
2088
2089	if (zonecfg_in_alt_root()) {
2090		zerror(gettext("cannot halt zone in alternate root"));
2091		return (Z_ERR);
2092	}
2093
2094	optind = 0;
2095	if ((arg = getopt(argc, argv, "?")) != EOF) {
2096		switch (arg) {
2097		case '?':
2098			sub_usage(SHELP_HALT, CMD_HALT);
2099			return (optopt == '?' ? Z_OK : Z_USAGE);
2100		default:
2101			sub_usage(SHELP_HALT, CMD_HALT);
2102			return (Z_USAGE);
2103		}
2104	}
2105	if (argc > optind) {
2106		sub_usage(SHELP_HALT, CMD_HALT);
2107		return (Z_USAGE);
2108	}
2109	/*
2110	 * zoneadmd should be the one to decide whether or not to proceed,
2111	 * so even though it seems that the fourth parameter below should
2112	 * perhaps be B_TRUE, it really shouldn't be.
2113	 */
2114	if (sanity_check(target_zone, CMD_HALT, B_FALSE, B_FALSE, B_FALSE)
2115	    != Z_OK)
2116		return (Z_ERR);
2117
2118	/*
2119	 * Invoke brand-specific handler.
2120	 */
2121	if (invoke_brand_handler(CMD_HALT, argv) != Z_OK)
2122		return (Z_ERR);
2123
2124	zarg.cmd = Z_HALT;
2125	return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2126}
2127
2128static int
2129reboot_func(int argc, char *argv[])
2130{
2131	zone_cmd_arg_t zarg;
2132	int arg;
2133
2134	if (zonecfg_in_alt_root()) {
2135		zerror(gettext("cannot reboot zone in alternate root"));
2136		return (Z_ERR);
2137	}
2138
2139	optind = 0;
2140	if ((arg = getopt(argc, argv, "?")) != EOF) {
2141		switch (arg) {
2142		case '?':
2143			sub_usage(SHELP_REBOOT, CMD_REBOOT);
2144			return (optopt == '?' ? Z_OK : Z_USAGE);
2145		default:
2146			sub_usage(SHELP_REBOOT, CMD_REBOOT);
2147			return (Z_USAGE);
2148		}
2149	}
2150
2151	zarg.bootbuf[0] = '\0';
2152	for (; optind < argc; optind++) {
2153		if (strlcat(zarg.bootbuf, argv[optind],
2154		    sizeof (zarg.bootbuf)) >= sizeof (zarg.bootbuf)) {
2155			zerror(gettext("Boot argument list too long"));
2156			return (Z_ERR);
2157		}
2158		if (optind < argc - 1)
2159			if (strlcat(zarg.bootbuf, " ", sizeof (zarg.bootbuf)) >=
2160			    sizeof (zarg.bootbuf)) {
2161				zerror(gettext("Boot argument list too long"));
2162				return (Z_ERR);
2163			}
2164	}
2165
2166
2167	/*
2168	 * zoneadmd should be the one to decide whether or not to proceed,
2169	 * so even though it seems that the fourth parameter below should
2170	 * perhaps be B_TRUE, it really shouldn't be.
2171	 */
2172	if (sanity_check(target_zone, CMD_REBOOT, B_TRUE, B_FALSE, B_FALSE)
2173	    != Z_OK)
2174		return (Z_ERR);
2175	if (verify_details(CMD_REBOOT, argv) != Z_OK)
2176		return (Z_ERR);
2177
2178	zarg.cmd = Z_REBOOT;
2179	return ((call_zoneadmd(target_zone, &zarg) == 0) ? Z_OK : Z_ERR);
2180}
2181
2182static int
2183verify_brand(zone_dochandle_t handle, int cmd_num, char *argv[])
2184{
2185	char cmdbuf[MAXPATHLEN];
2186	int err;
2187	char zonepath[MAXPATHLEN];
2188	brand_handle_t bh = NULL;
2189	int status, i;
2190
2191	/*
2192	 * Fetch the verify command from the brand configuration.
2193	 * "exec" the command so that the returned status is that of
2194	 * the command and not the shell.
2195	 */
2196	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2197	    Z_OK) {
2198		errno = err;
2199		zperror(cmd_to_str(cmd_num), B_TRUE);
2200		return (Z_ERR);
2201	}
2202	if ((bh = brand_open(target_brand)) == NULL) {
2203		zerror(gettext("missing or invalid brand"));
2204		return (Z_ERR);
2205	}
2206
2207	/*
2208	 * If the brand has its own verification routine, execute it now.
2209	 * The verification routine validates the intended zoneadm
2210	 * operation for the specific brand. The zoneadm subcommand and
2211	 * all its arguments are passed to the routine.
2212	 */
2213	(void) strcpy(cmdbuf, EXEC_PREFIX);
2214	err = brand_get_verify_adm(bh, target_zone, zonepath,
2215	    cmdbuf + EXEC_LEN, sizeof (cmdbuf) - EXEC_LEN, 0, NULL);
2216	brand_close(bh);
2217	if (err != 0)
2218		return (Z_BRAND_ERROR);
2219	if (strlen(cmdbuf) <= EXEC_LEN)
2220		return (Z_OK);
2221
2222	if (strlcat(cmdbuf, cmd_to_str(cmd_num),
2223	    sizeof (cmdbuf)) >= sizeof (cmdbuf))
2224		return (Z_ERR);
2225
2226	/* Build the argv string */
2227	i = 0;
2228	while (argv[i] != NULL) {
2229		if ((strlcat(cmdbuf, " ",
2230		    sizeof (cmdbuf)) >= sizeof (cmdbuf)) ||
2231		    (strlcat(cmdbuf, argv[i++],
2232		    sizeof (cmdbuf)) >= sizeof (cmdbuf)))
2233			return (Z_ERR);
2234	}
2235
2236	status = do_subproc_interactive(cmdbuf);
2237	err = subproc_status(gettext("brand-specific verification"),
2238	    status, B_FALSE);
2239
2240	return ((err == ZONE_SUBPROC_OK) ? Z_OK : Z_BRAND_ERROR);
2241}
2242
2243static int
2244verify_rctls(zone_dochandle_t handle)
2245{
2246	struct zone_rctltab rctltab;
2247	size_t rbs = rctlblk_size();
2248	rctlblk_t *rctlblk;
2249	int error = Z_INVAL;
2250
2251	if ((rctlblk = malloc(rbs)) == NULL) {
2252		zerror(gettext("failed to allocate %lu bytes: %s"), rbs,
2253		    strerror(errno));
2254		return (Z_NOMEM);
2255	}
2256
2257	if (zonecfg_setrctlent(handle) != Z_OK) {
2258		zerror(gettext("zonecfg_setrctlent failed"));
2259		free(rctlblk);
2260		return (error);
2261	}
2262
2263	rctltab.zone_rctl_valptr = NULL;
2264	while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
2265		struct zone_rctlvaltab *rctlval;
2266		const char *name = rctltab.zone_rctl_name;
2267
2268		if (!zonecfg_is_rctl(name)) {
2269			zerror(gettext("WARNING: Ignoring unrecognized rctl "
2270			    "'%s'."),  name);
2271			zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2272			rctltab.zone_rctl_valptr = NULL;
2273			continue;
2274		}
2275
2276		for (rctlval = rctltab.zone_rctl_valptr; rctlval != NULL;
2277		    rctlval = rctlval->zone_rctlval_next) {
2278			if (zonecfg_construct_rctlblk(rctlval, rctlblk)
2279			    != Z_OK) {
2280				zerror(gettext("invalid rctl value: "
2281				    "(priv=%s,limit=%s,action%s)"),
2282				    rctlval->zone_rctlval_priv,
2283				    rctlval->zone_rctlval_limit,
2284				    rctlval->zone_rctlval_action);
2285				goto out;
2286			}
2287			if (!zonecfg_valid_rctl(name, rctlblk)) {
2288				zerror(gettext("(priv=%s,limit=%s,action=%s) "
2289				    "is not a valid value for rctl '%s'"),
2290				    rctlval->zone_rctlval_priv,
2291				    rctlval->zone_rctlval_limit,
2292				    rctlval->zone_rctlval_action,
2293				    name);
2294				goto out;
2295			}
2296		}
2297		zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2298	}
2299	rctltab.zone_rctl_valptr = NULL;
2300	error = Z_OK;
2301out:
2302	zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
2303	(void) zonecfg_endrctlent(handle);
2304	free(rctlblk);
2305	return (error);
2306}
2307
2308static int
2309verify_pool(zone_dochandle_t handle)
2310{
2311	char poolname[MAXPATHLEN];
2312	pool_conf_t *poolconf;
2313	pool_t *pool;
2314	int status;
2315	int error;
2316
2317	/*
2318	 * This ends up being very similar to the check done in zoneadmd.
2319	 */
2320	error = zonecfg_get_pool(handle, poolname, sizeof (poolname));
2321	if (error == Z_NO_ENTRY || (error == Z_OK && strlen(poolname) == 0)) {
2322		/*
2323		 * No pool specified.
2324		 */
2325		return (0);
2326	}
2327	if (error != Z_OK) {
2328		zperror(gettext("Unable to retrieve pool name from "
2329		    "configuration"), B_TRUE);
2330		return (error);
2331	}
2332	/*
2333	 * Don't do anything if pools aren't enabled.
2334	 */
2335	if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) {
2336		zerror(gettext("WARNING: pools facility not active; "
2337		    "zone will not be bound to pool '%s'."), poolname);
2338		return (Z_OK);
2339	}
2340	/*
2341	 * Try to provide a sane error message if the requested pool doesn't
2342	 * exist.  It isn't clear that pools-related failures should
2343	 * necessarily translate to a failure to verify the zone configuration,
2344	 * hence they are not considered errors.
2345	 */
2346	if ((poolconf = pool_conf_alloc()) == NULL) {
2347		zerror(gettext("WARNING: pool_conf_alloc failed; "
2348		    "using default pool"));
2349		return (Z_OK);
2350	}
2351	if (pool_conf_open(poolconf, pool_dynamic_location(), PO_RDONLY) !=
2352	    PO_SUCCESS) {
2353		zerror(gettext("WARNING: pool_conf_open failed; "
2354		    "using default pool"));
2355		pool_conf_free(poolconf);
2356		return (Z_OK);
2357	}
2358	pool = pool_get_pool(poolconf, poolname);
2359	(void) pool_conf_close(poolconf);
2360	pool_conf_free(poolconf);
2361	if (pool == NULL) {
2362		zerror(gettext("WARNING: pool '%s' not found. "
2363		    "using default pool"), poolname);
2364	}
2365
2366	return (Z_OK);
2367}
2368
2369static int
2370verify_ipd(zone_dochandle_t handle)
2371{
2372	int return_code = Z_OK;
2373	struct zone_fstab fstab;
2374	struct stat st;
2375	char specdir[MAXPATHLEN];
2376
2377	if (zonecfg_setipdent(handle) != Z_OK) {
2378		/*
2379		 * TRANSLATION_NOTE
2380		 * inherit-pkg-dirs is a literal that should not be translated.
2381		 */
2382		(void) fprintf(stderr, gettext("could not verify "
2383		    "inherit-pkg-dirs: unable to enumerate mounts\n"));
2384		return (Z_ERR);
2385	}
2386	while (zonecfg_getipdent(handle, &fstab) == Z_OK) {
2387		/*
2388		 * Verify fs_dir exists.
2389		 */
2390		(void) snprintf(specdir, sizeof (specdir), "%s%s",
2391		    zonecfg_get_root(), fstab.zone_fs_dir);
2392		if (stat(specdir, &st) != 0) {
2393			/*
2394			 * TRANSLATION_NOTE
2395			 * inherit-pkg-dir is a literal that should not be
2396			 * translated.
2397			 */
2398			(void) fprintf(stderr, gettext("could not verify "
2399			    "inherit-pkg-dir %s: %s\n"),
2400			    fstab.zone_fs_dir, strerror(errno));
2401			return_code = Z_ERR;
2402		}
2403		if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2404			/*
2405			 * TRANSLATION_NOTE
2406			 * inherit-pkg-dir and NFS are literals that should
2407			 * not be translated.
2408			 */
2409			(void) fprintf(stderr, gettext("cannot verify "
2410			    "inherit-pkg-dir %s: NFS mounted file system.\n"
2411			    "\tA local file system must be used.\n"),
2412			    fstab.zone_fs_dir);
2413			return_code = Z_ERR;
2414		}
2415	}
2416	(void) zonecfg_endipdent(handle);
2417
2418	return (return_code);
2419}
2420
2421/*
2422 * Verify that the special device/file system exists and is valid.
2423 */
2424static int
2425verify_fs_special(struct zone_fstab *fstab)
2426{
2427	struct stat st;
2428
2429	/*
2430	 * This validation is really intended for standard zone administration.
2431	 * If we are in a mini-root or some other upgrade situation where
2432	 * we are using the scratch zone, just by-pass this.
2433	 */
2434	if (zonecfg_in_alt_root())
2435		return (Z_OK);
2436
2437	if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
2438		return (verify_fs_zfs(fstab));
2439
2440	if (stat(fstab->zone_fs_special, &st) != 0) {
2441		(void) fprintf(stderr, gettext("could not verify fs "
2442		    "%s: could not access %s: %s\n"), fstab->zone_fs_dir,
2443		    fstab->zone_fs_special, strerror(errno));
2444		return (Z_ERR);
2445	}
2446
2447	if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2448		/*
2449		 * TRANSLATION_NOTE
2450		 * fs and NFS are literals that should
2451		 * not be translated.
2452		 */
2453		(void) fprintf(stderr, gettext("cannot verify "
2454		    "fs %s: NFS mounted file system.\n"
2455		    "\tA local file system must be used.\n"),
2456		    fstab->zone_fs_special);
2457		return (Z_ERR);
2458	}
2459
2460	return (Z_OK);
2461}
2462
2463static int
2464verify_filesystems(zone_dochandle_t handle)
2465{
2466	int return_code = Z_OK;
2467	struct zone_fstab fstab;
2468	char cmdbuf[MAXPATHLEN];
2469	struct stat st;
2470
2471	/*
2472	 * No need to verify inherit-pkg-dir fs types, as their type is
2473	 * implicitly lofs, which is known.  Therefore, the types are only
2474	 * verified for regular file systems below.
2475	 *
2476	 * Since the actual mount point is not known until the dependent mounts
2477	 * are performed, we don't attempt any path validation here: that will
2478	 * happen later when zoneadmd actually does the mounts.
2479	 */
2480	if (zonecfg_setfsent(handle) != Z_OK) {
2481		(void) fprintf(stderr, gettext("could not verify file systems: "
2482		    "unable to enumerate mounts\n"));
2483		return (Z_ERR);
2484	}
2485	while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2486		if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2487			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2488			    "type %s is not allowed.\n"), fstab.zone_fs_dir,
2489			    fstab.zone_fs_type);
2490			return_code = Z_ERR;
2491			goto next_fs;
2492		}
2493		/*
2494		 * Verify /usr/lib/fs/<fstype>/mount exists.
2495		 */
2496		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/mount",
2497		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2498			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2499			    "type %s is too long.\n"), fstab.zone_fs_dir,
2500			    fstab.zone_fs_type);
2501			return_code = Z_ERR;
2502			goto next_fs;
2503		}
2504		if (stat(cmdbuf, &st) != 0) {
2505			(void) fprintf(stderr, gettext("could not verify fs "
2506			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2507			    cmdbuf, strerror(errno));
2508			return_code = Z_ERR;
2509			goto next_fs;
2510		}
2511		if (!S_ISREG(st.st_mode)) {
2512			(void) fprintf(stderr, gettext("could not verify fs "
2513			    "%s: %s is not a regular file\n"),
2514			    fstab.zone_fs_dir, cmdbuf);
2515			return_code = Z_ERR;
2516			goto next_fs;
2517		}
2518		/*
2519		 * Verify /usr/lib/fs/<fstype>/fsck exists iff zone_fs_raw is
2520		 * set.
2521		 */
2522		if (snprintf(cmdbuf, sizeof (cmdbuf), "/usr/lib/fs/%s/fsck",
2523		    fstab.zone_fs_type) > sizeof (cmdbuf)) {
2524			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2525			    "type %s is too long.\n"), fstab.zone_fs_dir,
2526			    fstab.zone_fs_type);
2527			return_code = Z_ERR;
2528			goto next_fs;
2529		}
2530		if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) {
2531			(void) fprintf(stderr, gettext("could not verify fs "
2532			    "%s: must specify 'raw' device for %s "
2533			    "file systems\n"),
2534			    fstab.zone_fs_dir, fstab.zone_fs_type);
2535			return_code = Z_ERR;
2536			goto next_fs;
2537		}
2538		if (fstab.zone_fs_raw[0] != '\0' &&
2539		    (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2540			(void) fprintf(stderr, gettext("cannot verify fs %s: "
2541			    "'raw' device specified but "
2542			    "no fsck executable exists for %s\n"),
2543			    fstab.zone_fs_dir, fstab.zone_fs_type);
2544			return_code = Z_ERR;
2545			goto next_fs;
2546		}
2547
2548		/* Verify fs_special. */
2549		if ((return_code = verify_fs_special(&fstab)) != Z_OK)
2550			goto next_fs;
2551
2552		/* Verify fs_raw. */
2553		if (fstab.zone_fs_raw[0] != '\0' &&
2554		    stat(fstab.zone_fs_raw, &st) != 0) {
2555			/*
2556			 * TRANSLATION_NOTE
2557			 * fs is a literal that should not be translated.
2558			 */
2559			(void) fprintf(stderr, gettext("could not verify fs "
2560			    "%s: could not access %s: %s\n"), fstab.zone_fs_dir,
2561			    fstab.zone_fs_raw, strerror(errno));
2562			return_code = Z_ERR;
2563			goto next_fs;
2564		}
2565next_fs:
2566		zonecfg_free_fs_option_list(fstab.zone_fs_options);
2567	}
2568	(void) zonecfg_endfsent(handle);
2569
2570	return (return_code);
2571}
2572
2573static int
2574verify_limitpriv(zone_dochandle_t handle)
2575{
2576	char *privname = NULL;
2577	int err;
2578	priv_set_t *privs;
2579
2580	if ((privs = priv_allocset()) == NULL) {
2581		zperror(gettext("failed to allocate privilege set"), B_FALSE);
2582		return (Z_NOMEM);
2583	}
2584	err = zonecfg_get_privset(handle, privs, &privname);
2585	switch (err) {
2586	case Z_OK:
2587		break;
2588	case Z_PRIV_PROHIBITED:
2589		(void) fprintf(stderr, gettext("privilege \"%s\" is not "
2590		    "permitted within the zone's privilege set\n"), privname);
2591		break;
2592	case Z_PRIV_REQUIRED:
2593		(void) fprintf(stderr, gettext("required privilege \"%s\" is "
2594		    "missing from the zone's privilege set\n"), privname);
2595		break;
2596	case Z_PRIV_UNKNOWN:
2597		(void) fprintf(stderr, gettext("unknown privilege \"%s\" "
2598		    "specified in the zone's privilege set\n"), privname);
2599		break;
2600	default:
2601		zperror(
2602		    gettext("failed to determine the zone's privilege set"),
2603		    B_TRUE);
2604		break;
2605	}
2606	free(privname);
2607	priv_freeset(privs);
2608	return (err);
2609}
2610
2611static void
2612free_local_netifs(int if_cnt, struct net_if **if_list)
2613{
2614	int		i;
2615
2616	for (i = 0; i < if_cnt; i++) {
2617		free(if_list[i]->name);
2618		free(if_list[i]);
2619	}
2620	free(if_list);
2621}
2622
2623/*
2624 * Get a list of the network interfaces, along with their address families,
2625 * that are plumbed in the global zone.  See if_tcp(7p) for a description
2626 * of the ioctls used here.
2627 */
2628static int
2629get_local_netifs(int *if_cnt, struct net_if ***if_list)
2630{
2631	int		s;
2632	int		i;
2633	int		res = Z_OK;
2634	int		space_needed;
2635	int		cnt = 0;
2636	struct		lifnum if_num;
2637	struct		lifconf if_conf;
2638	struct		lifreq *if_reqp;
2639	char		*if_buf;
2640	struct net_if	**local_ifs = NULL;
2641
2642	*if_cnt = 0;
2643	*if_list = NULL;
2644
2645	if ((s = socket(SOCKET_AF(AF_INET), SOCK_DGRAM, 0)) < 0)
2646		return (Z_ERR);
2647
2648	/*
2649	 * Come back here in the unlikely event that the number of interfaces
2650	 * increases between the time we get the count and the time we do the
2651	 * SIOCGLIFCONF ioctl.
2652	 */
2653retry:
2654	/* Get the number of interfaces. */
2655	if_num.lifn_family = AF_UNSPEC;
2656	if_num.lifn_flags = LIFC_NOXMIT;
2657	if (ioctl(s, SIOCGLIFNUM, &if_num) < 0) {
2658		(void) close(s);
2659		return (Z_ERR);
2660	}
2661
2662	/* Get the interface configuration list. */
2663	space_needed = if_num.lifn_count * sizeof (struct lifreq);
2664	if ((if_buf = malloc(space_needed)) == NULL) {
2665		(void) close(s);
2666		return (Z_ERR);
2667	}
2668	if_conf.lifc_family = AF_UNSPEC;
2669	if_conf.lifc_flags = LIFC_NOXMIT;
2670	if_conf.lifc_len = space_needed;
2671	if_conf.lifc_buf = if_buf;
2672	if (ioctl(s, SIOCGLIFCONF, &if_conf) < 0) {
2673		free(if_buf);
2674		/*
2675		 * SIOCGLIFCONF returns EINVAL if the buffer we passed in is
2676		 * too small.  In this case go back and get the new if cnt.
2677		 */
2678		if (errno == EINVAL)
2679			goto retry;
2680
2681		(void) close(s);
2682		return (Z_ERR);
2683	}
2684	(void) close(s);
2685
2686	/* Get the name and address family for each interface. */
2687	if_reqp = if_conf.lifc_req;
2688	for (i = 0; i < (if_conf.lifc_len / sizeof (struct lifreq)); i++) {
2689		struct net_if	**p;
2690		struct lifreq	req;
2691
2692		if (strcmp(LOOPBACK_IF, if_reqp->lifr_name) == 0) {
2693			if_reqp++;
2694			continue;
2695		}
2696
2697		if ((s = socket(SOCKET_AF(if_reqp->lifr_addr.ss_family),
2698		    SOCK_DGRAM, 0)) == -1) {
2699			res = Z_ERR;
2700			break;
2701		}
2702
2703		(void) strncpy(req.lifr_name, if_reqp->lifr_name,
2704		    sizeof (req.lifr_name));
2705		if (ioctl(s, SIOCGLIFADDR, &req) < 0) {
2706			(void) close(s);
2707			if_reqp++;
2708			continue;
2709		}
2710
2711		if ((p = (struct net_if **)realloc(local_ifs,
2712		    sizeof (struct net_if *) * (cnt + 1))) == NULL) {
2713			res = Z_ERR;
2714			break;
2715		}
2716		local_ifs = p;
2717
2718		if ((local_ifs[cnt] = malloc(sizeof (struct net_if))) == NULL) {
2719			res = Z_ERR;
2720			break;
2721		}
2722
2723		if ((local_ifs[cnt]->name = strdup(if_reqp->lifr_name))
2724		    == NULL) {
2725			free(local_ifs[cnt]);
2726			res = Z_ERR;
2727			break;
2728		}
2729		local_ifs[cnt]->af = req.lifr_addr.ss_family;
2730		cnt++;
2731
2732		(void) close(s);
2733		if_reqp++;
2734	}
2735
2736	free(if_buf);
2737
2738	if (res != Z_OK) {
2739		free_local_netifs(cnt, local_ifs);
2740	} else {
2741		*if_cnt = cnt;
2742		*if_list = local_ifs;
2743	}
2744
2745	return (res);
2746}
2747
2748static char *
2749af2str(int af)
2750{
2751	switch (af) {
2752	case AF_INET:
2753		return ("IPv4");
2754	case AF_INET6:
2755		return ("IPv6");
2756	default:
2757		return ("Unknown");
2758	}
2759}
2760
2761/*
2762 * Cross check the network interface name and address family with the
2763 * interfaces that are set up in the global zone so that we can print the
2764 * appropriate error message.
2765 */
2766static void
2767print_net_err(char *phys, char *addr, int af, char *msg)
2768{
2769	int		i;
2770	int		local_if_cnt = 0;
2771	struct net_if	**local_ifs = NULL;
2772	boolean_t	found_if = B_FALSE;
2773	boolean_t	found_af = B_FALSE;
2774
2775	if (get_local_netifs(&local_if_cnt, &local_ifs) != Z_OK) {
2776		(void) fprintf(stderr,
2777		    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2778		    "net", "address", addr, "physical", phys, msg);
2779		return;
2780	}
2781
2782	for (i = 0; i < local_if_cnt; i++) {
2783		if (strcmp(phys, local_ifs[i]->name) == 0) {
2784			found_if = B_TRUE;
2785			if (af == local_ifs[i]->af) {
2786				found_af = B_TRUE;
2787				break;
2788			}
2789		}
2790	}
2791
2792	free_local_netifs(local_if_cnt, local_ifs);
2793
2794	if (!found_if) {
2795		(void) fprintf(stderr,
2796		    gettext("could not verify %s %s=%s\n\t"
2797		    "network interface %s is not plumbed in the global zone\n"),
2798		    "net", "physical", phys, phys);
2799		return;
2800	}
2801
2802	/*
2803	 * Print this error if we were unable to find the address family
2804	 * for this interface.  If the af variable is not initialized to
2805	 * to something meaningful by the caller (not AF_UNSPEC) then we
2806	 * also skip this message since it wouldn't be informative.
2807	 */
2808	if (!found_af && af != AF_UNSPEC) {
2809		(void) fprintf(stderr,
2810		    gettext("could not verify %s %s=%s %s=%s\n\tthe %s address "
2811		    "family is not configured on this network interface in "
2812		    "the\n\tglobal zone\n"),
2813		    "net", "address", addr, "physical", phys, af2str(af));
2814		return;
2815	}
2816
2817	(void) fprintf(stderr,
2818	    gettext("could not verify %s %s=%s %s=%s\n\t%s\n"),
2819	    "net", "address", addr, "physical", phys, msg);
2820}
2821
2822static int
2823verify_handle(int cmd_num, zone_dochandle_t handle, char *argv[])
2824{
2825	struct zone_nwiftab nwiftab;
2826	int return_code = Z_OK;
2827	int err;
2828	boolean_t in_alt_root;
2829	zone_iptype_t iptype;
2830	int fd;
2831
2832	in_alt_root = zonecfg_in_alt_root();
2833	if (in_alt_root)
2834		goto no_net;
2835
2836	if ((err = zonecfg_get_iptype(handle, &iptype)) != Z_OK) {
2837		errno = err;
2838		zperror(cmd_to_str(cmd_num), B_TRUE);
2839		zonecfg_fini_handle(handle);
2840		return (Z_ERR);
2841	}
2842	if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
2843		errno = err;
2844		zperror(cmd_to_str(cmd_num), B_TRUE);
2845		zonecfg_fini_handle(handle);
2846		return (Z_ERR);
2847	}
2848	while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
2849		struct lifreq lifr;
2850		sa_family_t af = AF_UNSPEC;
2851		char dl_owner_zname[ZONENAME_MAX];
2852		zoneid_t dl_owner_zid;
2853		zoneid_t target_zid;
2854		int res;
2855
2856		/* skip any loopback interfaces */
2857		if (strcmp(nwiftab.zone_nwif_physical, "lo0") == 0)
2858			continue;
2859		switch (iptype) {
2860		case ZS_SHARED:
2861			if ((res = zonecfg_valid_net_address(
2862			    nwiftab.zone_nwif_address, &lifr)) != Z_OK) {
2863				print_net_err(nwiftab.zone_nwif_physical,
2864				    nwiftab.zone_nwif_address, af,
2865				    zonecfg_strerror(res));
2866			    return_code = Z_ERR;
2867			    continue;
2868			}
2869			af = lifr.lifr_addr.ss_family;
2870			if (!zonecfg_ifname_exists(af,
2871			    nwiftab.zone_nwif_physical)) {
2872				/*
2873				 * The interface failed to come up. We continue
2874				 * on anyway for the sake of consistency: a
2875				 * zone is not shut down if the interface fails
2876				 * any time after boot, nor does the global zone
2877				 * fail to boot if an interface fails.
2878				 */
2879				(void) fprintf(stderr,
2880				    gettext("WARNING: skipping network "
2881					"interface '%s' which may not be "
2882					"present/plumbed in the global "
2883					"zone.\n"),
2884				    nwiftab.zone_nwif_physical);
2885			}
2886			break;
2887		case ZS_EXCLUSIVE:
2888			/* Warning if it exists for either IPv4 or IPv6 */
2889
2890			if (zonecfg_ifname_exists(AF_INET,
2891			    nwiftab.zone_nwif_physical) ||
2892			    zonecfg_ifname_exists(AF_INET6,
2893			    nwiftab.zone_nwif_physical)) {
2894				(void) fprintf(stderr,
2895				    gettext("WARNING: skipping network "
2896				    "interface '%s' which is used in the "
2897				    "global zone.\n"),
2898				    nwiftab.zone_nwif_physical);
2899				break;
2900			}
2901			/*
2902			 * Verify that the physical interface can
2903			 * be opened
2904			 */
2905			fd = ifname_open(nwiftab.zone_nwif_physical);
2906			if (fd == -1) {
2907				(void) fprintf(stderr,
2908				    gettext("WARNING: skipping network "
2909				    "interface '%s' which cannot be opened.\n"),
2910				    nwiftab.zone_nwif_physical);
2911				break;
2912			} else {
2913				(void) close(fd);
2914			}
2915			/*
2916			 * Verify whether the physical interface is already
2917			 * used by a zone.
2918			 */
2919			dl_owner_zid = ALL_ZONES;
2920			if (zone_check_datalink(&dl_owner_zid,
2921			    nwiftab.zone_nwif_physical) != 0)
2922				break;
2923
2924			/*
2925			 * If the zone being verified is
2926			 * running and owns the interface
2927			 */
2928			target_zid = getzoneidbyname(target_zone);
2929			if (target_zid == dl_owner_zid)
2930				break;
2931
2932			/* Zone id match failed, use name to check */
2933			if (getzonenamebyid(dl_owner_zid, dl_owner_zname,
2934			    ZONENAME_MAX) < 0) {
2935				/* No name, show ID instead */
2936				(void) snprintf(dl_owner_zname, ZONENAME_MAX,
2937				    "<%d>", dl_owner_zid);
2938			} else if (strcmp(dl_owner_zname, target_zone) == 0)
2939				break;
2940
2941			/*
2942			 * Note here we only report a warning that
2943			 * the interface is already in use by another
2944			 * running zone, and the verify process just
2945			 * goes on, if the interface is still in use
2946			 * when this zone really boots up, zoneadmd
2947			 * will find it. If the name of the zone which
2948			 * owns this interface cannot be determined,
2949			 * then it is not possible to determine if there
2950			 * is a conflict so just report it as a warning.
2951			 */
2952			(void) fprintf(stderr,
2953			    gettext("WARNING: skipping network interface "
2954			    "'%s' which is used by the non-global zone "
2955			    "'%s'.\n"), nwiftab.zone_nwif_physical,
2956			    dl_owner_zname);
2957			break;
2958		}
2959	}
2960	(void) zonecfg_endnwifent(handle);
2961no_net:
2962
2963	/* verify that lofs has not been excluded from the kernel */
2964	if (!(cmd_num == CMD_DETACH || cmd_num == CMD_ATTACH ||
2965	    cmd_num == CMD_MOVE || cmd_num == CMD_CLONE) &&
2966	    modctl(MODLOAD, 1, "fs/lofs", NULL) != 0) {
2967		if (errno == ENXIO)
2968			(void) fprintf(stderr, gettext("could not verify "
2969			    "lofs(7FS): possibly excluded in /etc/system\n"));
2970		else
2971			(void) fprintf(stderr, gettext("could not verify "
2972			    "lofs(7FS): %s\n"), strerror(errno));
2973		return_code = Z_ERR;
2974	}
2975
2976	if (verify_filesystems(handle) != Z_OK)
2977		return_code = Z_ERR;
2978	if (verify_ipd(handle) != Z_OK)
2979		return_code = Z_ERR;
2980	if (!in_alt_root && verify_rctls(handle) != Z_OK)
2981		return_code = Z_ERR;
2982	if (!in_alt_root && verify_pool(handle) != Z_OK)
2983		return_code = Z_ERR;
2984	if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2985		return_code = Z_ERR;
2986	if (!in_alt_root && verify_datasets(handle) != Z_OK)
2987		return_code = Z_ERR;
2988
2989	/*
2990	 * As the "mount" command is used for patching/upgrading of zones
2991	 * or other maintenance processes, the zone's privilege set is not
2992	 * checked in this case.  Instead, the default, safe set of
2993	 * privileges will be used when this zone is created in the
2994	 * kernel.
2995	 */
2996	if (!in_alt_root && cmd_num != CMD_MOUNT &&
2997	    verify_limitpriv(handle) != Z_OK)
2998		return_code = Z_ERR;
2999
3000	return (return_code);
3001}
3002
3003static int
3004verify_details(int cmd_num, char *argv[])
3005{
3006	zone_dochandle_t handle;
3007	char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
3008	int return_code = Z_OK;
3009	int err;
3010
3011	if ((handle = zonecfg_init_handle()) == NULL) {
3012		zperror(cmd_to_str(cmd_num), B_TRUE);
3013		return (Z_ERR);
3014	}
3015	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
3016		errno = err;
3017		zperror(cmd_to_str(cmd_num), B_TRUE);
3018		zonecfg_fini_handle(handle);
3019		return (Z_ERR);
3020	}
3021	if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
3022	    Z_OK) {
3023		errno = err;
3024		zperror(cmd_to_str(cmd_num), B_TRUE);
3025		zonecfg_fini_handle(handle);
3026		return (Z_ERR);
3027	}
3028	/*
3029	 * zonecfg_get_zonepath() gets its data from the XML repository.
3030	 * Verify this against the index file, which is checked first by
3031	 * zone_get_zonepath().  If they don't match, bail out.
3032	 */
3033	if ((err = zone_get_zonepath(target_zone, checkpath,
3034	    sizeof (checkpath))) != Z_OK) {
3035		errno = err;
3036		zperror2(target_zone, gettext("could not get zone path"));
3037		return (Z_ERR);
3038	}
3039	if (strcmp(zonepath, checkpath) != 0) {
3040		/*
3041		 * TRANSLATION_NOTE
3042		 * XML and zonepath are literals that should not be translated.
3043		 */
3044		(void) fprintf(stderr, gettext("The XML repository has "
3045		    "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
3046		    "These must match, so fix the incorrect entry.\n"),
3047		    zonepath, checkpath);
3048		return (Z_ERR);
3049	}
3050	if (validate_zonepath(zonepath, cmd_num) != Z_OK) {
3051		(void) fprintf(stderr, gettext("could not verify zonepath %s "
3052		    "because of the above errors.\n"), zonepath);
3053		return_code = Z_ERR;
3054	}
3055
3056	if (verify_handle(cmd_num, handle, argv) != Z_OK)
3057		return_code = Z_ERR;
3058
3059	zonecfg_fini_handle(handle);
3060	if (return_code == Z_ERR)
3061		(void) fprintf(stderr,
3062		    gettext("%s: zone %s failed to verify\n"),
3063		    execname, target_zone);
3064	return (return_code);
3065}
3066
3067static int
3068verify_func(int argc, char *argv[])
3069{
3070	int arg;
3071
3072	optind = 0;
3073	if ((arg = getopt(argc, argv, "?")) != EOF) {
3074		switch (arg) {
3075		case '?':
3076			sub_usage(SHELP_VERIFY, CMD_VERIFY);
3077			return (optopt == '?' ? Z_OK : Z_USAGE);
3078		default:
3079			sub_usage(SHELP_VERIFY, CMD_VERIFY);
3080			return (Z_USAGE);
3081		}
3082	}
3083	if (argc > optind) {
3084		sub_usage(SHELP_VERIFY, CMD_VERIFY);
3085		return (Z_USAGE);
3086	}
3087	if (sanity_check(target_zone, CMD_VERIFY, B_FALSE, B_FALSE, B_FALSE)
3088	    != Z_OK)
3089		return (Z_ERR);
3090	return (verify_details(CMD_VERIFY, argv));
3091}
3092
3093static int
3094addopt(char *buf, int opt, char *optarg, size_t bufsize)
3095{
3096	char optstring[4];
3097
3098	if (opt > 0)
3099		(void) sprintf(optstring, " -%c", opt);
3100	else
3101		(void) strcpy(optstring, " ");
3102
3103	if ((strlcat(buf, optstring, bufsize) > bufsize))
3104		return (Z_ERR);
3105	if ((optarg != NULL) && (strlcat(buf, optarg, bufsize) > bufsize))
3106		return (Z_ERR);
3107	return (Z_OK);
3108}
3109
3110static int
3111install_func(int argc, char *argv[])
3112{
3113	char cmdbuf[MAXPATHLEN];
3114	int lockfd;
3115	int arg, err, subproc_err;
3116	char zonepath[MAXPATHLEN];
3117	brand_handle_t bh = NULL;
3118	int status;
3119	boolean_t nodataset = B_FALSE;
3120	char opts[128];
3121
3122	if (target_zone == NULL) {
3123		sub_usage(SHELP_INSTALL, CMD_INSTALL);
3124		return (Z_USAGE);
3125	}
3126
3127	if (zonecfg_in_alt_root()) {
3128		zerror(gettext("cannot install zone in alternate root"));
3129		return (Z_ERR);
3130	}
3131
3132	if ((err = zone_get_zonepath(target_zone, zonepath,
3133	    sizeof (zonepath))) != Z_OK) {
3134		errno = err;
3135		zperror2(target_zone, gettext("could not get zone path"));
3136		return (Z_ERR);
3137	}
3138
3139	/* Fetch the install command from the brand configuration.  */
3140	if ((bh = brand_open(target_brand)) == NULL) {
3141		zerror(gettext("missing or invalid brand"));
3142		return (Z_ERR);
3143	}
3144
3145	(void) strcpy(cmdbuf, EXEC_PREFIX);
3146	if (brand_get_install(bh, target_zone, zonepath, cmdbuf + EXEC_LEN,
3147	    sizeof (cmdbuf) - EXEC_LEN, 0, NULL) != 0) {
3148		zerror("invalid brand configuration: missing install resource");
3149		brand_close(bh);
3150		return (Z_ERR);
3151	}
3152
3153	(void) strcpy(opts, "?x:");
3154	if (!is_native_zone) {
3155		/*
3156		 * Fetch the list of recognized command-line options from
3157		 * the brand configuration file.
3158		 */
3159		if (brand_get_installopts(bh, opts + strlen(opts),
3160		    sizeof (opts) - strlen(opts)) != 0) {
3161			zerror("invalid brand configuration: missing "
3162			    "install options resource");
3163			brand_close(bh);
3164			return (Z_ERR);
3165		}
3166	}
3167	brand_close(bh);
3168
3169	optind = 0;
3170	while ((arg = getopt(argc, argv, opts)) != EOF) {
3171		switch (arg) {
3172		case '?':
3173			sub_usage(SHELP_INSTALL, CMD_INSTALL);
3174			return (optopt == '?' ? Z_OK : Z_USAGE);
3175		case 'x':
3176			if (strcmp(optarg, "nodataset") != 0) {
3177				sub_usage(SHELP_INSTALL, CMD_INSTALL);
3178				return (Z_USAGE);
3179			}
3180			nodataset = B_TRUE;
3181			break;
3182		default:
3183			if (is_native_zone) {
3184				sub_usage(SHELP_INSTALL, CMD_INSTALL);
3185				return (Z_USAGE);
3186			}
3187
3188			/*
3189			 * This option isn't for zoneadm, so append it to
3190			 * the command line passed to the brand-specific
3191			 * install routine.
3192			 */
3193			if (addopt(cmdbuf, optopt, optarg,
3194			    sizeof (cmdbuf)) != Z_OK) {
3195				zerror("Install command line too long");
3196				return (Z_ERR);
3197			}
3198			break;
3199		}
3200	}
3201
3202	if (!is_native_zone) {
3203		for (; optind < argc; optind++) {
3204			if (addopt(cmdbuf, 0, argv[optind],
3205			    sizeof (cmdbuf)) != Z_OK) {
3206				zerror("Install command line too long");
3207				return (Z_ERR);
3208			}
3209		}
3210	}
3211
3212	if (sanity_check(target_zone, CMD_INSTALL, B_FALSE, B_TRUE, B_FALSE)
3213	    != Z_OK)
3214		return (Z_ERR);
3215	if (verify_details(CMD_INSTALL, argv) != Z_OK)
3216		return (Z_ERR);
3217
3218	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3219		zerror(gettext("another %s may have an operation in progress."),
3220		    "zoneadm");
3221		return (Z_ERR);
3222	}
3223	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3224	if (err != Z_OK) {
3225		errno = err;
3226		zperror2(target_zone, gettext("could not set state"));
3227		goto done;
3228	}
3229
3230	if (!nodataset)
3231		create_zfs_zonepath(zonepath);
3232
3233	/*
3234	 * According to the Application Packaging Developer's Guide, a
3235	 * "checkinstall" script when included in a package is executed as
3236	 * the user "install", if such a user exists, or by the user
3237	 * "nobody".  In order to support this dubious behavior, the path
3238	 * to the zone being constructed is opened up during the life of
3239	 * the command laying down the zone's root file system.  Once this
3240	 * has completed, regardless of whether it was successful, the
3241	 * path to the zone is again restricted.
3242	 */
3243	if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) {
3244		zperror(zonepath, B_FALSE);
3245		err = Z_ERR;
3246		goto done;
3247	}
3248
3249	if (is_native_zone)
3250		status = do_subproc(cmdbuf);
3251	else
3252		status = do_subproc_interactive(cmdbuf);
3253
3254	if (chmod(zonepath, S_IRWXU) != 0) {
3255		zperror(zonepath, B_FALSE);
3256		err = Z_ERR;
3257		goto done;
3258	}
3259	if ((subproc_err =
3260	    subproc_status(gettext("brand-specific installation"), status,
3261	    B_FALSE)) != ZONE_SUBPROC_OK) {
3262		err = Z_ERR;
3263		goto done;
3264	}
3265
3266	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
3267		errno = err;
3268		zperror2(target_zone, gettext("could not set state"));
3269		goto done;
3270	}
3271
3272done:
3273	/*
3274	 * If the install script exited with ZONE_SUBPROC_USAGE or
3275	 * ZONE_SUBPROC_NOTCOMPLETE, try to clean up the zone and leave the
3276	 * zone in the CONFIGURED state so that another install can be
3277	 * attempted without requiring an uninstall first.
3278	 */
3279	if ((subproc_err == ZONE_SUBPROC_USAGE) ||
3280	    (subproc_err == ZONE_SUBPROC_NOTCOMPLETE)) {
3281		if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
3282			errno = err;
3283			zperror2(target_zone,
3284			    gettext("cleaning up zonepath failed"));
3285		} else if ((err = zone_set_state(target_zone,
3286		    ZONE_STATE_CONFIGURED)) != Z_OK) {
3287			errno = err;
3288			zperror2(target_zone, gettext("could not set state"));
3289		}
3290	}
3291
3292	release_lock_file(lockfd);
3293	return ((err == Z_OK) ? Z_OK : Z_ERR);
3294}
3295
3296/*
3297 * Check that the inherited pkg dirs are the same for the clone and its source.
3298 * The easiest way to do that is check that the list of ipds is the same
3299 * by matching each one against the other.  This algorithm should be fine since
3300 * the list of ipds should not be that long.
3301 */
3302static int
3303valid_ipd_clone(zone_dochandle_t s_handle, char *source_zone,
3304	zone_dochandle_t t_handle, char *target_zone)
3305{
3306	int err;
3307	int res = Z_OK;
3308	int s_cnt = 0;
3309	int t_cnt = 0;
3310	struct zone_fstab s_fstab;
3311	struct zone_fstab t_fstab;
3312
3313	/*
3314	 * First check the source of the clone against the target.
3315	 */
3316	if ((err = zonecfg_setipdent(s_handle)) != Z_OK) {
3317		errno = err;
3318		zperror2(source_zone, gettext("could not enumerate "
3319		    "inherit-pkg-dirs"));
3320		return (Z_ERR);
3321	}
3322
3323	while (zonecfg_getipdent(s_handle, &s_fstab) == Z_OK) {
3324		boolean_t match = B_FALSE;
3325
3326		s_cnt++;
3327
3328		if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
3329			errno = err;
3330			zperror2(target_zone, gettext("could not enumerate "
3331			    "inherit-pkg-dirs"));
3332			(void) zonecfg_endipdent(s_handle);
3333			return (Z_ERR);
3334		}
3335
3336		while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK) {
3337			if (strcmp(s_fstab.zone_fs_dir, t_fstab.zone_fs_dir)
3338			    == 0) {
3339				match = B_TRUE;
3340				break;
3341			}
3342		}
3343		(void) zonecfg_endipdent(t_handle);
3344
3345		if (!match) {
3346			(void) fprintf(stderr, gettext("inherit-pkg-dir "
3347			    "'%s' is not configured in zone %s.\n"),
3348			    s_fstab.zone_fs_dir, target_zone);
3349			res = Z_ERR;
3350		}
3351	}
3352
3353	(void) zonecfg_endipdent(s_handle);
3354
3355	/* skip the next check if we already have errors */
3356	if (res == Z_ERR)
3357		return (res);
3358
3359	/*
3360	 * Now check the number of ipds in the target so we can verify
3361	 * that the source is not a subset of the target.
3362	 */
3363	if ((err = zonecfg_setipdent(t_handle)) != Z_OK) {
3364		errno = err;
3365		zperror2(target_zone, gettext("could not enumerate "
3366		    "inherit-pkg-dirs"));
3367		return (Z_ERR);
3368	}
3369
3370	while (zonecfg_getipdent(t_handle, &t_fstab) == Z_OK)
3371		t_cnt++;
3372
3373	(void) zonecfg_endipdent(t_handle);
3374
3375	if (t_cnt != s_cnt) {
3376		(void) fprintf(stderr, gettext("Zone %s is configured "
3377		    "with inherit-pkg-dirs that are not configured in zone "
3378		    "%s.\n"), target_zone, source_zone);
3379		res = Z_ERR;
3380	}
3381
3382	return (res);
3383}
3384
3385static void
3386warn_dev_match(zone_dochandle_t s_handle, char *source_zone,
3387	zone_dochandle_t t_handle, char *target_zone)
3388{
3389	int err;
3390	struct zone_devtab s_devtab;
3391	struct zone_devtab t_devtab;
3392
3393	if ((err = zonecfg_setdevent(t_handle)) != Z_OK) {
3394		errno = err;
3395		zperror2(target_zone, gettext("could not enumerate devices"));
3396		return;
3397	}
3398
3399	while (zonecfg_getdevent(t_handle, &t_devtab) == Z_OK) {
3400		if ((err = zonecfg_setdevent(s_handle)) != Z_OK) {
3401			errno = err;
3402			zperror2(source_zone,
3403			    gettext("could not enumerate devices"));
3404			(void) zonecfg_enddevent(t_handle);
3405			return;
3406		}
3407
3408		while (zonecfg_getdevent(s_handle, &s_devtab) == Z_OK) {
3409			/*
3410			 * Use fnmatch to catch the case where wildcards
3411			 * were used in one zone and the other has an
3412			 * explicit entry (e.g. /dev/dsk/c0t0d0s6 vs.
3413			 * /dev/\*dsk/c0t0d0s6).
3414			 */
3415			if (fnmatch(t_devtab.zone_dev_match,
3416			    s_devtab.zone_dev_match, FNM_PATHNAME) == 0 ||
3417			    fnmatch(s_devtab.zone_dev_match,
3418			    t_devtab.zone_dev_match, FNM_PATHNAME) == 0) {
3419				(void) fprintf(stderr,
3420				    gettext("WARNING: device '%s' "
3421				    "is configured in both zones.\n"),
3422				    t_devtab.zone_dev_match);
3423				break;
3424			}
3425		}
3426		(void) zonecfg_enddevent(s_handle);
3427	}
3428
3429	(void) zonecfg_enddevent(t_handle);
3430}
3431
3432/*
3433 * Check if the specified mount option (opt) is contained within the
3434 * options string.
3435 */
3436static boolean_t
3437opt_match(char *opt, char *options)
3438{
3439	char *p;
3440	char *lastp;
3441
3442	if ((p = strtok_r(options, ",", &lastp)) != NULL) {
3443		if (strcmp(p, opt) == 0)
3444			return (B_TRUE);
3445		while ((p = strtok_r(NULL, ",", &lastp)) != NULL) {
3446			if (strcmp(p, opt) == 0)
3447				return (B_TRUE);
3448		}
3449	}
3450
3451	return (B_FALSE);
3452}
3453
3454#define	RW_LOFS	"WARNING: read-write lofs file system on '%s' is configured " \
3455	"in both zones.\n"
3456
3457static void
3458print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
3459{
3460	/*
3461	 * It is ok to have shared lofs mounted fs but we want to warn if
3462	 * either is rw since this will effect the other zone.
3463	 */
3464	if (strcmp(t_fstab->zone_fs_type, "lofs") == 0) {
3465		zone_fsopt_t *optp;
3466
3467		/* The default is rw so no options means rw */
3468		if (t_fstab->zone_fs_options == NULL ||
3469		    s_fstab->zone_fs_options == NULL) {
3470			(void) fprintf(stderr, gettext(RW_LOFS),
3471			    t_fstab->zone_fs_special);
3472			return;
3473		}
3474
3475		for (optp = s_fstab->zone_fs_options; optp != NULL;
3476		    optp = optp->zone_fsopt_next) {
3477			if (opt_match("rw", optp->zone_fsopt_opt)) {
3478				(void) fprintf(stderr, gettext(RW_LOFS),
3479				    s_fstab->zone_fs_special);
3480				return;
3481			}
3482		}
3483
3484		for (optp = t_fstab->zone_fs_options; optp != NULL;
3485		    optp = optp->zone_fsopt_next) {
3486			if (opt_match("rw", optp->zone_fsopt_opt)) {
3487				(void) fprintf(stderr, gettext(RW_LOFS),
3488				    t_fstab->zone_fs_special);
3489				return;
3490			}
3491		}
3492
3493		return;
3494	}
3495
3496	/*
3497	 * TRANSLATION_NOTE
3498	 * The first variable is the file system type and the second is
3499	 * the file system special device.  For example,
3500	 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
3501	 */
3502	(void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
3503	    "is configured in both zones.\n"), t_fstab->zone_fs_type,
3504	    t_fstab->zone_fs_special);
3505}
3506
3507static void
3508warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
3509	zone_dochandle_t t_handle, char *target_zone)
3510{
3511	int err;
3512	struct zone_fstab s_fstab;
3513	struct zone_fstab t_fstab;
3514
3515	if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
3516		errno = err;
3517		zperror2(target_zone,
3518		    gettext("could not enumerate file systems"));
3519		return;
3520	}
3521
3522	while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
3523		if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
3524			errno = err;
3525			zperror2(source_zone,
3526			    gettext("could not enumerate file systems"));
3527			(void) zonecfg_endfsent(t_handle);
3528			return;
3529		}
3530
3531		while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
3532			if (strcmp(t_fstab.zone_fs_special,
3533			    s_fstab.zone_fs_special) == 0) {
3534				print_fs_warnings(&s_fstab, &t_fstab);
3535				break;
3536			}
3537		}
3538		(void) zonecfg_endfsent(s_handle);
3539	}
3540
3541	(void) zonecfg_endfsent(t_handle);
3542}
3543
3544/*
3545 * We don't catch the case where you used the same IP address but
3546 * it is not an exact string match.  For example, 192.9.0.128 vs. 192.09.0.128.
3547 * However, we're not going to worry about that but we will check for
3548 * a possible netmask on one of the addresses (e.g. 10.0.0.1 and 10.0.0.1/24)
3549 * and handle that case as a match.
3550 */
3551static void
3552warn_ip_match(zone_dochandle_t s_handle, char *source_zone,
3553	zone_dochandle_t t_handle, char *target_zone)
3554{
3555	int err;
3556	struct zone_nwiftab s_nwiftab;
3557	struct zone_nwiftab t_nwiftab;
3558
3559	if ((err = zonecfg_setnwifent(t_handle)) != Z_OK) {
3560		errno = err;
3561		zperror2(target_zone,
3562		    gettext("could not enumerate network interfaces"));
3563		return;
3564	}
3565
3566	while (zonecfg_getnwifent(t_handle, &t_nwiftab) == Z_OK) {
3567		char *p;
3568
3569		/* remove an (optional) netmask from the address */
3570		if ((p = strchr(t_nwiftab.zone_nwif_address, '/')) != NULL)
3571			*p = '\0';
3572
3573		if ((err = zonecfg_setnwifent(s_handle)) != Z_OK) {
3574			errno = err;
3575			zperror2(source_zone,
3576			    gettext("could not enumerate network interfaces"));
3577			(void) zonecfg_endnwifent(t_handle);
3578			return;
3579		}
3580
3581		while (zonecfg_getnwifent(s_handle, &s_nwiftab) == Z_OK) {
3582			/* remove an (optional) netmask from the address */
3583			if ((p = strchr(s_nwiftab.zone_nwif_address, '/'))
3584			    != NULL)
3585				*p = '\0';
3586
3587			/* For exclusive-IP zones, address is not specified. */
3588			if (strlen(s_nwiftab.zone_nwif_address) == 0)
3589				continue;
3590
3591			if (strcmp(t_nwiftab.zone_nwif_address,
3592			    s_nwiftab.zone_nwif_address) == 0) {
3593				(void) fprintf(stderr,
3594				    gettext("WARNING: network address '%s' "
3595				    "is configured in both zones.\n"),
3596				    t_nwiftab.zone_nwif_address);
3597				break;
3598			}
3599		}
3600		(void) zonecfg_endnwifent(s_handle);
3601	}
3602
3603	(void) zonecfg_endnwifent(t_handle);
3604}
3605
3606static void
3607warn_dataset_match(zone_dochandle_t s_handle, char *source,
3608	zone_dochandle_t t_handle, char *target)
3609{
3610	int err;
3611	struct zone_dstab s_dstab;
3612	struct zone_dstab t_dstab;
3613
3614	if ((err = zonecfg_setdsent(t_handle)) != Z_OK) {
3615		errno = err;
3616		zperror2(target, gettext("could not enumerate datasets"));
3617		return;
3618	}
3619
3620	while (zonecfg_getdsent(t_handle, &t_dstab) == Z_OK) {
3621		if ((err = zonecfg_setdsent(s_handle)) != Z_OK) {
3622			errno = err;
3623			zperror2(source,
3624			    gettext("could not enumerate datasets"));
3625			(void) zonecfg_enddsent(t_handle);
3626			return;
3627		}
3628
3629		while (zonecfg_getdsent(s_handle, &s_dstab) == Z_OK) {
3630			if (strcmp(t_dstab.zone_dataset_name,
3631			    s_dstab.zone_dataset_name) == 0) {
3632				target_zone = source;
3633				zerror(gettext("WARNING: dataset '%s' "
3634				    "is configured in both zones.\n"),
3635				    t_dstab.zone_dataset_name);
3636				break;
3637			}
3638		}
3639		(void) zonecfg_enddsent(s_handle);
3640	}
3641
3642	(void) zonecfg_enddsent(t_handle);
3643}
3644
3645/*
3646 * Check that the clone and its source have the same brand type.
3647 */
3648static int
3649valid_brand_clone(char *source_zone, char *target_zone)
3650{
3651	brand_handle_t bh;
3652	char source_brand[MAXNAMELEN];
3653
3654	if ((zone_get_brand(source_zone, source_brand,
3655	    sizeof (source_brand))) != Z_OK) {
3656		(void) fprintf(stderr, "%s: zone '%s': %s\n",
3657		    execname, source_zone, gettext("missing or invalid brand"));
3658		return (Z_ERR);
3659	}
3660
3661	if (strcmp(source_brand, target_brand) != NULL) {
3662		(void) fprintf(stderr,
3663		    gettext("%s: Zones '%s' and '%s' have different brand "
3664		    "types.\n"), execname, source_zone, target_zone);
3665		return (Z_ERR);
3666	}
3667
3668	if ((bh = brand_open(target_brand)) == NULL) {
3669		zerror(gettext("missing or invalid brand"));
3670		return (Z_ERR);
3671	}
3672	brand_close(bh);
3673	return (Z_OK);
3674}
3675
3676static int
3677validate_clone(char *source_zone, char *target_zone)
3678{
3679	int err = Z_OK;
3680	zone_dochandle_t s_handle;
3681	zone_dochandle_t t_handle;
3682
3683	if ((t_handle = zonecfg_init_handle()) == NULL) {
3684		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3685		return (Z_ERR);
3686	}
3687	if ((err = zonecfg_get_handle(target_zone, t_handle)) != Z_OK) {
3688		errno = err;
3689		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3690		zonecfg_fini_handle(t_handle);
3691		return (Z_ERR);
3692	}
3693
3694	if ((s_handle = zonecfg_init_handle()) == NULL) {
3695		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3696		zonecfg_fini_handle(t_handle);
3697		return (Z_ERR);
3698	}
3699	if ((err = zonecfg_get_handle(source_zone, s_handle)) != Z_OK) {
3700		errno = err;
3701		zperror(cmd_to_str(CMD_CLONE), B_TRUE);
3702		goto done;
3703	}
3704
3705	/* verify new zone has same brand type */
3706	err = valid_brand_clone(source_zone, target_zone);
3707	if (err != Z_OK)
3708		goto done;
3709
3710	/* verify new zone has same inherit-pkg-dirs */
3711	err = valid_ipd_clone(s_handle, source_zone, t_handle, target_zone);
3712
3713	/* warn about imported fs's which are the same */
3714	warn_fs_match(s_handle, source_zone, t_handle, target_zone);
3715
3716	/* warn about imported IP addresses which are the same */
3717	warn_ip_match(s_handle, source_zone, t_handle, target_zone);
3718
3719	/* warn about imported devices which are the same */
3720	warn_dev_match(s_handle, source_zone, t_handle, target_zone);
3721
3722	/* warn about imported datasets which are the same */
3723	warn_dataset_match(s_handle, source_zone, t_handle, target_zone);
3724
3725done:
3726	zonecfg_fini_handle(t_handle);
3727	zonecfg_fini_handle(s_handle);
3728
3729	return ((err == Z_OK) ? Z_OK : Z_ERR);
3730}
3731
3732static int
3733copy_zone(char *src, char *dst)
3734{
3735	boolean_t out_null = B_FALSE;
3736	int status;
3737	char *outfile;
3738	char cmdbuf[MAXPATHLEN * 2 + 128];
3739
3740	if ((outfile = tempnam("/var/log", "zone")) == NULL) {
3741		outfile = "/dev/null";
3742		out_null = B_TRUE;
3743	}
3744
3745	/*
3746	 * Use find to get the list of files to copy.  We need to skip
3747	 * files of type "socket" since cpio can't handle those but that
3748	 * should be ok since the app will recreate the socket when it runs.
3749	 * We also need to filter out anything under the .zfs subdir.  Since
3750	 * find is running depth-first, we need the extra egrep to filter .zfs.
3751	 */
3752	(void) snprintf(cmdbuf, sizeof (cmdbuf),
3753	    "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
3754	    "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
3755	    "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
3756	    src, dst, outfile);
3757
3758	status = do_subproc(cmdbuf);
3759
3760	if (subproc_status("copy", status, B_TRUE) != ZONE_SUBPROC_OK) {
3761		if (!out_null)
3762			(void) fprintf(stderr, gettext("\nThe copy failed.\n"
3763			    "More information can be found in %s\n"), outfile);
3764		return (Z_ERR);
3765	}
3766
3767	if (!out_null)
3768		(void) unlink(outfile);
3769
3770	return (Z_OK);
3771}
3772
3773static int
3774zone_postclone(char *zonepath)
3775{
3776	char cmdbuf[MAXPATHLEN];
3777	int status;
3778	brand_handle_t bh;
3779	int err = Z_OK;
3780
3781	/*
3782	 * Fetch the post-clone command, if any, from the brand
3783	 * configuration.
3784	 */
3785	if ((bh = brand_open(target_brand)) == NULL) {
3786		zerror(gettext("missing or invalid brand"));
3787		return (Z_ERR);
3788	}
3789	(void) strcpy(cmdbuf, EXEC_PREFIX);
3790	err = brand_get_postclone(bh, target_zone, zonepath, cmdbuf + EXEC_LEN,
3791	    sizeof (cmdbuf) - EXEC_LEN, 0, NULL);
3792	brand_close(bh);
3793
3794	if (err == 0 && strlen(cmdbuf) > EXEC_LEN) {
3795		status = do_subproc(cmdbuf);
3796		if ((err = subproc_status("postclone", status, B_FALSE))
3797		    != ZONE_SUBPROC_OK) {
3798			zerror(gettext("post-clone configuration failed."));
3799			err = Z_ERR;
3800		}
3801	}
3802
3803	return (err);
3804}
3805
3806/* ARGSUSED */
3807static int
3808zfm_print(const char *p, void *r) {
3809	zerror("  %s\n", p);
3810	return (0);
3811}
3812
3813int
3814clone_copy(char *source_zonepath, char *zonepath)
3815{
3816	int err;
3817
3818	/* Don't clone the zone if anything is still mounted there */
3819	if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
3820		zerror(gettext("These file systems are mounted on "
3821		    "subdirectories of %s.\n"), source_zonepath);
3822		(void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
3823		return (Z_ERR);
3824	}
3825
3826	/*
3827	 * Attempt to create a ZFS fs for the zonepath.  As usual, we don't
3828	 * care if this works or not since we always have the default behavior
3829	 * of a simple directory for the zonepath.
3830	 */
3831	create_zfs_zonepath(zonepath);
3832
3833	(void) printf(gettext("Copying %s..."), source_zonepath);
3834	(void) fflush(stdout);
3835
3836	err = copy_zone(source_zonepath, zonepath);
3837
3838	(void) printf("\n");
3839
3840	return (err);
3841}
3842
3843static int
3844clone_func(int argc, char *argv[])
3845{
3846	char *source_zone = NULL;
3847	int lockfd;
3848	int err, arg;
3849	char zonepath[MAXPATHLEN];
3850	char source_zonepath[MAXPATHLEN];
3851	zone_state_t state;
3852	zone_entry_t *zent;
3853	char *method = NULL;
3854	char *snapshot = NULL;
3855
3856	if (zonecfg_in_alt_root()) {
3857		zerror(gettext("cannot clone zone in alternate root"));
3858		return (Z_ERR);
3859	}
3860
3861	optind = 0;
3862	if ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
3863		switch (arg) {
3864		case '?':
3865			sub_usage(SHELP_CLONE, CMD_CLONE);
3866			return (optopt == '?' ? Z_OK : Z_USAGE);
3867		case 'm':
3868			method = optarg;
3869			break;
3870		case 's':
3871			snapshot = optarg;
3872			break;
3873		default:
3874			sub_usage(SHELP_CLONE, CMD_CLONE);
3875			return (Z_USAGE);
3876		}
3877	}
3878	if (argc != (optind + 1) ||
3879	    (method != NULL && strcmp(method, "copy") != 0)) {
3880		sub_usage(SHELP_CLONE, CMD_CLONE);
3881		return (Z_USAGE);
3882	}
3883	source_zone = argv[optind];
3884	if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE, B_FALSE)
3885	    != Z_OK)
3886		return (Z_ERR);
3887	if (verify_details(CMD_CLONE, argv) != Z_OK)
3888		return (Z_ERR);
3889
3890	/*
3891	 * We also need to do some extra validation on the source zone.
3892	 */
3893	if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3894		zerror(gettext("%s operation is invalid for the global zone."),
3895		    cmd_to_str(CMD_CLONE));
3896		return (Z_ERR);
3897	}
3898
3899	if (strncmp(source_zone, "SUNW", 4) == 0) {
3900		zerror(gettext("%s operation is invalid for zones starting "
3901		    "with SUNW."), cmd_to_str(CMD_CLONE));
3902		return (Z_ERR);
3903	}
3904
3905	zent = lookup_running_zone(source_zone);
3906	if (zent != NULL) {
3907		/* check whether the zone is ready or running */
3908		if ((err = zone_get_state(zent->zname, &zent->zstate_num))
3909		    != Z_OK) {
3910			errno = err;
3911			zperror2(zent->zname, gettext("could not get state"));
3912			/* can't tell, so hedge */
3913			zent->zstate_str = "ready/running";
3914		} else {
3915			zent->zstate_str = zone_state_str(zent->zstate_num);
3916		}
3917		zerror(gettext("%s operation is invalid for %s zones."),
3918		    cmd_to_str(CMD_CLONE), zent->zstate_str);
3919		return (Z_ERR);
3920	}
3921
3922	if ((err = zone_get_state(source_zone, &state)) != Z_OK) {
3923		errno = err;
3924		zperror2(source_zone, gettext("could not get state"));
3925		return (Z_ERR);
3926	}
3927	if (state != ZONE_STATE_INSTALLED) {
3928		(void) fprintf(stderr,
3929		    gettext("%s: zone %s is %s; %s is required.\n"),
3930		    execname, source_zone, zone_state_str(state),
3931		    zone_state_str(ZONE_STATE_INSTALLED));
3932		return (Z_ERR);
3933	}
3934
3935	/*
3936	 * The source zone checks out ok, continue with the clone.
3937	 */
3938
3939	if (validate_clone(source_zone, target_zone) != Z_OK)
3940		return (Z_ERR);
3941
3942	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3943		zerror(gettext("another %s may have an operation in progress."),
3944		    "zoneadm");
3945		return (Z_ERR);
3946	}
3947
3948	if ((err = zone_get_zonepath(source_zone, source_zonepath,
3949	    sizeof (source_zonepath))) != Z_OK) {
3950		errno = err;
3951		zperror2(source_zone, gettext("could not get zone path"));
3952		goto done;
3953	}
3954
3955	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3956	    != Z_OK) {
3957		errno = err;
3958		zperror2(target_zone, gettext("could not get zone path"));
3959		goto done;
3960	}
3961
3962	if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3963	    != Z_OK) {
3964		errno = err;
3965		zperror2(target_zone, gettext("could not set state"));
3966		goto done;
3967	}
3968
3969	if (snapshot != NULL) {
3970		err = clone_snapshot_zfs(snapshot, zonepath);
3971	} else {
3972		/*
3973		 * We always copy the clone unless the source is ZFS and a
3974		 * ZFS clone worked.  We fallback to copying if the ZFS clone
3975		 * fails for some reason.
3976		 */
3977		err = Z_ERR;
3978		if (method == NULL && is_zonepath_zfs(source_zonepath))
3979			err = clone_zfs(source_zone, source_zonepath, zonepath);
3980
3981		if (err != Z_OK)
3982			err = clone_copy(source_zonepath, zonepath);
3983	}
3984
3985	/*
3986	 * Trusted Extensions requires that cloned zones use the same sysid
3987	 * configuration, so it is not appropriate to perform any
3988	 * post-clone reconfiguration.
3989	 */
3990	if ((err == Z_OK) && !is_system_labeled())
3991		err = zone_postclone(zonepath);
3992
3993done:
3994	/*
3995	 * If everything went well, we mark the zone as installed.
3996	 */
3997	if (err == Z_OK) {
3998		err = zone_set_state(target_zone, ZONE_STATE_INSTALLED);
3999		if (err != Z_OK) {
4000			errno = err;
4001			zperror2(target_zone, gettext("could not set state"));
4002		}
4003	}
4004	release_lock_file(lockfd);
4005	return ((err == Z_OK) ? Z_OK : Z_ERR);
4006}
4007
4008/*
4009 * Used when removing a zonepath after uninstalling or cleaning up after
4010 * the move subcommand.  This handles a zonepath that has non-standard
4011 * contents so that we will only cleanup the stuff we know about and leave
4012 * any user data alone.
4013 *
4014 * If the "all" parameter is true then we should remove the whole zonepath
4015 * even if it has non-standard files/directories in it.  This can be used when
4016 * we need to cleanup after moving the zonepath across file systems.
4017 *
4018 * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
4019 * and not the shell.
4020 */
4021static int
4022cleanup_zonepath(char *zonepath, boolean_t all)
4023{
4024	int		status;
4025	int		i;
4026	boolean_t	non_std = B_FALSE;
4027	struct dirent	*dp;
4028	DIR		*dirp;
4029	char		*std_entries[] = {"dev", "lu", "root", NULL};
4030			/* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
4031	char		cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
4032
4033	/*
4034	 * We shouldn't need these checks but lets be paranoid since we
4035	 * could blow away the whole system here if we got the wrong zonepath.
4036	 */
4037	if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
4038		(void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
4039		return (Z_INVAL);
4040	}
4041
4042	/*
4043	 * If the dirpath is already gone (maybe it was manually removed) then
4044	 * we just return Z_OK so that the cleanup is successful.
4045	 */
4046	if ((dirp = opendir(zonepath)) == NULL)
4047		return (Z_OK);
4048
4049	/*
4050	 * Look through the zonepath directory to see if there are any
4051	 * non-standard files/dirs.  Also skip .zfs since that might be
4052	 * there but we'll handle ZFS file systems as a special case.
4053	 */
4054	while ((dp = readdir(dirp)) != NULL) {
4055		if (strcmp(dp->d_name, ".") == 0 ||
4056		    strcmp(dp->d_name, "..") == 0 ||
4057		    strcmp(dp->d_name, ".zfs") == 0)
4058			continue;
4059
4060		for (i = 0; std_entries[i] != NULL; i++)
4061			if (strcmp(dp->d_name, std_entries[i]) == 0)
4062				break;
4063
4064		if (std_entries[i] == NULL)
4065			non_std = B_TRUE;
4066	}
4067	(void) closedir(dirp);
4068
4069	if (!all && non_std) {
4070		/*
4071		 * There are extra, non-standard directories/files in the
4072		 * zonepath so we don't want to remove the zonepath.  We
4073		 * just want to remove the standard directories and leave
4074		 * the user data alone.
4075		 */
4076		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
4077
4078		for (i = 0; std_entries[i] != NULL; i++) {
4079			char tmpbuf[MAXPATHLEN];
4080
4081			if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
4082			    zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
4083			    strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
4084			    sizeof (cmdbuf)) {
4085				(void) fprintf(stderr,
4086				    gettext("path is too long\n"));
4087				return (Z_INVAL);
4088			}
4089		}
4090
4091		status = do_subproc(cmdbuf);
4092
4093		(void) fprintf(stderr, gettext("WARNING: Unable to completely "
4094		    "remove %s\nbecause it contains additional user data.  "
4095		    "Only the standard directory\nentries have been "
4096		    "removed.\n"),
4097		    zonepath);
4098
4099		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4100		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4101	}
4102
4103	/*
4104	 * There is nothing unexpected in the zonepath, try to get rid of the
4105	 * whole zonepath directory.
4106	 *
4107	 * If the zonepath is its own zfs file system, try to destroy the
4108	 * file system.  If that fails for some reason (e.g. it has clones)
4109	 * then we'll just remove the contents of the zonepath.
4110	 */
4111	if (is_zonepath_zfs(zonepath)) {
4112		if (destroy_zfs(zonepath) == Z_OK)
4113			return (Z_OK);
4114		(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
4115		    " %s/*", zonepath);
4116		status = do_subproc(cmdbuf);
4117		return ((subproc_status(RMCOMMAND, status, B_TRUE) ==
4118		    ZONE_SUBPROC_OK) ? Z_OK : Z_ERR);
4119	}
4120
4121	(void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
4122	    zonepath);
4123	status = do_subproc(cmdbuf);
4124
4125	return ((subproc_status(RMCOMMAND, status, B_TRUE) == ZONE_SUBPROC_OK)
4126	    ? Z_OK : Z_ERR);
4127}
4128
4129static int
4130move_func(int argc, char *argv[])
4131{
4132	char *new_zonepath = NULL;
4133	int lockfd;
4134	int err, arg;
4135	char zonepath[MAXPATHLEN];
4136	zone_dochandle_t handle;
4137	boolean_t fast;
4138	boolean_t is_zfs = B_FALSE;
4139	struct dirent *dp;
4140	DIR *dirp;
4141	boolean_t empty = B_TRUE;
4142	boolean_t revert;
4143	struct stat zonepath_buf;
4144	struct stat new_zonepath_buf;
4145
4146	if (zonecfg_in_alt_root()) {
4147		zerror(gettext("cannot move zone in alternate root"));
4148		return (Z_ERR);
4149	}
4150
4151	optind = 0;
4152	if ((arg = getopt(argc, argv, "?")) != EOF) {
4153		switch (arg) {
4154		case '?':
4155			sub_usage(SHELP_MOVE, CMD_MOVE);
4156			return (optopt == '?' ? Z_OK : Z_USAGE);
4157		default:
4158			sub_usage(SHELP_MOVE, CMD_MOVE);
4159			return (Z_USAGE);
4160		}
4161	}
4162	if (argc != (optind + 1)) {
4163		sub_usage(SHELP_MOVE, CMD_MOVE);
4164		return (Z_USAGE);
4165	}
4166	new_zonepath = argv[optind];
4167	if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE, B_FALSE)
4168	    != Z_OK)
4169		return (Z_ERR);
4170	if (verify_details(CMD_MOVE, argv) != Z_OK)
4171		return (Z_ERR);
4172
4173	/*
4174	 * Check out the new zonepath.  This has the side effect of creating
4175	 * a directory for the new zonepath.  We depend on this later when we
4176	 * stat to see if we are doing a cross file system move or not.
4177	 */
4178	if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
4179		return (Z_ERR);
4180
4181	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4182	    != Z_OK) {
4183		errno = err;
4184		zperror2(target_zone, gettext("could not get zone path"));
4185		return (Z_ERR);
4186	}
4187
4188	if (stat(zonepath, &zonepath_buf) == -1) {
4189		zperror(gettext("could not stat zone path"), B_FALSE);
4190		return (Z_ERR);
4191	}
4192
4193	if (stat(new_zonepath, &new_zonepath_buf) == -1) {
4194		zperror(gettext("could not stat new zone path"), B_FALSE);
4195		return (Z_ERR);
4196	}
4197
4198	/*
4199	 * Check if the destination directory is empty.
4200	 */
4201	if ((dirp = opendir(new_zonepath)) == NULL) {
4202		zperror(gettext("could not open new zone path"), B_FALSE);
4203		return (Z_ERR);
4204	}
4205	while ((dp = readdir(dirp)) != (struct dirent *)0) {
4206		if (strcmp(dp->d_name, ".") == 0 ||
4207		    strcmp(dp->d_name, "..") == 0)
4208			continue;
4209		empty = B_FALSE;
4210		break;
4211	}
4212	(void) closedir(dirp);
4213
4214	/* Error if there is anything in the destination directory. */
4215	if (!empty) {
4216		(void) fprintf(stderr, gettext("could not move zone to %s: "
4217		    "directory not empty\n"), new_zonepath);
4218		return (Z_ERR);
4219	}
4220
4221	/* Don't move the zone if anything is still mounted there */
4222	if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
4223		zerror(gettext("These file systems are mounted on "
4224		    "subdirectories of %s.\n"), zonepath);
4225		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
4226		return (Z_ERR);
4227	}
4228
4229	/*
4230	 * Check if we are moving in the same file system and can do a fast
4231	 * move or if we are crossing file systems and have to copy the data.
4232	 */
4233	fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
4234
4235	if ((handle = zonecfg_init_handle()) == NULL) {
4236		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4237		return (Z_ERR);
4238	}
4239
4240	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4241		errno = err;
4242		zperror(cmd_to_str(CMD_MOVE), B_TRUE);
4243		zonecfg_fini_handle(handle);
4244		return (Z_ERR);
4245	}
4246
4247	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4248		zerror(gettext("another %s may have an operation in progress."),
4249		    "zoneadm");
4250		zonecfg_fini_handle(handle);
4251		return (Z_ERR);
4252	}
4253
4254	/*
4255	 * We're making some file system changes now so we have to clean up
4256	 * the file system before we are done.  This will either clean up the
4257	 * new zonepath if the zonecfg update failed or it will clean up the
4258	 * old zonepath if everything is ok.
4259	 */
4260	revert = B_TRUE;
4261
4262	if (is_zonepath_zfs(zonepath) &&
4263	    move_zfs(zonepath, new_zonepath) != Z_ERR) {
4264		is_zfs = B_TRUE;
4265
4266	} else if (fast) {
4267		/* same file system, use rename for a quick move */
4268
4269		/*
4270		 * Remove the new_zonepath directory that got created above
4271		 * during the validation.  It gets in the way of the rename.
4272		 */
4273		if (rmdir(new_zonepath) != 0) {
4274			zperror(gettext("could not rmdir new zone path"),
4275			    B_FALSE);
4276			zonecfg_fini_handle(handle);
4277			release_lock_file(lockfd);
4278			return (Z_ERR);
4279		}
4280
4281		if (rename(zonepath, new_zonepath) != 0) {
4282			/*
4283			 * If this fails we don't need to do all of the
4284			 * cleanup that happens for the rest of the code
4285			 * so just return from this error.
4286			 */
4287			zperror(gettext("could not move zone"), B_FALSE);
4288			zonecfg_fini_handle(handle);
4289			release_lock_file(lockfd);
4290			return (Z_ERR);
4291		}
4292
4293	} else {
4294		/*
4295		 * Attempt to create a ZFS fs for the new zonepath.  As usual,
4296		 * we don't care if this works or not since we always have the
4297		 * default behavior of a simple directory for the zonepath.
4298		 */
4299		create_zfs_zonepath(new_zonepath);
4300
4301		(void) printf(gettext(
4302		    "Moving across file systems; copying zonepath %s..."),
4303		    zonepath);
4304		(void) fflush(stdout);
4305
4306		err = copy_zone(zonepath, new_zonepath);
4307
4308		(void) printf("\n");
4309		if (err != Z_OK)
4310			goto done;
4311	}
4312
4313	if ((err = zonecfg_set_zonepath(handle, new_zonepath)) != Z_OK) {
4314		errno = err;
4315		zperror(gettext("could not set new zonepath"), B_TRUE);
4316		goto done;
4317	}
4318
4319	if ((err = zonecfg_save(handle)) != Z_OK) {
4320		errno = err;
4321		zperror(gettext("zonecfg save failed"), B_TRUE);
4322		goto done;
4323	}
4324
4325	revert = B_FALSE;
4326
4327done:
4328	zonecfg_fini_handle(handle);
4329	release_lock_file(lockfd);
4330
4331	/*
4332	 * Clean up the file system based on how things went.  We either
4333	 * clean up the new zonepath if the operation failed for some reason
4334	 * or we clean up the old zonepath if everything is ok.
4335	 */
4336	if (revert) {
4337		/* The zonecfg update failed, cleanup the new zonepath. */
4338		if (is_zfs) {
4339			if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
4340				(void) fprintf(stderr, gettext("could not "
4341				    "restore zonepath, the zfs mountpoint is "
4342				    "set as:\n%s\n"), new_zonepath);
4343				/*
4344				 * err is already != Z_OK since we're reverting
4345				 */
4346			}
4347
4348		} else if (fast) {
4349			if (rename(new_zonepath, zonepath) != 0) {
4350				zperror(gettext("could not restore zonepath"),
4351				    B_FALSE);
4352				/*
4353				 * err is already != Z_OK since we're reverting
4354				 */
4355			}
4356		} else {
4357			(void) printf(gettext("Cleaning up zonepath %s..."),
4358			    new_zonepath);
4359			(void) fflush(stdout);
4360			err = cleanup_zonepath(new_zonepath, B_TRUE);
4361			(void) printf("\n");
4362
4363			if (err != Z_OK) {
4364				errno = err;
4365				zperror(gettext("could not remove new "
4366				    "zonepath"), B_TRUE);
4367			} else {
4368				/*
4369				 * Because we're reverting we know the mainline
4370				 * code failed but we just reused the err
4371				 * variable so we reset it back to Z_ERR.
4372				 */
4373				err = Z_ERR;
4374			}
4375		}
4376
4377	} else {
4378		/* The move was successful, cleanup the old zonepath. */
4379		if (!is_zfs && !fast) {
4380			(void) printf(
4381			    gettext("Cleaning up zonepath %s..."), zonepath);
4382			(void) fflush(stdout);
4383			err = cleanup_zonepath(zonepath, B_TRUE);
4384			(void) printf("\n");
4385
4386			if (err != Z_OK) {
4387				errno = err;
4388				zperror(gettext("could not remove zonepath"),
4389				    B_TRUE);
4390			}
4391		}
4392	}
4393
4394	return ((err == Z_OK) ? Z_OK : Z_ERR);
4395}
4396
4397static int
4398detach_func(int argc, char *argv[])
4399{
4400	int lockfd;
4401	int err, arg;
4402	char zonepath[MAXPATHLEN];
4403	zone_dochandle_t handle;
4404	boolean_t execute = B_TRUE;
4405
4406	if (zonecfg_in_alt_root()) {
4407		zerror(gettext("cannot detach zone in alternate root"));
4408		return (Z_ERR);
4409	}
4410
4411	optind = 0;
4412	if ((arg = getopt(argc, argv, "?n")) != EOF) {
4413		switch (arg) {
4414		case '?':
4415			sub_usage(SHELP_DETACH, CMD_DETACH);
4416			return (optopt == '?' ? Z_OK : Z_USAGE);
4417		case 'n':
4418			execute = B_FALSE;
4419			break;
4420		default:
4421			sub_usage(SHELP_DETACH, CMD_DETACH);
4422			return (Z_USAGE);
4423		}
4424	}
4425
4426	if (execute) {
4427		if (sanity_check(target_zone, CMD_DETACH, B_FALSE, B_TRUE,
4428		    B_FALSE) != Z_OK)
4429			return (Z_ERR);
4430		if (verify_details(CMD_DETACH, argv) != Z_OK)
4431			return (Z_ERR);
4432	} else {
4433		/*
4434		 * We want a dry-run to work for a non-privileged user so we
4435		 * only do minimal validation.
4436		 */
4437		if (getzoneid() != GLOBAL_ZONEID) {
4438			zerror(gettext("must be in the global zone to %s a "
4439			    "zone."), cmd_to_str(CMD_DETACH));
4440			return (Z_ERR);
4441		}
4442
4443		if (target_zone == NULL) {
4444			zerror(gettext("no zone specified"));
4445			return (Z_ERR);
4446		}
4447
4448		if (strcmp(target_zone, GLOBAL_ZONENAME) == 0) {
4449			zerror(gettext("%s operation is invalid for the "
4450			    "global zone."), cmd_to_str(CMD_DETACH));
4451			return (Z_ERR);
4452		}
4453	}
4454
4455	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4456	    != Z_OK) {
4457		errno = err;
4458		zperror2(target_zone, gettext("could not get zone path"));
4459		return (Z_ERR);
4460	}
4461
4462	/* Don't detach the zone if anything is still mounted there */
4463	if (execute && zonecfg_find_mounts(zonepath, NULL, NULL)) {
4464		zerror(gettext("These file systems are mounted on "
4465		    "subdirectories of %s.\n"), zonepath);
4466		(void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
4467		return (Z_ERR);
4468	}
4469
4470	if ((handle = zonecfg_init_handle()) == NULL) {
4471		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4472		return (Z_ERR);
4473	}
4474
4475	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4476		errno = err;
4477		zperror(cmd_to_str(CMD_DETACH), B_TRUE);
4478		zonecfg_fini_handle(handle);
4479		return (Z_ERR);
4480	}
4481
4482	if (execute && grab_lock_file(target_zone, &lockfd) != Z_OK) {
4483		zerror(gettext("another %s may have an operation in progress."),
4484		    "zoneadm");
4485		zonecfg_fini_handle(handle);
4486		return (Z_ERR);
4487	}
4488
4489	if ((err = zonecfg_get_detach_info(handle, B_TRUE)) != Z_OK) {
4490		errno = err;
4491		zperror(gettext("getting the detach information failed"),
4492		    B_TRUE);
4493		goto done;
4494	}
4495
4496	if ((err = zonecfg_detach_save(handle, (execute ? 0 : ZONE_DRY_RUN)))
4497	    != Z_OK) {
4498		errno = err;
4499		zperror(gettext("saving the detach manifest failed"), B_TRUE);
4500		goto done;
4501	}
4502
4503	/*
4504	 * Set the zone state back to configured unless we are running with the
4505	 * no-execute option.
4506	 */
4507	if (execute && (err = zone_set_state(target_zone,
4508	    ZONE_STATE_CONFIGURED)) != Z_OK) {
4509		errno = err;
4510		zperror(gettext("could not reset state"), B_TRUE);
4511	}
4512
4513done:
4514	zonecfg_fini_handle(handle);
4515	if (execute)
4516		release_lock_file(lockfd);
4517
4518	return ((err == Z_OK) ? Z_OK : Z_ERR);
4519}
4520
4521/*
4522 * During attach we go through and fix up the /dev entries for the zone
4523 * we are attaching.  In order to regenerate /dev with the correct devices,
4524 * the old /dev will be removed, the zone readied (which generates a new
4525 * /dev) then halted, then we use the info from the manifest to update
4526 * the modes, owners, etc. on the new /dev.
4527 */
4528static int
4529dev_fix(zone_dochandle_t handle)
4530{
4531	int			res;
4532	int			err;
4533	int			status;
4534	struct zone_devpermtab	devtab;
4535	zone_cmd_arg_t		zarg;
4536	char			devpath[MAXPATHLEN];
4537				/* 6: "exec " and " " */
4538	char			cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6];
4539
4540	if ((res = zonecfg_get_zonepath(handle, devpath, sizeof (devpath)))
4541	    != Z_OK)
4542		return (res);
4543
4544	if (strlcat(devpath, "/dev", sizeof (devpath)) >= sizeof (devpath))
4545		return (Z_TOO_BIG);
4546
4547	/*
4548	 * "exec" the command so that the returned status is that of
4549	 * RMCOMMAND and not the shell.
4550	 */
4551	(void) snprintf(cmdbuf, sizeof (cmdbuf), EXEC_PREFIX RMCOMMAND " %s",
4552	    devpath);
4553	status = do_subproc(cmdbuf);
4554	if ((err = subproc_status(RMCOMMAND, status, B_TRUE)) !=
4555	    ZONE_SUBPROC_OK) {
4556		(void) fprintf(stderr,
4557		    gettext("could not remove existing /dev\n"));
4558		return (Z_ERR);
4559	}
4560
4561	/* In order to ready the zone, it must be in the installed state */
4562	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4563		errno = err;
4564		zperror(gettext("could not reset state"), B_TRUE);
4565		return (Z_ERR);
4566	}
4567
4568	/* We have to ready the zone to regen the dev tree */
4569	zarg.cmd = Z_READY;
4570	if (call_zoneadmd(target_zone, &zarg) != 0) {
4571		zerror(gettext("call to %s failed"), "zoneadmd");
4572		/* attempt to restore zone to configured state */
4573		(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4574		return (Z_ERR);
4575	}
4576
4577	zarg.cmd = Z_HALT;
4578	if (call_zoneadmd(target_zone, &zarg) != 0) {
4579		zerror(gettext("call to %s failed"), "zoneadmd");
4580		/* attempt to restore zone to configured state */
4581		(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4582		return (Z_ERR);
4583	}
4584
4585	/* attempt to restore zone to configured state */
4586	(void) zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4587
4588	if (zonecfg_setdevperment(handle) != Z_OK) {
4589		(void) fprintf(stderr,
4590		    gettext("unable to enumerate device entries\n"));
4591		return (Z_ERR);
4592	}
4593
4594	while (zonecfg_getdevperment(handle, &devtab) == Z_OK) {
4595		int err;
4596
4597		if ((err = zonecfg_devperms_apply(handle,
4598		    devtab.zone_devperm_name, devtab.zone_devperm_uid,
4599		    devtab.zone_devperm_gid, devtab.zone_devperm_mode,
4600		    devtab.zone_devperm_acl)) != Z_OK && err != Z_INVAL)
4601			(void) fprintf(stderr, gettext("error updating device "
4602			    "%s: %s\n"), devtab.zone_devperm_name,
4603			    zonecfg_strerror(err));
4604
4605		free(devtab.zone_devperm_acl);
4606	}
4607
4608	(void) zonecfg_enddevperment(handle);
4609
4610	return (Z_OK);
4611}
4612
4613/*
4614 * Validate attaching a zone but don't actually do the work.  The zone
4615 * does not have to exist, so there is some complexity getting a new zone
4616 * configuration set up so that we can perform the validation.  This is
4617 * handled within zonecfg_attach_manifest() which returns two handles; one
4618 * for the the full configuration to validate (rem_handle) and the other
4619 * (local_handle) containing only the zone configuration derived from the
4620 * manifest.
4621 */
4622static int
4623dryrun_attach(char *manifest_path, char *argv[])
4624{
4625	int fd;
4626	int err;
4627	int res;
4628	zone_dochandle_t local_handle;
4629	zone_dochandle_t rem_handle = NULL;
4630
4631	if (strcmp(manifest_path, "-") == 0) {
4632		fd = 0;
4633	} else if ((fd = open(manifest_path, O_RDONLY)) < 0) {
4634		zperror(gettext("could not open manifest path"), B_FALSE);
4635		return (Z_ERR);
4636	}
4637
4638	if ((local_handle = zonecfg_init_handle()) == NULL) {
4639		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4640		res = Z_ERR;
4641		goto done;
4642	}
4643
4644	if ((rem_handle = zonecfg_init_handle()) == NULL) {
4645		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4646		res = Z_ERR;
4647		goto done;
4648	}
4649
4650	if ((err = zonecfg_attach_manifest(fd, local_handle, rem_handle))
4651	    != Z_OK) {
4652		if (err == Z_INVALID_DOCUMENT)
4653			zerror(gettext("Cannot attach to an earlier release "
4654			    "of the operating system"));
4655		else
4656			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4657		res = Z_ERR;
4658		goto done;
4659	}
4660
4661	/*
4662	 * Retrieve remote handle brand type and determine whether it is
4663	 * native or not.
4664	 */
4665	if (zonecfg_get_brand(rem_handle, target_brand, sizeof (target_brand))
4666	    != Z_OK) {
4667		zerror(gettext("missing or invalid brand"));
4668		exit(Z_ERR);
4669	}
4670	is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
4671
4672	res = verify_handle(CMD_ATTACH, local_handle, argv);
4673
4674	/* Get the detach information for the locally defined zone. */
4675	if ((err = zonecfg_get_detach_info(local_handle, B_FALSE)) != Z_OK) {
4676		errno = err;
4677		zperror(gettext("getting the attach information failed"),
4678		    B_TRUE);
4679		res = Z_ERR;
4680	} else {
4681		/* sw_cmp prints error msgs as necessary */
4682		if (sw_cmp(local_handle, rem_handle, SW_CMP_NONE) != Z_OK)
4683			res = Z_ERR;
4684	}
4685
4686done:
4687	if (strcmp(manifest_path, "-") != 0)
4688		(void) close(fd);
4689
4690	zonecfg_fini_handle(local_handle);
4691	zonecfg_fini_handle(rem_handle);
4692
4693	return ((res == Z_OK) ? Z_OK : Z_ERR);
4694}
4695
4696static int
4697attach_func(int argc, char *argv[])
4698{
4699	int lockfd;
4700	int err, arg;
4701	boolean_t force = B_FALSE;
4702	zone_dochandle_t handle;
4703	zone_dochandle_t athandle = NULL;
4704	char zonepath[MAXPATHLEN];
4705	char brand[MAXNAMELEN], atbrand[MAXNAMELEN];
4706	boolean_t execute = B_TRUE;
4707	char *manifest_path;
4708
4709	if (zonecfg_in_alt_root()) {
4710		zerror(gettext("cannot attach zone in alternate root"));
4711		return (Z_ERR);
4712	}
4713
4714	optind = 0;
4715	if ((arg = getopt(argc, argv, "?Fn:")) != EOF) {
4716		switch (arg) {
4717		case '?':
4718			sub_usage(SHELP_ATTACH, CMD_ATTACH);
4719			return (optopt == '?' ? Z_OK : Z_USAGE);
4720		case 'F':
4721			force = B_TRUE;
4722			break;
4723		case 'n':
4724			execute = B_FALSE;
4725			manifest_path = optarg;
4726			break;
4727		default:
4728			sub_usage(SHELP_ATTACH, CMD_ATTACH);
4729			return (Z_USAGE);
4730		}
4731	}
4732
4733	/*
4734	 * If the no-execute option was specified, we need to branch down
4735	 * a completely different path since there is no zone required to be
4736	 * configured for this option.
4737	 */
4738	if (!execute)
4739		return (dryrun_attach(manifest_path, argv));
4740
4741	if (sanity_check(target_zone, CMD_ATTACH, B_FALSE, B_TRUE, B_FALSE)
4742	    != Z_OK)
4743		return (Z_ERR);
4744	if (verify_details(CMD_ATTACH, argv) != Z_OK)
4745		return (Z_ERR);
4746
4747	if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
4748	    != Z_OK) {
4749		errno = err;
4750		zperror2(target_zone, gettext("could not get zone path"));
4751		return (Z_ERR);
4752	}
4753
4754	if ((handle = zonecfg_init_handle()) == NULL) {
4755		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4756		return (Z_ERR);
4757	}
4758
4759	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
4760		errno = err;
4761		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4762		zonecfg_fini_handle(handle);
4763		return (Z_ERR);
4764	}
4765
4766	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4767		zerror(gettext("another %s may have an operation in progress."),
4768		    "zoneadm");
4769		zonecfg_fini_handle(handle);
4770		return (Z_ERR);
4771	}
4772
4773	if (force)
4774		goto forced;
4775
4776	if ((athandle = zonecfg_init_handle()) == NULL) {
4777		zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4778		goto done;
4779	}
4780
4781	if ((err = zonecfg_get_attach_handle(zonepath, target_zone, B_TRUE,
4782	    athandle)) != Z_OK) {
4783		if (err == Z_NO_ZONE)
4784			zerror(gettext("Not a detached zone"));
4785		else if (err == Z_INVALID_DOCUMENT)
4786			zerror(gettext("Cannot attach to an earlier release "
4787			    "of the operating system"));
4788		else
4789			zperror(cmd_to_str(CMD_ATTACH), B_TRUE);
4790		goto done;
4791	}
4792
4793	/* Get the detach information for the locally defined zone. */
4794	if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
4795		errno = err;
4796		zperror(gettext("getting the attach information failed"),
4797		    B_TRUE);
4798		goto done;
4799	}
4800
4801	/*
4802	 * Ensure that the detached and locally defined zones are both of
4803	 * the same brand.
4804	 */
4805	if ((zonecfg_get_brand(handle, brand, sizeof (brand)) != 0) ||
4806	    (zonecfg_get_brand(athandle, atbrand, sizeof (atbrand)) != 0)) {
4807		err = Z_ERR;
4808		zerror(gettext("missing or invalid brand"));
4809		goto done;
4810	}
4811
4812	if (strcmp(atbrand, brand) != NULL) {
4813		err = Z_ERR;
4814		zerror(gettext("Trying to attach a '%s' zone to a '%s' "
4815		    "configuration."), atbrand, brand);
4816		goto done;
4817	}
4818
4819	/* sw_cmp prints error msgs as necessary */
4820	if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
4821		goto done;
4822
4823	if ((err = dev_fix(athandle)) != Z_OK)
4824		goto done;
4825
4826forced:
4827
4828	zonecfg_rm_detached(handle, force);
4829
4830	if ((err = zone_set_state(target_zone, ZONE_STATE_INSTALLED)) != Z_OK) {
4831		errno = err;
4832		zperror(gettext("could not reset state"), B_TRUE);
4833	}
4834
4835done:
4836	zonecfg_fini_handle(handle);
4837	release_lock_file(lockfd);
4838	if (athandle != NULL)
4839		zonecfg_fini_handle(athandle);
4840
4841	return ((err == Z_OK) ? Z_OK : Z_ERR);
4842}
4843
4844/*
4845 * On input, TRUE => yes, FALSE => no.
4846 * On return, TRUE => 1, FALSE => 0, could not ask => -1.
4847 */
4848
4849static int
4850ask_yesno(boolean_t default_answer, const char *question)
4851{
4852	char line[64];	/* should be large enough to answer yes or no */
4853
4854	if (!isatty(STDIN_FILENO))
4855		return (-1);
4856	for (;;) {
4857		(void) printf("%s (%s)? ", question,
4858		    default_answer ? "[y]/n" : "y/[n]");
4859		if (fgets(line, sizeof (line), stdin) == NULL ||
4860		    line[0] == '\n')
4861			return (default_answer ? 1 : 0);
4862		if (tolower(line[0]) == 'y')
4863			return (1);
4864		if (tolower(line[0]) == 'n')
4865			return (0);
4866	}
4867}
4868
4869static int
4870uninstall_func(int argc, char *argv[])
4871{
4872	char line[ZONENAME_MAX + 128];	/* Enough for "Are you sure ..." */
4873	char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
4874	boolean_t force = B_FALSE;
4875	int lockfd, answer;
4876	int err, arg;
4877
4878	if (zonecfg_in_alt_root()) {
4879		zerror(gettext("cannot uninstall zone in alternate root"));
4880		return (Z_ERR);
4881	}
4882
4883	optind = 0;
4884	while ((arg = getopt(argc, argv, "?F")) != EOF) {
4885		switch (arg) {
4886		case '?':
4887			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4888			return (optopt == '?' ? Z_OK : Z_USAGE);
4889		case 'F':
4890			force = B_TRUE;
4891			break;
4892		default:
4893			sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4894			return (Z_USAGE);
4895		}
4896	}
4897	if (argc > optind) {
4898		sub_usage(SHELP_UNINSTALL, CMD_UNINSTALL);
4899		return (Z_USAGE);
4900	}
4901
4902	if (sanity_check(target_zone, CMD_UNINSTALL, B_FALSE, B_TRUE, B_FALSE)
4903	    != Z_OK)
4904		return (Z_ERR);
4905
4906	/*
4907	 * Invoke brand-specific handler.
4908	 */
4909	if (invoke_brand_handler(CMD_UNINSTALL, argv) != Z_OK)
4910		return (Z_ERR);
4911
4912	if (!force) {
4913		(void) snprintf(line, sizeof (line),
4914		    gettext("Are you sure you want to %s zone %s"),
4915		    cmd_to_str(CMD_UNINSTALL), target_zone);
4916		if ((answer = ask_yesno(B_FALSE, line)) == 0) {
4917			return (Z_OK);
4918		} else if (answer == -1) {
4919			zerror(gettext("Input not from terminal and -F "
4920			    "not specified: %s not done."),
4921			    cmd_to_str(CMD_UNINSTALL));
4922			return (Z_ERR);
4923		}
4924	}
4925
4926	if ((err = zone_get_zonepath(target_zone, zonepath,
4927	    sizeof (zonepath))) != Z_OK) {
4928		errno = err;
4929		zperror2(target_zone, gettext("could not get zone path"));
4930		return (Z_ERR);
4931	}
4932	if ((err = zone_get_rootpath(target_zone, rootpath,
4933	    sizeof (rootpath))) != Z_OK) {
4934		errno = err;
4935		zperror2(target_zone, gettext("could not get root path"));
4936		return (Z_ERR);
4937	}
4938
4939	/*
4940	 * If there seems to be a zoneadmd running for this zone, call it
4941	 * to tell it that an uninstall is happening; if all goes well it
4942	 * will then shut itself down.
4943	 */
4944	if (ping_zoneadmd(target_zone) == Z_OK) {
4945		zone_cmd_arg_t zarg;
4946		zarg.cmd = Z_NOTE_UNINSTALLING;
4947		/* we don't care too much if this fails... just plow on */
4948		(void) call_zoneadmd(target_zone, &zarg);
4949	}
4950
4951	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
4952		zerror(gettext("another %s may have an operation in progress."),
4953		    "zoneadm");
4954		return (Z_ERR);
4955	}
4956
4957	/* Don't uninstall the zone if anything is mounted there */
4958	err = zonecfg_find_mounts(rootpath, NULL, NULL);
4959	if (err) {
4960		zerror(gettext("These file systems are mounted on "
4961		    "subdirectories of %s.\n"), rootpath);
4962		(void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
4963		return (Z_ERR);
4964	}
4965
4966	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
4967	if (err != Z_OK) {
4968		errno = err;
4969		zperror2(target_zone, gettext("could not set state"));
4970		goto bad;
4971	}
4972
4973	if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
4974		errno = err;
4975		zperror2(target_zone, gettext("cleaning up zonepath failed"));
4976		goto bad;
4977	}
4978
4979	err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4980	if (err != Z_OK) {
4981		errno = err;
4982		zperror2(target_zone, gettext("could not reset state"));
4983	}
4984bad:
4985	release_lock_file(lockfd);
4986	return (err);
4987}
4988
4989/* ARGSUSED */
4990static int
4991mount_func(int argc, char *argv[])
4992{
4993	zone_cmd_arg_t zarg;
4994	boolean_t force = B_FALSE;
4995	int arg;
4996
4997	/*
4998	 * The only supported subargument to the "mount" subcommand is
4999	 * "-f", which forces us to mount a zone in the INCOMPLETE state.
5000	 */
5001	optind = 0;
5002	if ((arg = getopt(argc, argv, "f")) != EOF) {
5003		switch (arg) {
5004		case 'f':
5005			force = B_TRUE;
5006			break;
5007		default:
5008			return (Z_USAGE);
5009		}
5010	}
5011	if (argc > optind)
5012		return (Z_USAGE);
5013
5014	if (sanity_check(target_zone, CMD_MOUNT, B_FALSE, B_FALSE, force)
5015	    != Z_OK)
5016		return (Z_ERR);
5017	if (verify_details(CMD_MOUNT, argv) != Z_OK)
5018		return (Z_ERR);
5019
5020	zarg.cmd = force ? Z_FORCEMOUNT : Z_MOUNT;
5021	if (call_zoneadmd(target_zone, &zarg) != 0) {
5022		zerror(gettext("call to %s failed"), "zoneadmd");
5023		return (Z_ERR);
5024	}
5025	return (Z_OK);
5026}
5027
5028/* ARGSUSED */
5029static int
5030unmount_func(int argc, char *argv[])
5031{
5032	zone_cmd_arg_t zarg;
5033
5034	if (argc > 0)
5035		return (Z_USAGE);
5036	if (sanity_check(target_zone, CMD_UNMOUNT, B_FALSE, B_FALSE, B_FALSE)
5037	    != Z_OK)
5038		return (Z_ERR);
5039
5040	zarg.cmd = Z_UNMOUNT;
5041	if (call_zoneadmd(target_zone, &zarg) != 0) {
5042		zerror(gettext("call to %s failed"), "zoneadmd");
5043		return (Z_ERR);
5044	}
5045	return (Z_OK);
5046}
5047
5048static int
5049mark_func(int argc, char *argv[])
5050{
5051	int err, lockfd;
5052
5053	if (argc != 1 || strcmp(argv[0], "incomplete") != 0)
5054		return (Z_USAGE);
5055	if (sanity_check(target_zone, CMD_MARK, B_FALSE, B_FALSE, B_FALSE)
5056	    != Z_OK)
5057		return (Z_ERR);
5058
5059	/*
5060	 * Invoke brand-specific handler.
5061	 */
5062	if (invoke_brand_handler(CMD_MARK, argv) != Z_OK)
5063		return (Z_ERR);
5064
5065	if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
5066		zerror(gettext("another %s may have an operation in progress."),
5067		    "zoneadm");
5068		return (Z_ERR);
5069	}
5070
5071	err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
5072	if (err != Z_OK) {
5073		errno = err;
5074		zperror2(target_zone, gettext("could not set state"));
5075	}
5076	release_lock_file(lockfd);
5077
5078	return (err);
5079}
5080
5081/*
5082 * Check what scheduling class we're running under and print a warning if
5083 * we're not using FSS.
5084 */
5085static int
5086check_sched_fss(zone_dochandle_t handle)
5087{
5088	char class_name[PC_CLNMSZ];
5089
5090	if (zonecfg_get_dflt_sched_class(handle, class_name,
5091	    sizeof (class_name)) != Z_OK) {
5092		zerror(gettext("WARNING: unable to determine the zone's "
5093		    "scheduling class"));
5094	} else if (strcmp("FSS", class_name) != 0) {
5095		zerror(gettext("WARNING: The zone.cpu-shares rctl is set but\n"
5096		    "FSS is not the default scheduling class for this zone.  "
5097		    "FSS will be\nused for processes in the zone but to get "
5098		    "the full benefit of FSS,\nit should be the default "
5099		    "scheduling class.  See dispadmin(1M) for\nmore details."));
5100		return (Z_SYSTEM);
5101	}
5102
5103	return (Z_OK);
5104}
5105
5106static int
5107check_cpu_shares_sched(zone_dochandle_t handle)
5108{
5109	int err;
5110	int res = Z_OK;
5111	struct zone_rctltab rctl;
5112
5113	if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
5114		errno = err;
5115		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5116		return (err);
5117	}
5118
5119	while (zonecfg_getrctlent(handle, &rctl) == Z_OK) {
5120		if (strcmp(rctl.zone_rctl_name, "zone.cpu-shares") == 0) {
5121			if (check_sched_fss(handle) != Z_OK)
5122				res = Z_SYSTEM;
5123			break;
5124		}
5125	}
5126
5127	(void) zonecfg_endrctlent(handle);
5128
5129	return (res);
5130}
5131
5132/*
5133 * Check if there is a mix of processes running in different pools within the
5134 * zone.  This is currently only going to be called for the global zone from
5135 * apply_func but that could be generalized in the future.
5136 */
5137static boolean_t
5138mixed_pools(zoneid_t zoneid)
5139{
5140	DIR *dirp;
5141	dirent_t *dent;
5142	boolean_t mixed = B_FALSE;
5143	boolean_t poolid_set = B_FALSE;
5144	poolid_t last_poolid = 0;
5145
5146	if ((dirp = opendir("/proc")) == NULL) {
5147		zerror(gettext("could not open /proc"));
5148		return (B_FALSE);
5149	}
5150
5151	while ((dent = readdir(dirp)) != NULL) {
5152		int procfd;
5153		psinfo_t ps;
5154		char procpath[MAXPATHLEN];
5155
5156		if (dent->d_name[0] == '.')
5157			continue;
5158
5159		(void) snprintf(procpath, sizeof (procpath), "/proc/%s/psinfo",
5160		    dent->d_name);
5161
5162		if ((procfd = open(procpath, O_RDONLY)) == -1)
5163			continue;
5164
5165		if (read(procfd, &ps, sizeof (ps)) == sizeof (psinfo_t)) {
5166			/* skip processes in other zones and system processes */
5167			if (zoneid != ps.pr_zoneid || ps.pr_flag & SSYS) {
5168				(void) close(procfd);
5169				continue;
5170			}
5171
5172			if (poolid_set) {
5173				if (ps.pr_poolid != last_poolid)
5174					mixed = B_TRUE;
5175			} else {
5176				last_poolid = ps.pr_poolid;
5177				poolid_set = B_TRUE;
5178			}
5179		}
5180
5181		(void) close(procfd);
5182
5183		if (mixed)
5184			break;
5185	}
5186
5187	(void) closedir(dirp);
5188
5189	return (mixed);
5190}
5191
5192/*
5193 * Check if a persistent or temporary pool is configured for the zone.
5194 * This is currently only going to be called for the global zone from
5195 * apply_func but that could be generalized in the future.
5196 */
5197static boolean_t
5198pool_configured(zone_dochandle_t handle)
5199{
5200	int err1, err2;
5201	struct zone_psettab pset_tab;
5202	char poolname[MAXPATHLEN];
5203
5204	err1 = zonecfg_lookup_pset(handle, &pset_tab);
5205	err2 = zonecfg_get_pool(handle, poolname, sizeof (poolname));
5206
5207	if (err1 == Z_NO_ENTRY &&
5208	    (err2 == Z_NO_ENTRY || (err2 == Z_OK && strlen(poolname) == 0)))
5209		return (B_FALSE);
5210
5211	return (B_TRUE);
5212}
5213
5214/*
5215 * This is an undocumented interface which is currently only used to apply
5216 * the global zone resource management settings when the system boots.
5217 * This function does not yet properly handle updating a running system so
5218 * any projects running in the zone would be trashed if this function
5219 * were to run after the zone had booted.  It also does not reset any
5220 * rctl settings that were removed from zonecfg.  There is still work to be
5221 * done before we can properly support dynamically updating the resource
5222 * management settings for a running zone (global or non-global).  Thus, this
5223 * functionality is undocumented for now.
5224 */
5225/* ARGSUSED */
5226static int
5227apply_func(int argc, char *argv[])
5228{
5229	int err;
5230	int res = Z_OK;
5231	priv_set_t *privset;
5232	zoneid_t zoneid;
5233	zone_dochandle_t handle;
5234	struct zone_mcaptab mcap;
5235	char pool_err[128];
5236
5237	zoneid = getzoneid();
5238
5239	if (zonecfg_in_alt_root() || zoneid != GLOBAL_ZONEID ||
5240	    target_zone == NULL || strcmp(target_zone, GLOBAL_ZONENAME) != 0)
5241		return (usage(B_FALSE));
5242
5243	if ((privset = priv_allocset()) == NULL) {
5244		zerror(gettext("%s failed"), "priv_allocset");
5245		return (Z_ERR);
5246	}
5247
5248	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
5249		zerror(gettext("%s failed"), "getppriv");
5250		priv_freeset(privset);
5251		return (Z_ERR);
5252	}
5253
5254	if (priv_isfullset(privset) == B_FALSE) {
5255		(void) usage(B_FALSE);
5256		priv_freeset(privset);
5257		return (Z_ERR);
5258	}
5259	priv_freeset(privset);
5260
5261	if ((handle = zonecfg_init_handle()) == NULL) {
5262		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5263		return (Z_ERR);
5264	}
5265
5266	if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
5267		errno = err;
5268		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5269		zonecfg_fini_handle(handle);
5270		return (Z_ERR);
5271	}
5272
5273	/* specific error msgs are printed within apply_rctls */
5274	if ((err = zonecfg_apply_rctls(target_zone, handle)) != Z_OK) {
5275		errno = err;
5276		zperror(cmd_to_str(CMD_APPLY), B_TRUE);
5277		res = Z_ERR;
5278	}
5279
5280	if ((err = check_cpu_shares_sched(handle)) != Z_OK)
5281		res = Z_ERR;
5282
5283	if (pool_configured(handle)) {
5284		if (mixed_pools(zoneid)) {
5285			zerror(gettext("Zone is using multiple resource "
5286			    "pools.  The pool\nconfiguration cannot be "
5287			    "applied without rebooting."));
5288			res = Z_ERR;
5289		} else {
5290
5291			/*
5292			 * The next two blocks of code attempt to set up
5293			 * temporary pools as well as persistent pools.  In
5294			 * both cases we call the functions unconditionally.
5295			 * Within each funtion the code will check if the zone
5296			 * is actually configured for a temporary pool or
5297			 * persistent pool and just return if there is nothing
5298			 * to do.
5299			 */
5300			if ((err = zonecfg_bind_tmp_pool(handle, zoneid,
5301			    pool_err, sizeof (pool_err))) != Z_OK) {
5302				if (err == Z_POOL || err == Z_POOL_CREATE ||
5303				    err == Z_POOL_BIND)
5304					zerror("%s: %s", zonecfg_strerror(err),
5305					    pool_err);
5306				else
5307					zerror(gettext("could not bind zone to "
5308					    "temporary pool: %s"),
5309					    zonecfg_strerror(err));
5310				res = Z_ERR;
5311			}
5312
5313			if ((err = zonecfg_bind_pool(handle, zoneid, pool_err,
5314			    sizeof (pool_err))) != Z_OK) {
5315				if (err == Z_POOL || err == Z_POOL_BIND)
5316					zerror("%s: %s", zonecfg_strerror(err),
5317					    pool_err);
5318				else
5319					zerror("%s", zonecfg_strerror(err));
5320			}
5321		}
5322	}
5323
5324	/*
5325	 * If a memory cap is configured, set the cap in the kernel using
5326	 * zone_setattr() and make sure the rcapd SMF service is enabled.
5327	 */
5328	if (zonecfg_getmcapent(handle, &mcap) == Z_OK) {
5329		uint64_t num;
5330		char smf_err[128];
5331
5332		num = (uint64_t)strtoll(mcap.zone_physmem_cap, NULL, 10);
5333		if (zone_setattr(zoneid, ZONE_ATTR_PHYS_MCAP, &num, 0) == -1) {
5334			zerror(gettext("could not set zone memory cap"));
5335			res = Z_ERR;
5336		}
5337
5338		if (zonecfg_enable_rcapd(smf_err, sizeof (smf_err)) != Z_OK) {
5339			zerror(gettext("enabling system/rcap service failed: "
5340			    "%s"), smf_err);
5341			res = Z_ERR;
5342		}
5343	}
5344
5345	zonecfg_fini_handle(handle);
5346
5347	return (res);
5348}
5349
5350static int
5351help_func(int argc, char *argv[])
5352{
5353	int arg, cmd_num;
5354
5355	if (argc == 0) {
5356		(void) usage(B_TRUE);
5357		return (Z_OK);
5358	}
5359	optind = 0;
5360	if ((arg = getopt(argc, argv, "?")) != EOF) {
5361		switch (arg) {
5362		case '?':
5363			sub_usage(SHELP_HELP, CMD_HELP);
5364			return (optopt == '?' ? Z_OK : Z_USAGE);
5365		default:
5366			sub_usage(SHELP_HELP, CMD_HELP);
5367			return (Z_USAGE);
5368		}
5369	}
5370	while (optind < argc) {
5371		/* Private commands have NULL short_usage; omit them */
5372		if ((cmd_num = cmd_match(argv[optind])) < 0 ||
5373		    cmdtab[cmd_num].short_usage == NULL) {
5374			sub_usage(SHELP_HELP, CMD_HELP);
5375			return (Z_USAGE);
5376		}
5377		sub_usage(cmdtab[cmd_num].short_usage, cmd_num);
5378		optind++;
5379	}
5380	return (Z_OK);
5381}
5382
5383/*
5384 * Returns: CMD_MIN thru CMD_MAX on success, -1 on error
5385 */
5386
5387static int
5388cmd_match(char *cmd)
5389{
5390	int i;
5391
5392	for (i = CMD_MIN; i <= CMD_MAX; i++) {
5393		/* return only if there is an exact match */
5394		if (strcmp(cmd, cmdtab[i].cmd_name) == 0)
5395			return (cmdtab[i].cmd_num);
5396	}
5397	return (-1);
5398}
5399
5400static int
5401parse_and_run(int argc, char *argv[])
5402{
5403	int i = cmd_match(argv[0]);
5404
5405	if (i < 0)
5406		return (usage(B_FALSE));
5407	return (cmdtab[i].handler(argc - 1, &(argv[1])));
5408}
5409
5410static char *
5411get_execbasename(char *execfullname)
5412{
5413	char *last_slash, *execbasename;
5414
5415	/* guard against '/' at end of command invocation */
5416	for (;;) {
5417		last_slash = strrchr(execfullname, '/');
5418		if (last_slash == NULL) {
5419			execbasename = execfullname;
5420			break;
5421		} else {
5422			execbasename = last_slash + 1;
5423			if (*execbasename == '\0') {
5424				*last_slash = '\0';
5425				continue;
5426			}
5427			break;
5428		}
5429	}
5430	return (execbasename);
5431}
5432
5433int
5434main(int argc, char **argv)
5435{
5436	int arg;
5437	zoneid_t zid;
5438	struct stat st;
5439	char *zone_lock_env;
5440	int err;
5441
5442	if ((locale = setlocale(LC_ALL, "")) == NULL)
5443		locale = "C";
5444	(void) textdomain(TEXT_DOMAIN);
5445	setbuf(stdout, NULL);
5446	(void) sigset(SIGHUP, SIG_IGN);
5447	execname = get_execbasename(argv[0]);
5448	target_zone = NULL;
5449	if (chdir("/") != 0) {
5450		zerror(gettext("could not change directory to /."));
5451		exit(Z_ERR);
5452	}
5453
5454	if (init_zfs() != Z_OK)
5455		exit(Z_ERR);
5456
5457	while ((arg = getopt(argc, argv, "?u:z:R:")) != EOF) {
5458		switch (arg) {
5459		case '?':
5460			return (usage(B_TRUE));
5461		case 'u':
5462			target_uuid = optarg;
5463			break;
5464		case 'z':
5465			target_zone = optarg;
5466			break;
5467		case 'R':	/* private option for admin/install use */
5468			if (*optarg != '/') {
5469				zerror(gettext("root path must be absolute."));
5470				exit(Z_ERR);
5471			}
5472			if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
5473				zerror(
5474				    gettext("root path must be a directory."));
5475				exit(Z_ERR);
5476			}
5477			zonecfg_set_root(optarg);
5478			break;
5479		default:
5480			return (usage(B_FALSE));
5481		}
5482	}
5483
5484	if (optind >= argc)
5485		return (usage(B_FALSE));
5486
5487	if (target_uuid != NULL && *target_uuid != '\0') {
5488		uuid_t uuid;
5489		static char newtarget[ZONENAME_MAX];
5490
5491		if (uuid_parse(target_uuid, uuid) == -1) {
5492			zerror(gettext("illegal UUID value specified"));
5493			exit(Z_ERR);
5494		}
5495		if (zonecfg_get_name_by_uuid(uuid, newtarget,
5496		    sizeof (newtarget)) == Z_OK)
5497			target_zone = newtarget;
5498	}
5499
5500	if (target_zone != NULL && zone_get_id(target_zone, &zid) != 0) {
5501		errno = Z_NO_ZONE;
5502		zperror(target_zone, B_TRUE);
5503		exit(Z_ERR);
5504	}
5505
5506	/*
5507	 * See if we have inherited the right to manipulate this zone from
5508	 * a zoneadm instance in our ancestry.  If so, set zone_lock_cnt to
5509	 * indicate it.  If not, make that explicit in our environment.
5510	 */
5511	zone_lock_env = getenv(LOCK_ENV_VAR);
5512	if (zone_lock_env == NULL) {
5513		if (putenv(zoneadm_lock_not_held) != 0) {
5514			zperror(target_zone, B_TRUE);
5515			exit(Z_ERR);
5516		}
5517	} else {
5518		zoneadm_is_nested = B_TRUE;
5519		if (atoi(zone_lock_env) == 1)
5520			zone_lock_cnt = 1;
5521	}
5522
5523	/*
5524	 * If we are going to be operating on a single zone, retrieve its
5525	 * brand type and determine whether it is native or not.
5526	 */
5527	if ((target_zone != NULL) &&
5528	    (strcmp(target_zone, GLOBAL_ZONENAME) != NULL)) {
5529		if (zone_get_brand(target_zone, target_brand,
5530		    sizeof (target_brand)) != Z_OK) {
5531			zerror(gettext("missing or invalid brand"));
5532			exit(Z_ERR);
5533		}
5534		is_native_zone = (strcmp(target_brand, NATIVE_BRAND_NAME) == 0);
5535	}
5536
5537	err = parse_and_run(argc - optind, &argv[optind]);
5538
5539	return (err);
5540}
5541