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