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