10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51497Sdp * Common Development and Distribution License (the "License").
61497Sdp * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21222Scomay
220Sstevel@tonic-gate /*
2312227SFrank.Batschulat@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * zonecfg is a lex/yacc based command interpreter used to manage zone
280Sstevel@tonic-gate * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
290Sstevel@tonic-gate * the grammar (see zonecfg_grammar.y) builds up into commands, some of
300Sstevel@tonic-gate * which takes resources and/or properties as arguments. See the block
310Sstevel@tonic-gate * comments near the end of zonecfg_grammar.y for how the data structures
320Sstevel@tonic-gate * which keep track of these resources and properties are built up.
330Sstevel@tonic-gate *
340Sstevel@tonic-gate * The resource/property data structures are inserted into a command
350Sstevel@tonic-gate * structure (see zonecfg.h), which also keeps track of command names,
360Sstevel@tonic-gate * miscellaneous arguments, and function handlers. The grammar selects
370Sstevel@tonic-gate * the appropriate function handler, each of which takes a pointer to a
380Sstevel@tonic-gate * command structure as its sole argument, and invokes it. The grammar
390Sstevel@tonic-gate * itself is "entered" (a la the Matrix) by yyparse(), which is called
400Sstevel@tonic-gate * from read_input(), our main driving function. That in turn is called
410Sstevel@tonic-gate * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
420Sstevel@tonic-gate * of which is called from main() depending on how the program was invoked.
430Sstevel@tonic-gate *
440Sstevel@tonic-gate * The rest of this module consists of the various function handlers and
450Sstevel@tonic-gate * their helper functions. Some of these functions, particularly the
460Sstevel@tonic-gate * X_to_str() functions, which maps command, resource and property numbers
470Sstevel@tonic-gate * to strings, are used quite liberally, as doing so results in a better
480Sstevel@tonic-gate * program w/rt I18N, reducing the need for translation notes.
490Sstevel@tonic-gate */
500Sstevel@tonic-gate
510Sstevel@tonic-gate #include <sys/mntent.h>
520Sstevel@tonic-gate #include <sys/varargs.h>
530Sstevel@tonic-gate #include <sys/sysmacros.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate #include <errno.h>
562712Snn35248 #include <fcntl.h>
570Sstevel@tonic-gate #include <strings.h>
580Sstevel@tonic-gate #include <unistd.h>
590Sstevel@tonic-gate #include <ctype.h>
600Sstevel@tonic-gate #include <stdlib.h>
610Sstevel@tonic-gate #include <assert.h>
620Sstevel@tonic-gate #include <sys/stat.h>
630Sstevel@tonic-gate #include <zone.h>
640Sstevel@tonic-gate #include <arpa/inet.h>
650Sstevel@tonic-gate #include <netdb.h>
660Sstevel@tonic-gate #include <locale.h>
670Sstevel@tonic-gate #include <libintl.h>
680Sstevel@tonic-gate #include <alloca.h>
690Sstevel@tonic-gate #include <signal.h>
702712Snn35248 #include <wait.h>
710Sstevel@tonic-gate #include <libtecla.h>
72789Sahrens #include <libzfs.h>
732712Snn35248 #include <sys/brand.h>
742712Snn35248 #include <libbrand.h>
758662SJordan.Vaughan@Sun.com #include <sys/systeminfo.h>
768083SJordan.Vaughan@Sun.com #include <libdladm.h>
778083SJordan.Vaughan@Sun.com #include <libinetutil.h>
7812578SGlenn.Faden@Sun.COM #include <pwd.h>
7912748SSowmini.Varadhan@oracle.COM #include <inet/ip.h>
800Sstevel@tonic-gate
810Sstevel@tonic-gate #include <libzonecfg.h>
820Sstevel@tonic-gate #include "zonecfg.h"
830Sstevel@tonic-gate
840Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
850Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
860Sstevel@tonic-gate #endif
870Sstevel@tonic-gate
880Sstevel@tonic-gate #define PAGER "/usr/bin/more"
892712Snn35248 #define EXEC_PREFIX "exec "
902712Snn35248 #define EXEC_LEN (strlen(EXEC_PREFIX))
910Sstevel@tonic-gate
920Sstevel@tonic-gate struct help {
930Sstevel@tonic-gate uint_t cmd_num;
940Sstevel@tonic-gate char *cmd_name;
950Sstevel@tonic-gate uint_t flags;
960Sstevel@tonic-gate char *short_usage;
970Sstevel@tonic-gate };
980Sstevel@tonic-gate
990Sstevel@tonic-gate extern int yyparse(void);
1000Sstevel@tonic-gate extern int lex_lineno;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate #define MAX_LINE_LEN 1024
1030Sstevel@tonic-gate #define MAX_CMD_HIST 1024
1042712Snn35248 #define MAX_CMD_LEN 1024
1050Sstevel@tonic-gate
1063247Sgjelinek #define ONE_MB 1048576
1073247Sgjelinek
1080Sstevel@tonic-gate /*
1090Sstevel@tonic-gate * Each SHELP_ should be a simple string.
1100Sstevel@tonic-gate */
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
1130Sstevel@tonic-gate "add <property-name> <property-value>\n\t(resource scope)"
1140Sstevel@tonic-gate #define SHELP_CANCEL "cancel"
1153247Sgjelinek #define SHELP_CLEAR "clear <property-name>"
1160Sstevel@tonic-gate #define SHELP_COMMIT "commit"
1171507Sgjelinek #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
1180Sstevel@tonic-gate #define SHELP_DELETE "delete [-F]"
1190Sstevel@tonic-gate #define SHELP_END "end"
1200Sstevel@tonic-gate #define SHELP_EXIT "exit [-F]"
1210Sstevel@tonic-gate #define SHELP_EXPORT "export [-f output-file]"
1220Sstevel@tonic-gate #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
1230Sstevel@tonic-gate #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
1243247Sgjelinek #define SHELP_REMOVE "remove [-F] <resource-type> " \
1253247Sgjelinek "[ <property-name>=<property-value> ]*\n" \
1263247Sgjelinek "\t(global scope)\n" \
1273247Sgjelinek "remove <property-name> <property-value>\n" \
1283247Sgjelinek "\t(resource scope)"
1290Sstevel@tonic-gate #define SHELP_REVERT "revert [-F]"
1300Sstevel@tonic-gate #define SHELP_SELECT "select <resource-type> { <property-name>=" \
1310Sstevel@tonic-gate "<property-value> }"
1320Sstevel@tonic-gate #define SHELP_SET "set <property-name>=<property-value>"
1330Sstevel@tonic-gate #define SHELP_VERIFY "verify"
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate static struct help helptab[] = {
1360Sstevel@tonic-gate { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, },
1370Sstevel@tonic-gate { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, },
1383247Sgjelinek { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, },
1390Sstevel@tonic-gate { CMD_COMMIT, "commit", 0, SHELP_COMMIT, },
1400Sstevel@tonic-gate { CMD_CREATE, "create", 0, SHELP_CREATE, },
1410Sstevel@tonic-gate { CMD_DELETE, "delete", 0, SHELP_DELETE, },
1420Sstevel@tonic-gate { CMD_END, "end", 0, SHELP_END, },
1430Sstevel@tonic-gate { CMD_EXIT, "exit", 0, SHELP_EXIT, },
1440Sstevel@tonic-gate { CMD_EXPORT, "export", 0, SHELP_EXPORT, },
1450Sstevel@tonic-gate { CMD_HELP, "help", 0, SHELP_HELP },
1460Sstevel@tonic-gate { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, },
1470Sstevel@tonic-gate { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, },
1480Sstevel@tonic-gate { CMD_REVERT, "revert", 0, SHELP_REVERT, },
1490Sstevel@tonic-gate { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, },
1500Sstevel@tonic-gate { CMD_SET, "set", HELP_PROPS, SHELP_SET, },
1510Sstevel@tonic-gate { CMD_VERIFY, "verify", 0, SHELP_VERIFY, },
1520Sstevel@tonic-gate { 0 },
1530Sstevel@tonic-gate };
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate #define MAX_RT_STRLEN 16
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /* These *must* match the order of the RT_ define's from zonecfg.h */
15811024SJordan.Vaughan@Sun.com char *res_types[] = {
1590Sstevel@tonic-gate "unknown",
160565Sdp "zonename",
1610Sstevel@tonic-gate "zonepath",
1620Sstevel@tonic-gate "autoboot",
1630Sstevel@tonic-gate "pool",
1640Sstevel@tonic-gate "fs",
1650Sstevel@tonic-gate "net",
1660Sstevel@tonic-gate "device",
1670Sstevel@tonic-gate "rctl",
1680Sstevel@tonic-gate "attr",
169789Sahrens "dataset",
1701645Scomay "limitpriv",
1712267Sdp "bootargs",
1722712Snn35248 "brand",
1733247Sgjelinek "dedicated-cpu",
1743247Sgjelinek "capped-memory",
1753247Sgjelinek ALIAS_MAXLWPS,
1763247Sgjelinek ALIAS_MAXSHMMEM,
1773247Sgjelinek ALIAS_MAXSHMIDS,
1783247Sgjelinek ALIAS_MAXMSGIDS,
1793247Sgjelinek ALIAS_MAXSEMIDS,
1803247Sgjelinek ALIAS_SHARES,
1813247Sgjelinek "scheduling-class",
1823448Sdh155122 "ip-type",
1833792Sakolb "capped-cpu",
1848662SJordan.Vaughan@Sun.com "hostid",
18512578SGlenn.Faden@Sun.COM "admin",
18612633Sjohn.levon@sun.com "fs-allowed",
18712725SMenno.Lageman@Sun.COM ALIAS_MAXPROCS,
1880Sstevel@tonic-gate NULL
1890Sstevel@tonic-gate };
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /* These *must* match the order of the PT_ define's from zonecfg.h */
19211024SJordan.Vaughan@Sun.com char *prop_types[] = {
1930Sstevel@tonic-gate "unknown",
194565Sdp "zonename",
1950Sstevel@tonic-gate "zonepath",
1960Sstevel@tonic-gate "autoboot",
1970Sstevel@tonic-gate "pool",
1980Sstevel@tonic-gate "dir",
1990Sstevel@tonic-gate "special",
2000Sstevel@tonic-gate "type",
2010Sstevel@tonic-gate "options",
2020Sstevel@tonic-gate "address",
2030Sstevel@tonic-gate "physical",
2040Sstevel@tonic-gate "name",
2050Sstevel@tonic-gate "value",
2060Sstevel@tonic-gate "match",
2070Sstevel@tonic-gate "priv",
2080Sstevel@tonic-gate "limit",
2090Sstevel@tonic-gate "action",
2100Sstevel@tonic-gate "raw",
2111645Scomay "limitpriv",
2122267Sdp "bootargs",
2132712Snn35248 "brand",
2143247Sgjelinek "ncpus",
2153247Sgjelinek "importance",
2163247Sgjelinek "swap",
2173247Sgjelinek "locked",
2183247Sgjelinek ALIAS_SHARES,
2193247Sgjelinek ALIAS_MAXLWPS,
2203247Sgjelinek ALIAS_MAXSHMMEM,
2213247Sgjelinek ALIAS_MAXSHMIDS,
2223247Sgjelinek ALIAS_MAXMSGIDS,
2233247Sgjelinek ALIAS_MAXSEMIDS,
2243247Sgjelinek ALIAS_MAXLOCKEDMEM,
2253247Sgjelinek ALIAS_MAXSWAP,
2263247Sgjelinek "scheduling-class",
2273448Sdh155122 "ip-type",
2286076Sgfaden "defrouter",
2298662SJordan.Vaughan@Sun.com "hostid",
23012578SGlenn.Faden@Sun.COM "user",
23112578SGlenn.Faden@Sun.COM "auths",
23212633Sjohn.levon@sun.com "fs-allowed",
23312725SMenno.Lageman@Sun.COM ALIAS_MAXPROCS,
23412748SSowmini.Varadhan@oracle.COM "allowed-address",
2350Sstevel@tonic-gate NULL
2360Sstevel@tonic-gate };
2370Sstevel@tonic-gate
2381645Scomay /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
2390Sstevel@tonic-gate static char *prop_val_types[] = {
2400Sstevel@tonic-gate "simple",
2410Sstevel@tonic-gate "complex",
2420Sstevel@tonic-gate "list",
2430Sstevel@tonic-gate };
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate * The various _cmds[] lists below are for command tab-completion.
2470Sstevel@tonic-gate */
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate /*
2500Sstevel@tonic-gate * remove has a space afterwards because it has qualifiers; the other commands
2513247Sgjelinek * that have qualifiers (add, select, etc.) don't need a space here because
2520Sstevel@tonic-gate * they have their own _cmds[] lists below.
2530Sstevel@tonic-gate */
2540Sstevel@tonic-gate static const char *global_scope_cmds[] = {
2550Sstevel@tonic-gate "add",
2563247Sgjelinek "clear",
2570Sstevel@tonic-gate "commit",
2580Sstevel@tonic-gate "create",
2590Sstevel@tonic-gate "delete",
2600Sstevel@tonic-gate "exit",
2610Sstevel@tonic-gate "export",
2620Sstevel@tonic-gate "help",
2630Sstevel@tonic-gate "info",
2640Sstevel@tonic-gate "remove ",
2650Sstevel@tonic-gate "revert",
2660Sstevel@tonic-gate "select",
2670Sstevel@tonic-gate "set",
2680Sstevel@tonic-gate "verify",
2690Sstevel@tonic-gate NULL
2700Sstevel@tonic-gate };
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate static const char *add_cmds[] = {
2730Sstevel@tonic-gate "add fs",
2740Sstevel@tonic-gate "add net",
2750Sstevel@tonic-gate "add device",
2760Sstevel@tonic-gate "add rctl",
2770Sstevel@tonic-gate "add attr",
278789Sahrens "add dataset",
2793247Sgjelinek "add dedicated-cpu",
2803792Sakolb "add capped-cpu",
2813247Sgjelinek "add capped-memory",
28212578SGlenn.Faden@Sun.COM "add admin",
2833247Sgjelinek NULL
2843247Sgjelinek };
2853247Sgjelinek
2863247Sgjelinek static const char *clear_cmds[] = {
2873247Sgjelinek "clear autoboot",
2883247Sgjelinek "clear pool",
2893247Sgjelinek "clear limitpriv",
2903247Sgjelinek "clear bootargs",
2913247Sgjelinek "clear scheduling-class",
2923448Sdh155122 "clear ip-type",
2933247Sgjelinek "clear " ALIAS_MAXLWPS,
2943247Sgjelinek "clear " ALIAS_MAXSHMMEM,
2953247Sgjelinek "clear " ALIAS_MAXSHMIDS,
2963247Sgjelinek "clear " ALIAS_MAXMSGIDS,
2973247Sgjelinek "clear " ALIAS_MAXSEMIDS,
2983247Sgjelinek "clear " ALIAS_SHARES,
29912725SMenno.Lageman@Sun.COM "clear " ALIAS_MAXPROCS,
3000Sstevel@tonic-gate NULL
3010Sstevel@tonic-gate };
3020Sstevel@tonic-gate
3032607Sdp static const char *remove_cmds[] = {
3042607Sdp "remove fs ",
3052607Sdp "remove net ",
3062607Sdp "remove device ",
3072607Sdp "remove rctl ",
3082607Sdp "remove attr ",
3092607Sdp "remove dataset ",
3103247Sgjelinek "remove dedicated-cpu ",
3113792Sakolb "remove capped-cpu ",
3123247Sgjelinek "remove capped-memory ",
31312578SGlenn.Faden@Sun.COM "remove admin ",
3142607Sdp NULL
3152607Sdp };
3162607Sdp
3170Sstevel@tonic-gate static const char *select_cmds[] = {
318565Sdp "select fs ",
319565Sdp "select net ",
320565Sdp "select device ",
321565Sdp "select rctl ",
322565Sdp "select attr ",
323789Sahrens "select dataset ",
3243247Sgjelinek "select dedicated-cpu",
3253792Sakolb "select capped-cpu",
3263247Sgjelinek "select capped-memory",
32712578SGlenn.Faden@Sun.COM "select admin",
3280Sstevel@tonic-gate NULL
3290Sstevel@tonic-gate };
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate static const char *set_cmds[] = {
332565Sdp "set zonename=",
333565Sdp "set zonepath=",
3342712Snn35248 "set brand=",
335565Sdp "set autoboot=",
336565Sdp "set pool=",
3371645Scomay "set limitpriv=",
3382267Sdp "set bootargs=",
3393247Sgjelinek "set scheduling-class=",
3403448Sdh155122 "set ip-type=",
3413247Sgjelinek "set " ALIAS_MAXLWPS "=",
3423247Sgjelinek "set " ALIAS_MAXSHMMEM "=",
3433247Sgjelinek "set " ALIAS_MAXSHMIDS "=",
3443247Sgjelinek "set " ALIAS_MAXMSGIDS "=",
3453247Sgjelinek "set " ALIAS_MAXSEMIDS "=",
3463247Sgjelinek "set " ALIAS_SHARES "=",
3478662SJordan.Vaughan@Sun.com "set hostid=",
34812633Sjohn.levon@sun.com "set fs-allowed=",
34912725SMenno.Lageman@Sun.COM "set " ALIAS_MAXPROCS "=",
3500Sstevel@tonic-gate NULL
3510Sstevel@tonic-gate };
3520Sstevel@tonic-gate
3532607Sdp static const char *info_cmds[] = {
3542607Sdp "info fs ",
3552607Sdp "info net ",
3562607Sdp "info device ",
3572607Sdp "info rctl ",
3582607Sdp "info attr ",
3592607Sdp "info dataset ",
3603247Sgjelinek "info capped-memory",
3613247Sgjelinek "info dedicated-cpu",
3623792Sakolb "info capped-cpu",
3632607Sdp "info zonename",
3642607Sdp "info zonepath",
3652607Sdp "info autoboot",
3662607Sdp "info pool",
3672607Sdp "info limitpriv",
3682607Sdp "info bootargs",
3693247Sgjelinek "info brand",
3703247Sgjelinek "info scheduling-class",
3713448Sdh155122 "info ip-type",
3723247Sgjelinek "info max-lwps",
3733247Sgjelinek "info max-shm-memory",
3743247Sgjelinek "info max-shm-ids",
3753247Sgjelinek "info max-msg-ids",
3763247Sgjelinek "info max-sem-ids",
3773247Sgjelinek "info cpu-shares",
3788662SJordan.Vaughan@Sun.com "info hostid",
37912578SGlenn.Faden@Sun.COM "info admin",
38012633Sjohn.levon@sun.com "info fs-allowed",
38112725SMenno.Lageman@Sun.COM "info max-processes",
3822607Sdp NULL
3832607Sdp };
3842607Sdp
3850Sstevel@tonic-gate static const char *fs_res_scope_cmds[] = {
3860Sstevel@tonic-gate "add options ",
3870Sstevel@tonic-gate "cancel",
3880Sstevel@tonic-gate "end",
3890Sstevel@tonic-gate "exit",
3900Sstevel@tonic-gate "help",
3910Sstevel@tonic-gate "info",
3921645Scomay "remove options ",
3930Sstevel@tonic-gate "set dir=",
3940Sstevel@tonic-gate "set raw=",
3950Sstevel@tonic-gate "set special=",
3960Sstevel@tonic-gate "set type=",
3973247Sgjelinek "clear raw",
3980Sstevel@tonic-gate NULL
3990Sstevel@tonic-gate };
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate static const char *net_res_scope_cmds[] = {
4020Sstevel@tonic-gate "cancel",
4030Sstevel@tonic-gate "end",
4040Sstevel@tonic-gate "exit",
4050Sstevel@tonic-gate "help",
4060Sstevel@tonic-gate "info",
4070Sstevel@tonic-gate "set address=",
4080Sstevel@tonic-gate "set physical=",
40912626SGerald.Jelinek@Sun.COM "set defrouter=",
4100Sstevel@tonic-gate NULL
4110Sstevel@tonic-gate };
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate static const char *device_res_scope_cmds[] = {
4140Sstevel@tonic-gate "cancel",
4150Sstevel@tonic-gate "end",
4160Sstevel@tonic-gate "exit",
4170Sstevel@tonic-gate "help",
4180Sstevel@tonic-gate "info",
4190Sstevel@tonic-gate "set match=",
4200Sstevel@tonic-gate NULL
4210Sstevel@tonic-gate };
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate static const char *attr_res_scope_cmds[] = {
4240Sstevel@tonic-gate "cancel",
4250Sstevel@tonic-gate "end",
4260Sstevel@tonic-gate "exit",
4270Sstevel@tonic-gate "help",
4280Sstevel@tonic-gate "info",
4290Sstevel@tonic-gate "set name=",
4300Sstevel@tonic-gate "set type=",
4310Sstevel@tonic-gate "set value=",
4320Sstevel@tonic-gate NULL
4330Sstevel@tonic-gate };
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate static const char *rctl_res_scope_cmds[] = {
4360Sstevel@tonic-gate "add value ",
4370Sstevel@tonic-gate "cancel",
4380Sstevel@tonic-gate "end",
4390Sstevel@tonic-gate "exit",
4400Sstevel@tonic-gate "help",
4410Sstevel@tonic-gate "info",
4421645Scomay "remove value ",
4430Sstevel@tonic-gate "set name=",
4440Sstevel@tonic-gate NULL
4450Sstevel@tonic-gate };
4460Sstevel@tonic-gate
447789Sahrens static const char *dataset_res_scope_cmds[] = {
448789Sahrens "cancel",
449789Sahrens "end",
450789Sahrens "exit",
451789Sahrens "help",
452789Sahrens "info",
453789Sahrens "set name=",
454789Sahrens NULL
455789Sahrens };
456789Sahrens
4573247Sgjelinek static const char *pset_res_scope_cmds[] = {
4583247Sgjelinek "cancel",
4593247Sgjelinek "end",
4603247Sgjelinek "exit",
4613247Sgjelinek "help",
4623247Sgjelinek "info",
4633247Sgjelinek "set ncpus=",
4643247Sgjelinek "set importance=",
4653247Sgjelinek "clear importance",
4663247Sgjelinek NULL
4673247Sgjelinek };
4683247Sgjelinek
4693792Sakolb static const char *pcap_res_scope_cmds[] = {
4703792Sakolb "cancel",
4713792Sakolb "end",
4723792Sakolb "exit",
4733792Sakolb "help",
4743792Sakolb "info",
4753792Sakolb "set ncpus=",
4763792Sakolb NULL
4773792Sakolb };
4783792Sakolb
4793247Sgjelinek static const char *mcap_res_scope_cmds[] = {
4803247Sgjelinek "cancel",
4813247Sgjelinek "end",
4823247Sgjelinek "exit",
4833247Sgjelinek "help",
4843247Sgjelinek "info",
4853247Sgjelinek "set physical=",
4863247Sgjelinek "set swap=",
4873247Sgjelinek "set locked=",
4883247Sgjelinek "clear physical",
4893247Sgjelinek "clear swap",
4903247Sgjelinek "clear locked",
4913247Sgjelinek NULL
4923247Sgjelinek };
4933247Sgjelinek
49412578SGlenn.Faden@Sun.COM static const char *admin_res_scope_cmds[] = {
49512578SGlenn.Faden@Sun.COM "cancel",
49612578SGlenn.Faden@Sun.COM "end",
49712578SGlenn.Faden@Sun.COM "exit",
49812578SGlenn.Faden@Sun.COM "help",
49912578SGlenn.Faden@Sun.COM "info",
50012578SGlenn.Faden@Sun.COM "set user=",
50112578SGlenn.Faden@Sun.COM "set auths=",
50212578SGlenn.Faden@Sun.COM NULL
50312578SGlenn.Faden@Sun.COM };
50412578SGlenn.Faden@Sun.COM
50512748SSowmini.Varadhan@oracle.COM struct xif {
50612748SSowmini.Varadhan@oracle.COM struct xif *xif_next;
50712748SSowmini.Varadhan@oracle.COM char xif_name[LIFNAMSIZ];
50812748SSowmini.Varadhan@oracle.COM boolean_t xif_has_address;
50912748SSowmini.Varadhan@oracle.COM boolean_t xif_has_defrouter;
51012748SSowmini.Varadhan@oracle.COM };
51112748SSowmini.Varadhan@oracle.COM
5120Sstevel@tonic-gate /* Global variables */
5130Sstevel@tonic-gate
51412748SSowmini.Varadhan@oracle.COM /* list of network interfaces specified for exclusive IP zone */
51512748SSowmini.Varadhan@oracle.COM struct xif *xif;
51612748SSowmini.Varadhan@oracle.COM
5170Sstevel@tonic-gate /* set early in main(), never modified thereafter, used all over the place */
5180Sstevel@tonic-gate static char *execname;
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate /* set in main(), used all over the place */
5210Sstevel@tonic-gate static zone_dochandle_t handle;
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /* used all over the place */
524565Sdp static char zone[ZONENAME_MAX];
525565Sdp static char revert_zone[ZONENAME_MAX];
5260Sstevel@tonic-gate
5272712Snn35248 /* global brand operations */
5282727Sedp static brand_handle_t brand;
5292712Snn35248
5300Sstevel@tonic-gate /* set in modifying functions, checked in read_input() */
5316215Sgjelinek static boolean_t need_to_commit = B_FALSE;
5326215Sgjelinek boolean_t saw_error;
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /* set in yacc parser, checked in read_input() */
5356215Sgjelinek boolean_t newline_terminated;
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate /* set in main(), checked in lex error handler */
5386215Sgjelinek boolean_t cmd_file_mode;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate /* set in exit_func(), checked in read_input() */
5416215Sgjelinek static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate /* used in short_usage() and zerr() */
5440Sstevel@tonic-gate static char *cmd_file_name = NULL;
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate /* checked in read_input() and other places */
5476215Sgjelinek static boolean_t ok_to_prompt = B_FALSE;
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate /* set and checked in initialize() */
5506215Sgjelinek static boolean_t got_handle = B_FALSE;
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate /* initialized in do_interactive(), checked in initialize() */
5536215Sgjelinek static boolean_t interactive_mode;
5540Sstevel@tonic-gate
5553247Sgjelinek /* set if configuring the global zone */
5566215Sgjelinek static boolean_t global_zone = B_FALSE;
5573247Sgjelinek
5580Sstevel@tonic-gate /* set in main(), checked in multiple places */
5596215Sgjelinek static boolean_t read_only_mode;
5606215Sgjelinek
5616215Sgjelinek /* scope is outer/global or inner/resource */
5626215Sgjelinek static boolean_t global_scope = B_TRUE;
5630Sstevel@tonic-gate static int resource_scope; /* should be in the RT_ list from zonecfg.h */
5640Sstevel@tonic-gate static int end_op = -1; /* operation on end is either add or modify */
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate int num_prop_vals; /* for grammar */
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate /*
5690Sstevel@tonic-gate * These are for keeping track of resources as they are specified as part of
5700Sstevel@tonic-gate * the multi-step process. They should be initialized by add_resource() or
5710Sstevel@tonic-gate * select_func() and filled in by add_property() or set_func().
5720Sstevel@tonic-gate */
5730Sstevel@tonic-gate static struct zone_fstab old_fstab, in_progress_fstab;
5740Sstevel@tonic-gate static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
5750Sstevel@tonic-gate static struct zone_devtab old_devtab, in_progress_devtab;
5760Sstevel@tonic-gate static struct zone_rctltab old_rctltab, in_progress_rctltab;
5770Sstevel@tonic-gate static struct zone_attrtab old_attrtab, in_progress_attrtab;
578789Sahrens static struct zone_dstab old_dstab, in_progress_dstab;
5793247Sgjelinek static struct zone_psettab old_psettab, in_progress_psettab;
5803247Sgjelinek static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
58112578SGlenn.Faden@Sun.COM static struct zone_admintab old_admintab, in_progress_admintab;
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate static GetLine *gl; /* The gl_get_line() resource object */
5840Sstevel@tonic-gate
5853247Sgjelinek static void bytes_to_units(char *str, char *buf, int bufsize);
5863247Sgjelinek
5870Sstevel@tonic-gate /* Functions begin here */
5880Sstevel@tonic-gate
5896215Sgjelinek static boolean_t
initial_match(const char * line1,const char * line2,int word_end)5900Sstevel@tonic-gate initial_match(const char *line1, const char *line2, int word_end)
5910Sstevel@tonic-gate {
5920Sstevel@tonic-gate if (word_end <= 0)
5936215Sgjelinek return (B_TRUE);
5940Sstevel@tonic-gate return (strncmp(line1, line2, word_end) == 0);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate
5970Sstevel@tonic-gate static int
add_stuff(WordCompletion * cpl,const char * line1,const char ** list,int word_end)5980Sstevel@tonic-gate add_stuff(WordCompletion *cpl, const char *line1, const char **list,
5990Sstevel@tonic-gate int word_end)
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate int i, err;
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate for (i = 0; list[i] != NULL; i++) {
6040Sstevel@tonic-gate if (initial_match(line1, list[i], word_end)) {
6050Sstevel@tonic-gate err = cpl_add_completion(cpl, line1, 0, word_end,
6060Sstevel@tonic-gate list[i] + word_end, "", "");
6070Sstevel@tonic-gate if (err != 0)
6080Sstevel@tonic-gate return (err);
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate }
6110Sstevel@tonic-gate return (0);
6120Sstevel@tonic-gate }
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate static
6150Sstevel@tonic-gate /* ARGSUSED */
CPL_MATCH_FN(cmd_cpl_fn)6160Sstevel@tonic-gate CPL_MATCH_FN(cmd_cpl_fn)
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate if (global_scope) {
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate * The MAX/MIN tests below are to make sure we have at least
6210Sstevel@tonic-gate * enough characters to distinguish from other prefixes (MAX)
6220Sstevel@tonic-gate * but only check MIN(what we have, what we're checking).
6230Sstevel@tonic-gate */
6240Sstevel@tonic-gate if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
6250Sstevel@tonic-gate return (add_stuff(cpl, line, add_cmds, word_end));
6263247Sgjelinek if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
6273247Sgjelinek return (add_stuff(cpl, line, clear_cmds, word_end));
6280Sstevel@tonic-gate if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
6290Sstevel@tonic-gate return (add_stuff(cpl, line, select_cmds, word_end));
6300Sstevel@tonic-gate if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
6310Sstevel@tonic-gate return (add_stuff(cpl, line, set_cmds, word_end));
6322607Sdp if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
6332607Sdp return (add_stuff(cpl, line, remove_cmds, word_end));
6342607Sdp if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
6352607Sdp return (add_stuff(cpl, line, info_cmds, word_end));
6360Sstevel@tonic-gate return (add_stuff(cpl, line, global_scope_cmds, word_end));
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate switch (resource_scope) {
6390Sstevel@tonic-gate case RT_FS:
6400Sstevel@tonic-gate return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
6410Sstevel@tonic-gate case RT_NET:
6420Sstevel@tonic-gate return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
6430Sstevel@tonic-gate case RT_DEVICE:
6440Sstevel@tonic-gate return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
6450Sstevel@tonic-gate case RT_RCTL:
6460Sstevel@tonic-gate return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
6470Sstevel@tonic-gate case RT_ATTR:
6480Sstevel@tonic-gate return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
649789Sahrens case RT_DATASET:
650789Sahrens return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
6513247Sgjelinek case RT_DCPU:
6523247Sgjelinek return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
6533792Sakolb case RT_PCAP:
6543792Sakolb return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
6553247Sgjelinek case RT_MCAP:
6563247Sgjelinek return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
65712578SGlenn.Faden@Sun.COM case RT_ADMIN:
65812578SGlenn.Faden@Sun.COM return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate return (0);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate /*
6640Sstevel@tonic-gate * For the main CMD_func() functions below, several of them call getopt()
6650Sstevel@tonic-gate * then check optind against argc to make sure an extra parameter was not
6660Sstevel@tonic-gate * passed in. The reason this is not caught in the grammar is that the
6670Sstevel@tonic-gate * grammar just checks for a miscellaneous TOKEN, which is *expected* to
6680Sstevel@tonic-gate * be "-F" (for example), but could be anything. So (for example) this
6690Sstevel@tonic-gate * check will prevent "create bogus".
6700Sstevel@tonic-gate */
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate cmd_t *
alloc_cmd(void)6730Sstevel@tonic-gate alloc_cmd(void)
6740Sstevel@tonic-gate {
6750Sstevel@tonic-gate return (calloc(1, sizeof (cmd_t)));
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate void
free_cmd(cmd_t * cmd)6790Sstevel@tonic-gate free_cmd(cmd_t *cmd)
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate int i;
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
6840Sstevel@tonic-gate if (cmd->cmd_property_ptr[i] != NULL) {
6850Sstevel@tonic-gate property_value_ptr_t pp = cmd->cmd_property_ptr[i];
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate switch (pp->pv_type) {
6880Sstevel@tonic-gate case PROP_VAL_SIMPLE:
6890Sstevel@tonic-gate free(pp->pv_simple);
6900Sstevel@tonic-gate break;
6910Sstevel@tonic-gate case PROP_VAL_COMPLEX:
6920Sstevel@tonic-gate free_complex(pp->pv_complex);
6930Sstevel@tonic-gate break;
6940Sstevel@tonic-gate case PROP_VAL_LIST:
6950Sstevel@tonic-gate free_list(pp->pv_list);
6960Sstevel@tonic-gate break;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate for (i = 0; i < cmd->cmd_argc; i++)
7000Sstevel@tonic-gate free(cmd->cmd_argv[i]);
7010Sstevel@tonic-gate free(cmd);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate complex_property_ptr_t
alloc_complex(void)7050Sstevel@tonic-gate alloc_complex(void)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate return (calloc(1, sizeof (complex_property_t)));
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate void
free_complex(complex_property_ptr_t complex)7110Sstevel@tonic-gate free_complex(complex_property_ptr_t complex)
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate if (complex == NULL)
7140Sstevel@tonic-gate return;
7150Sstevel@tonic-gate free_complex(complex->cp_next);
7160Sstevel@tonic-gate if (complex->cp_value != NULL)
7170Sstevel@tonic-gate free(complex->cp_value);
7180Sstevel@tonic-gate free(complex);
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate list_property_ptr_t
alloc_list(void)7220Sstevel@tonic-gate alloc_list(void)
7230Sstevel@tonic-gate {
7240Sstevel@tonic-gate return (calloc(1, sizeof (list_property_t)));
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate void
free_list(list_property_ptr_t list)7280Sstevel@tonic-gate free_list(list_property_ptr_t list)
7290Sstevel@tonic-gate {
7300Sstevel@tonic-gate if (list == NULL)
7310Sstevel@tonic-gate return;
7320Sstevel@tonic-gate if (list->lp_simple != NULL)
7330Sstevel@tonic-gate free(list->lp_simple);
7340Sstevel@tonic-gate free_complex(list->lp_complex);
7350Sstevel@tonic-gate free_list(list->lp_next);
7360Sstevel@tonic-gate free(list);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate void
free_outer_list(list_property_ptr_t list)7400Sstevel@tonic-gate free_outer_list(list_property_ptr_t list)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate if (list == NULL)
7430Sstevel@tonic-gate return;
7440Sstevel@tonic-gate free_outer_list(list->lp_next);
7450Sstevel@tonic-gate free(list);
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate static struct zone_rctlvaltab *
alloc_rctlvaltab(void)7490Sstevel@tonic-gate alloc_rctlvaltab(void)
7500Sstevel@tonic-gate {
7510Sstevel@tonic-gate return (calloc(1, sizeof (struct zone_rctlvaltab)));
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate static char *
rt_to_str(int res_type)7550Sstevel@tonic-gate rt_to_str(int res_type)
7560Sstevel@tonic-gate {
7570Sstevel@tonic-gate assert(res_type >= RT_MIN && res_type <= RT_MAX);
7580Sstevel@tonic-gate return (res_types[res_type]);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate static char *
pt_to_str(int prop_type)7620Sstevel@tonic-gate pt_to_str(int prop_type)
7630Sstevel@tonic-gate {
7640Sstevel@tonic-gate assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
7650Sstevel@tonic-gate return (prop_types[prop_type]);
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate static char *
pvt_to_str(int pv_type)7690Sstevel@tonic-gate pvt_to_str(int pv_type)
7700Sstevel@tonic-gate {
7710Sstevel@tonic-gate assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
7720Sstevel@tonic-gate return (prop_val_types[pv_type]);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate static char *
cmd_to_str(int cmd_num)7760Sstevel@tonic-gate cmd_to_str(int cmd_num)
7770Sstevel@tonic-gate {
7780Sstevel@tonic-gate assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
7790Sstevel@tonic-gate return (helptab[cmd_num].cmd_name);
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate
78211882SFrank.Batschulat@Sun.COM /* PRINTFLIKE1 */
78311882SFrank.Batschulat@Sun.COM static void
zerr(const char * fmt,...)78411882SFrank.Batschulat@Sun.COM zerr(const char *fmt, ...)
78511882SFrank.Batschulat@Sun.COM {
78611882SFrank.Batschulat@Sun.COM va_list alist;
78711882SFrank.Batschulat@Sun.COM static int last_lineno;
78811882SFrank.Batschulat@Sun.COM
78911882SFrank.Batschulat@Sun.COM /* lex_lineno has already been incremented in the lexer; compensate */
79011882SFrank.Batschulat@Sun.COM if (cmd_file_mode && lex_lineno > last_lineno) {
79111882SFrank.Batschulat@Sun.COM if (strcmp(cmd_file_name, "-") == 0)
79211882SFrank.Batschulat@Sun.COM (void) fprintf(stderr, gettext("On line %d:\n"),
79311882SFrank.Batschulat@Sun.COM lex_lineno - 1);
79411882SFrank.Batschulat@Sun.COM else
79511882SFrank.Batschulat@Sun.COM (void) fprintf(stderr, gettext("On line %d of %s:\n"),
79611882SFrank.Batschulat@Sun.COM lex_lineno - 1, cmd_file_name);
79711882SFrank.Batschulat@Sun.COM last_lineno = lex_lineno;
79811882SFrank.Batschulat@Sun.COM }
79911882SFrank.Batschulat@Sun.COM va_start(alist, fmt);
80011882SFrank.Batschulat@Sun.COM (void) vfprintf(stderr, fmt, alist);
80111882SFrank.Batschulat@Sun.COM (void) fprintf(stderr, "\n");
80211882SFrank.Batschulat@Sun.COM va_end(alist);
80311882SFrank.Batschulat@Sun.COM }
80411882SFrank.Batschulat@Sun.COM
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate * This is a separate function rather than a set of define's because of the
8070Sstevel@tonic-gate * gettext() wrapping.
8080Sstevel@tonic-gate */
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate * TRANSLATION_NOTE
8120Sstevel@tonic-gate * Each string below should have \t follow \n whenever needed; the
8130Sstevel@tonic-gate * initial \t and the terminal \n will be provided by the calling function.
8140Sstevel@tonic-gate */
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate static char *
long_help(int cmd_num)8170Sstevel@tonic-gate long_help(int cmd_num)
8180Sstevel@tonic-gate {
8190Sstevel@tonic-gate static char line[1024]; /* arbitrary large amount */
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
8220Sstevel@tonic-gate switch (cmd_num) {
8230Sstevel@tonic-gate case CMD_HELP:
8240Sstevel@tonic-gate return (gettext("Prints help message."));
8250Sstevel@tonic-gate case CMD_CREATE:
8260Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
8270Sstevel@tonic-gate gettext("Creates a configuration for the "
8280Sstevel@tonic-gate "specified zone. %s should be\n\tused to "
8290Sstevel@tonic-gate "begin configuring a new zone. If overwriting an "
8300Sstevel@tonic-gate "existing\n\tconfiguration, the -F flag can be "
8310Sstevel@tonic-gate "used to force the action. If\n\t-t template is "
8320Sstevel@tonic-gate "given, creates a configuration identical to the\n"
8330Sstevel@tonic-gate "\tspecified template, except that the zone name "
8341634Sgjelinek "is changed from\n\ttemplate to zonename. '%s -a' "
8351634Sgjelinek "creates a configuration from a\n\tdetached "
8361634Sgjelinek "zonepath. '%s -b' results in a blank "
8371634Sgjelinek "configuration.\n\t'%s' with no arguments applies "
8381634Sgjelinek "the Sun default settings."),
8390Sstevel@tonic-gate cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
8401634Sgjelinek cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
8410Sstevel@tonic-gate return (line);
8420Sstevel@tonic-gate case CMD_EXIT:
8430Sstevel@tonic-gate return (gettext("Exits the program. The -F flag can "
8440Sstevel@tonic-gate "be used to force the action."));
8450Sstevel@tonic-gate case CMD_EXPORT:
8460Sstevel@tonic-gate return (gettext("Prints configuration to standard "
8470Sstevel@tonic-gate "output, or to output-file if\n\tspecified, in "
8480Sstevel@tonic-gate "a form suitable for use in a command-file."));
8490Sstevel@tonic-gate case CMD_ADD:
8500Sstevel@tonic-gate return (gettext("Add specified resource to "
8510Sstevel@tonic-gate "configuration."));
8520Sstevel@tonic-gate case CMD_DELETE:
8530Sstevel@tonic-gate return (gettext("Deletes the specified zone. The -F "
8540Sstevel@tonic-gate "flag can be used to force the\n\taction."));
8550Sstevel@tonic-gate case CMD_REMOVE:
8560Sstevel@tonic-gate return (gettext("Remove specified resource from "
8573247Sgjelinek "configuration. The -F flag can be used\n\tto "
8583247Sgjelinek "force the action."));
8590Sstevel@tonic-gate case CMD_SELECT:
8600Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
8610Sstevel@tonic-gate gettext("Selects a resource to modify. "
8620Sstevel@tonic-gate "Resource modification is completed\n\twith the "
8630Sstevel@tonic-gate "command \"%s\". The property name/value pairs "
8640Sstevel@tonic-gate "must uniquely\n\tidentify a resource. Note that "
8650Sstevel@tonic-gate "the curly braces ('{', '}') mean one\n\tor more "
8660Sstevel@tonic-gate "of whatever is between them."),
8670Sstevel@tonic-gate cmd_to_str(CMD_END));
8680Sstevel@tonic-gate return (line);
8690Sstevel@tonic-gate case CMD_SET:
8700Sstevel@tonic-gate return (gettext("Sets property values."));
8713247Sgjelinek case CMD_CLEAR:
8723247Sgjelinek return (gettext("Clears property values."));
8730Sstevel@tonic-gate case CMD_INFO:
8740Sstevel@tonic-gate return (gettext("Displays information about the "
8750Sstevel@tonic-gate "current configuration. If resource\n\ttype is "
8760Sstevel@tonic-gate "specified, displays only information about "
8770Sstevel@tonic-gate "resources of\n\tthe relevant type. If resource "
8780Sstevel@tonic-gate "id is specified, displays only\n\tinformation "
8790Sstevel@tonic-gate "about that resource."));
8800Sstevel@tonic-gate case CMD_VERIFY:
8810Sstevel@tonic-gate return (gettext("Verifies current configuration "
8820Sstevel@tonic-gate "for correctness (some resource types\n\thave "
8830Sstevel@tonic-gate "required properties)."));
8840Sstevel@tonic-gate case CMD_COMMIT:
8850Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
8860Sstevel@tonic-gate gettext("Commits current configuration. "
8870Sstevel@tonic-gate "Configuration must be committed to\n\tbe used by "
8880Sstevel@tonic-gate "%s. Until the configuration is committed, "
8890Sstevel@tonic-gate "changes \n\tcan be removed with the %s "
8900Sstevel@tonic-gate "command. This operation is\n\tattempted "
8910Sstevel@tonic-gate "automatically upon completion of a %s "
8920Sstevel@tonic-gate "session."), "zoneadm", cmd_to_str(CMD_REVERT),
8930Sstevel@tonic-gate "zonecfg");
8940Sstevel@tonic-gate return (line);
8950Sstevel@tonic-gate case CMD_REVERT:
8960Sstevel@tonic-gate return (gettext("Reverts configuration back to the "
8970Sstevel@tonic-gate "last committed state. The -F flag\n\tcan be "
8980Sstevel@tonic-gate "used to force the action."));
8990Sstevel@tonic-gate case CMD_CANCEL:
9000Sstevel@tonic-gate return (gettext("Cancels resource/property "
9010Sstevel@tonic-gate "specification."));
9020Sstevel@tonic-gate case CMD_END:
9030Sstevel@tonic-gate return (gettext("Ends resource/property "
9040Sstevel@tonic-gate "specification."));
9050Sstevel@tonic-gate }
9060Sstevel@tonic-gate /* NOTREACHED */
907222Scomay return (NULL);
9080Sstevel@tonic-gate }
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate /*
9110Sstevel@tonic-gate * Called with verbose TRUE when help is explicitly requested, FALSE for
9120Sstevel@tonic-gate * unexpected errors.
9130Sstevel@tonic-gate */
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate void
usage(boolean_t verbose,uint_t flags)9166215Sgjelinek usage(boolean_t verbose, uint_t flags)
9170Sstevel@tonic-gate {
91811882SFrank.Batschulat@Sun.COM FILE *fp = verbose ? stdout : stderr;
91911882SFrank.Batschulat@Sun.COM FILE *newfp;
9206215Sgjelinek boolean_t need_to_close = B_FALSE;
921*12761SSusan.Kamm-Worrell@Sun.COM char *pager, *space;
9220Sstevel@tonic-gate int i;
92311882SFrank.Batschulat@Sun.COM struct stat statbuf;
9240Sstevel@tonic-gate
9250Sstevel@tonic-gate /* don't page error output */
9260Sstevel@tonic-gate if (verbose && interactive_mode) {
9270Sstevel@tonic-gate if ((pager = getenv("PAGER")) == NULL)
9280Sstevel@tonic-gate pager = PAGER;
92911882SFrank.Batschulat@Sun.COM
930*12761SSusan.Kamm-Worrell@Sun.COM space = strchr(pager, ' ');
931*12761SSusan.Kamm-Worrell@Sun.COM if (space)
932*12761SSusan.Kamm-Worrell@Sun.COM *space = '\0';
93311882SFrank.Batschulat@Sun.COM if (stat(pager, &statbuf) == 0) {
934*12761SSusan.Kamm-Worrell@Sun.COM if (space)
935*12761SSusan.Kamm-Worrell@Sun.COM *space = ' ';
93611882SFrank.Batschulat@Sun.COM if ((newfp = popen(pager, "w")) != NULL) {
93711882SFrank.Batschulat@Sun.COM need_to_close = B_TRUE;
93811882SFrank.Batschulat@Sun.COM fp = newfp;
93911882SFrank.Batschulat@Sun.COM }
94011882SFrank.Batschulat@Sun.COM } else {
94111882SFrank.Batschulat@Sun.COM zerr(gettext("PAGER %s does not exist (%s)."),
94211882SFrank.Batschulat@Sun.COM pager, strerror(errno));
94311882SFrank.Batschulat@Sun.COM }
94411882SFrank.Batschulat@Sun.COM }
94511882SFrank.Batschulat@Sun.COM
9460Sstevel@tonic-gate if (flags & HELP_META) {
9470Sstevel@tonic-gate (void) fprintf(fp, gettext("More help is available for the "
9480Sstevel@tonic-gate "following:\n"));
9490Sstevel@tonic-gate (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
9500Sstevel@tonic-gate cmd_to_str(CMD_HELP));
9510Sstevel@tonic-gate (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
9520Sstevel@tonic-gate cmd_to_str(CMD_HELP));
9530Sstevel@tonic-gate (void) fprintf(fp, "\tusage ('%s usage')\n\n",
9540Sstevel@tonic-gate cmd_to_str(CMD_HELP));
9550Sstevel@tonic-gate (void) fprintf(fp, gettext("You may also obtain help on any "
9560Sstevel@tonic-gate "command by typing '%s <command-name>.'\n"),
9570Sstevel@tonic-gate cmd_to_str(CMD_HELP));
9580Sstevel@tonic-gate }
9590Sstevel@tonic-gate if (flags & HELP_RES_SCOPE) {
9600Sstevel@tonic-gate switch (resource_scope) {
9610Sstevel@tonic-gate case RT_FS:
9620Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is "
9630Sstevel@tonic-gate "used to configure a file-system.\n"),
9640Sstevel@tonic-gate rt_to_str(resource_scope));
9650Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n"));
9660Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9670Sstevel@tonic-gate pt_to_str(PT_DIR), gettext("<path>"));
9680Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9690Sstevel@tonic-gate pt_to_str(PT_SPECIAL), gettext("<path>"));
9700Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9710Sstevel@tonic-gate pt_to_str(PT_RAW), gettext("<raw-device>"));
9720Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9730Sstevel@tonic-gate pt_to_str(PT_TYPE), gettext("<file-system type>"));
9740Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
9750Sstevel@tonic-gate pt_to_str(PT_OPTIONS),
9760Sstevel@tonic-gate gettext("<file-system options>"));
9771645Scomay (void) fprintf(fp, "\t%s %s %s\n",
9781645Scomay cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
9791645Scomay gettext("<file-system options>"));
9800Sstevel@tonic-gate (void) fprintf(fp, gettext("Consult the file-system "
9810Sstevel@tonic-gate "specific manual page, such as mount_ufs(1M), "
9820Sstevel@tonic-gate "for\ndetails about file-system options. Note "
9830Sstevel@tonic-gate "that any file-system options with an\nembedded "
9840Sstevel@tonic-gate "'=' character must be enclosed in double quotes, "
9850Sstevel@tonic-gate /*CSTYLED*/
9860Sstevel@tonic-gate "such as \"%s=5\".\n"), MNTOPT_RETRY);
9870Sstevel@tonic-gate break;
9880Sstevel@tonic-gate case RT_NET:
9890Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is "
9900Sstevel@tonic-gate "used to configure a network interface.\n"),
9910Sstevel@tonic-gate rt_to_str(resource_scope));
9920Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n"));
9930Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9940Sstevel@tonic-gate pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
9950Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
99612748SSowmini.Varadhan@oracle.COM pt_to_str(PT_ALLOWED_ADDRESS),
99712748SSowmini.Varadhan@oracle.COM gettext("<IP-address>"));
99812748SSowmini.Varadhan@oracle.COM (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
9990Sstevel@tonic-gate pt_to_str(PT_PHYSICAL), gettext("<interface>"));
10000Sstevel@tonic-gate (void) fprintf(fp, gettext("See ifconfig(1M) for "
10010Sstevel@tonic-gate "details of the <interface> string.\n"));
100212748SSowmini.Varadhan@oracle.COM (void) fprintf(fp, gettext("%s %s is valid "
100312748SSowmini.Varadhan@oracle.COM "if the %s property is set to %s, otherwise it "
10046076Sgfaden "must not be set.\n"),
10053448Sdh155122 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
100612748SSowmini.Varadhan@oracle.COM pt_to_str(PT_IPTYPE), gettext("shared"));
100712748SSowmini.Varadhan@oracle.COM (void) fprintf(fp, gettext("%s %s is valid "
100812748SSowmini.Varadhan@oracle.COM "if the %s property is set to %s, otherwise it "
100912748SSowmini.Varadhan@oracle.COM "must not be set.\n"),
101012748SSowmini.Varadhan@oracle.COM cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
101112748SSowmini.Varadhan@oracle.COM pt_to_str(PT_IPTYPE), gettext("exclusive"));
101212748SSowmini.Varadhan@oracle.COM (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
101312748SSowmini.Varadhan@oracle.COM "is valid if the %s or %s property is set, "
101412748SSowmini.Varadhan@oracle.COM "otherwise it must not be set\n"),
101512748SSowmini.Varadhan@oracle.COM cmd_to_str(CMD_SET),
101612748SSowmini.Varadhan@oracle.COM pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
10176076Sgfaden cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
101812748SSowmini.Varadhan@oracle.COM gettext(pt_to_str(PT_ADDRESS)),
101912748SSowmini.Varadhan@oracle.COM gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
10200Sstevel@tonic-gate break;
10210Sstevel@tonic-gate case RT_DEVICE:
10220Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is "
10230Sstevel@tonic-gate "used to configure a device node.\n"),
10240Sstevel@tonic-gate rt_to_str(resource_scope));
10250Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n"));
10260Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10270Sstevel@tonic-gate pt_to_str(PT_MATCH), gettext("<device-path>"));
10280Sstevel@tonic-gate break;
10290Sstevel@tonic-gate case RT_RCTL:
10300Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is "
10310Sstevel@tonic-gate "used to configure a resource control.\n"),
10320Sstevel@tonic-gate rt_to_str(resource_scope));
10330Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n"));
10340Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10350Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("<string>"));
10360Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
10370Sstevel@tonic-gate cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
10380Sstevel@tonic-gate pt_to_str(PT_PRIV), gettext("<priv-value>"),
10390Sstevel@tonic-gate pt_to_str(PT_LIMIT), gettext("<number>"),
10400Sstevel@tonic-gate pt_to_str(PT_ACTION), gettext("<action-value>"));
10411645Scomay (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
10421645Scomay cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
10431645Scomay pt_to_str(PT_PRIV), gettext("<priv-value>"),
10441645Scomay pt_to_str(PT_LIMIT), gettext("<number>"),
10451645Scomay pt_to_str(PT_ACTION), gettext("<action-value>"));
10460Sstevel@tonic-gate (void) fprintf(fp, "%s\n\t%s := privileged\n"
10470Sstevel@tonic-gate "\t%s := none | deny\n", gettext("Where"),
10480Sstevel@tonic-gate gettext("<priv-value>"), gettext("<action-value>"));
10490Sstevel@tonic-gate break;
10500Sstevel@tonic-gate case RT_ATTR:
10510Sstevel@tonic-gate (void) fprintf(fp, gettext("The '%s' resource scope is "
10520Sstevel@tonic-gate "used to configure a generic attribute.\n"),
10530Sstevel@tonic-gate rt_to_str(resource_scope));
10540Sstevel@tonic-gate (void) fprintf(fp, gettext("Valid commands:\n"));
10550Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10560Sstevel@tonic-gate pt_to_str(PT_NAME), gettext("<name>"));
10570Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=boolean\n",
10580Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10590Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=true | false\n",
10600Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
10610Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n"));
10620Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
10630Sstevel@tonic-gate pt_to_str(PT_TYPE));
10640Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10650Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<integer>"));
10660Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n"));
10670Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=string\n",
10680Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10690Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10700Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<string>"));
10710Sstevel@tonic-gate (void) fprintf(fp, gettext("or\n"));
10720Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=uint\n",
10730Sstevel@tonic-gate cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
10740Sstevel@tonic-gate (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10750Sstevel@tonic-gate pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
10760Sstevel@tonic-gate break;
1077789Sahrens case RT_DATASET:
1078789Sahrens (void) fprintf(fp, gettext("The '%s' resource scope is "
1079789Sahrens "used to export ZFS datasets.\n"),
1080789Sahrens rt_to_str(resource_scope));
1081789Sahrens (void) fprintf(fp, gettext("Valid commands:\n"));
1082789Sahrens (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1083789Sahrens pt_to_str(PT_NAME), gettext("<name>"));
1084789Sahrens break;
10853247Sgjelinek case RT_DCPU:
10863247Sgjelinek (void) fprintf(fp, gettext("The '%s' resource scope "
10873247Sgjelinek "configures the 'pools' facility to dedicate\na "
10883247Sgjelinek "subset of the system's processors to this zone "
10893247Sgjelinek "while it is running.\n"),
10903247Sgjelinek rt_to_str(resource_scope));
10913247Sgjelinek (void) fprintf(fp, gettext("Valid commands:\n"));
10923247Sgjelinek (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10933247Sgjelinek pt_to_str(PT_NCPUS),
10943247Sgjelinek gettext("<unsigned integer | range>"));
10953247Sgjelinek (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
10963247Sgjelinek pt_to_str(PT_IMPORTANCE),
10973247Sgjelinek gettext("<unsigned integer>"));
10983247Sgjelinek break;
10993792Sakolb case RT_PCAP:
11003792Sakolb (void) fprintf(fp, gettext("The '%s' resource scope is "
11013792Sakolb "used to set an upper limit (a cap) on the\n"
11023792Sakolb "percentage of CPU that can be used by this zone. "
11033792Sakolb "A '%s' value of 1\ncorresponds to one cpu. The "
11043792Sakolb "value can be set higher than 1, up to the total\n"
11053792Sakolb "number of CPUs on the system. The value can "
11063792Sakolb "also be less than 1,\nrepresenting a fraction of "
11073792Sakolb "a cpu.\n"),
11083792Sakolb rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
11093792Sakolb (void) fprintf(fp, gettext("Valid commands:\n"));
11103792Sakolb (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11113792Sakolb pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
11123792Sakolb break;
11133247Sgjelinek case RT_MCAP:
11143247Sgjelinek (void) fprintf(fp, gettext("The '%s' resource scope is "
11153247Sgjelinek "used to set an upper limit (a cap) on the\n"
11163247Sgjelinek "amount of physical memory, swap space and locked "
11173247Sgjelinek "memory that can be used by\nthis zone.\n"),
11183247Sgjelinek rt_to_str(resource_scope));
11193247Sgjelinek (void) fprintf(fp, gettext("Valid commands:\n"));
11203247Sgjelinek (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11213247Sgjelinek pt_to_str(PT_PHYSICAL),
11223247Sgjelinek gettext("<qualified unsigned decimal>"));
11233247Sgjelinek (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11243247Sgjelinek pt_to_str(PT_SWAP),
11253247Sgjelinek gettext("<qualified unsigned decimal>"));
11263247Sgjelinek (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
11273247Sgjelinek pt_to_str(PT_LOCKED),
11283247Sgjelinek gettext("<qualified unsigned decimal>"));
11293247Sgjelinek break;
113012578SGlenn.Faden@Sun.COM case RT_ADMIN:
113112578SGlenn.Faden@Sun.COM (void) fprintf(fp, gettext("The '%s' resource scope is "
113212578SGlenn.Faden@Sun.COM "used to delegate specific zone management\n"
113312578SGlenn.Faden@Sun.COM "rights to users and roles. These rights are "
113412578SGlenn.Faden@Sun.COM "only applicable to this zone.\n"),
113512578SGlenn.Faden@Sun.COM rt_to_str(resource_scope));
113612578SGlenn.Faden@Sun.COM (void) fprintf(fp, gettext("Valid commands:\n"));
113712578SGlenn.Faden@Sun.COM (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
113812578SGlenn.Faden@Sun.COM pt_to_str(PT_USER),
113912578SGlenn.Faden@Sun.COM gettext("<single user or role name>"));
114012578SGlenn.Faden@Sun.COM (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
114112578SGlenn.Faden@Sun.COM pt_to_str(PT_AUTHS),
114212578SGlenn.Faden@Sun.COM gettext("<comma separated list>"));
114312578SGlenn.Faden@Sun.COM break;
11440Sstevel@tonic-gate }
11450Sstevel@tonic-gate (void) fprintf(fp, gettext("And from any resource scope, you "
11460Sstevel@tonic-gate "can:\n"));
11470Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
11480Sstevel@tonic-gate gettext("(to conclude this operation)"));
11490Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
11500Sstevel@tonic-gate gettext("(to cancel this operation)"));
11510Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
11520Sstevel@tonic-gate gettext("(to exit the zonecfg utility)"));
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate if (flags & HELP_USAGE) {
11550Sstevel@tonic-gate (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
11560Sstevel@tonic-gate execname, cmd_to_str(CMD_HELP));
11570Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
11580Sstevel@tonic-gate execname, gettext("interactive"));
11590Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
11600Sstevel@tonic-gate (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
11610Sstevel@tonic-gate execname);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate if (flags & HELP_SUBCMDS) {
11640Sstevel@tonic-gate (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
11650Sstevel@tonic-gate for (i = 0; i <= CMD_MAX; i++) {
11660Sstevel@tonic-gate (void) fprintf(fp, "%s\n", helptab[i].short_usage);
11670Sstevel@tonic-gate if (verbose)
11680Sstevel@tonic-gate (void) fprintf(fp, "\t%s\n\n", long_help(i));
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate if (flags & HELP_SYNTAX) {
11720Sstevel@tonic-gate if (!verbose)
11730Sstevel@tonic-gate (void) fprintf(fp, "\n");
11740Sstevel@tonic-gate (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
11750Sstevel@tonic-gate (void) fprintf(fp, gettext("\t(except the reserved words "
11760Sstevel@tonic-gate "'%s' and anything starting with '%s')\n"), "global",
11770Sstevel@tonic-gate "SUNW");
11780Sstevel@tonic-gate (void) fprintf(fp,
11790Sstevel@tonic-gate gettext("\tName must be less than %d characters.\n"),
11800Sstevel@tonic-gate ZONENAME_MAX);
11810Sstevel@tonic-gate if (verbose)
11820Sstevel@tonic-gate (void) fprintf(fp, "\n");
11830Sstevel@tonic-gate }
11840Sstevel@tonic-gate if (flags & HELP_NETADDR) {
11850Sstevel@tonic-gate (void) fprintf(fp, gettext("\n<net-addr> :="));
11860Sstevel@tonic-gate (void) fprintf(fp,
11870Sstevel@tonic-gate gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
11880Sstevel@tonic-gate (void) fprintf(fp,
11890Sstevel@tonic-gate gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
11900Sstevel@tonic-gate (void) fprintf(fp,
11910Sstevel@tonic-gate gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
11920Sstevel@tonic-gate (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
11930Sstevel@tonic-gate "IPv6 address syntax.\n"));
11940Sstevel@tonic-gate (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
11950Sstevel@tonic-gate (void) fprintf(fp,
11960Sstevel@tonic-gate gettext("<IPv6-prefix-length> := [0-128]\n"));
11970Sstevel@tonic-gate (void) fprintf(fp,
11980Sstevel@tonic-gate gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate if (flags & HELP_RESOURCES) {
120112734Sgary.pennington@oracle.com (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
120212578SGlenn.Faden@Sun.COM "%s | %s | %s | %s | %s\n\n",
12030Sstevel@tonic-gate gettext("resource type"), rt_to_str(RT_FS),
120412734Sgary.pennington@oracle.com rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
12052607Sdp rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
12063247Sgjelinek rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
120712578SGlenn.Faden@Sun.COM rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
120812578SGlenn.Faden@Sun.COM rt_to_str(RT_ADMIN));
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate if (flags & HELP_PROPS) {
12110Sstevel@tonic-gate (void) fprintf(fp, gettext("For resource type ... there are "
12120Sstevel@tonic-gate "property types ...:\n"));
12130Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1214565Sdp pt_to_str(PT_ZONENAME));
1215565Sdp (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12160Sstevel@tonic-gate pt_to_str(PT_ZONEPATH));
12170Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12182712Snn35248 pt_to_str(PT_BRAND));
12192712Snn35248 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12200Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT));
12210Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12222267Sdp pt_to_str(PT_BOOTARGS));
12232267Sdp (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12240Sstevel@tonic-gate pt_to_str(PT_POOL));
12251645Scomay (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12261645Scomay pt_to_str(PT_LIMITPRIV));
12273247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12283247Sgjelinek pt_to_str(PT_SCHED));
12293247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12303448Sdh155122 pt_to_str(PT_IPTYPE));
12313448Sdh155122 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12328662SJordan.Vaughan@Sun.com pt_to_str(PT_HOSTID));
12338662SJordan.Vaughan@Sun.com (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
123412633Sjohn.levon@sun.com pt_to_str(PT_FS_ALLOWED));
123512633Sjohn.levon@sun.com (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12363247Sgjelinek pt_to_str(PT_MAXLWPS));
12373247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
123812725SMenno.Lageman@Sun.COM pt_to_str(PT_MAXPROCS));
123912725SMenno.Lageman@Sun.COM (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12403247Sgjelinek pt_to_str(PT_MAXSHMMEM));
12413247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12423247Sgjelinek pt_to_str(PT_MAXSHMIDS));
12433247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12443247Sgjelinek pt_to_str(PT_MAXMSGIDS));
12453247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12463247Sgjelinek pt_to_str(PT_MAXSEMIDS));
12473247Sgjelinek (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
12483247Sgjelinek pt_to_str(PT_SHARES));
124912227SFrank.Batschulat@Sun.COM (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
125012227SFrank.Batschulat@Sun.COM rt_to_str(RT_FS), pt_to_str(PT_DIR),
125112227SFrank.Batschulat@Sun.COM pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
125212227SFrank.Batschulat@Sun.COM pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
125312748SSowmini.Varadhan@oracle.COM (void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
125412748SSowmini.Varadhan@oracle.COM pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
125512748SSowmini.Varadhan@oracle.COM pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
12560Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
12570Sstevel@tonic-gate pt_to_str(PT_MATCH));
12580Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
12590Sstevel@tonic-gate pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
12600Sstevel@tonic-gate (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
12610Sstevel@tonic-gate pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
12620Sstevel@tonic-gate pt_to_str(PT_VALUE));
1263789Sahrens (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1264789Sahrens pt_to_str(PT_NAME));
12653247Sgjelinek (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
12663247Sgjelinek pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
12673792Sakolb (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
12683792Sakolb pt_to_str(PT_NCPUS));
12693247Sgjelinek (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
12703247Sgjelinek pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
12713247Sgjelinek pt_to_str(PT_LOCKED));
127212578SGlenn.Faden@Sun.COM (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
127312578SGlenn.Faden@Sun.COM pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
12740Sstevel@tonic-gate }
12750Sstevel@tonic-gate if (need_to_close)
12760Sstevel@tonic-gate (void) pclose(fp);
12770Sstevel@tonic-gate }
12780Sstevel@tonic-gate
12790Sstevel@tonic-gate static void
zone_perror(char * prefix,int err,boolean_t set_saw)12806215Sgjelinek zone_perror(char *prefix, int err, boolean_t set_saw)
12810Sstevel@tonic-gate {
12820Sstevel@tonic-gate zerr("%s: %s", prefix, zonecfg_strerror(err));
12830Sstevel@tonic-gate if (set_saw)
12846215Sgjelinek saw_error = B_TRUE;
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate
12870Sstevel@tonic-gate /*
12880Sstevel@tonic-gate * zone_perror() expects a single string, but for remove and select
12890Sstevel@tonic-gate * we have both the command and the resource type, so this wrapper
12900Sstevel@tonic-gate * function serves the same purpose in a slightly different way.
12910Sstevel@tonic-gate */
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate static void
z_cmd_rt_perror(int cmd_num,int res_num,int err,boolean_t set_saw)12946215Sgjelinek z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
12950Sstevel@tonic-gate {
12960Sstevel@tonic-gate zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
12970Sstevel@tonic-gate zonecfg_strerror(err));
12980Sstevel@tonic-gate if (set_saw)
12996215Sgjelinek saw_error = B_TRUE;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate
13020Sstevel@tonic-gate /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
13030Sstevel@tonic-gate static int
initialize(boolean_t handle_expected)13046215Sgjelinek initialize(boolean_t handle_expected)
13050Sstevel@tonic-gate {
13060Sstevel@tonic-gate int err;
13072712Snn35248 char brandname[MAXNAMELEN];
13080Sstevel@tonic-gate
13090Sstevel@tonic-gate if (zonecfg_check_handle(handle) != Z_OK) {
13100Sstevel@tonic-gate if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
13116215Sgjelinek got_handle = B_TRUE;
13122712Snn35248 if (zonecfg_get_brand(handle, brandname,
13132712Snn35248 sizeof (brandname)) != Z_OK) {
13142712Snn35248 zerr("Zone %s is inconsistent: missing "
13152712Snn35248 "brand attribute", zone);
13162712Snn35248 exit(Z_ERR);
13172712Snn35248 }
13182712Snn35248 if ((brand = brand_open(brandname)) == NULL) {
13192712Snn35248 zerr("Zone %s uses non-existent brand \"%s\"."
13202712Snn35248 " Unable to continue", zone, brandname);
13212712Snn35248 exit(Z_ERR);
13222712Snn35248 }
132312578SGlenn.Faden@Sun.COM /*
132412578SGlenn.Faden@Sun.COM * If the user_attr file is newer than
132512578SGlenn.Faden@Sun.COM * the zone config file, the admins
132612578SGlenn.Faden@Sun.COM * may need to be updated since the
132712578SGlenn.Faden@Sun.COM * RBAC files are authoritative for
132812578SGlenn.Faden@Sun.COM * authorization checks.
132912578SGlenn.Faden@Sun.COM */
133012578SGlenn.Faden@Sun.COM err = zonecfg_update_userauths(handle, zone);
133112578SGlenn.Faden@Sun.COM if (err == Z_OK) {
133212578SGlenn.Faden@Sun.COM zerr(gettext("The administrative rights "
133312578SGlenn.Faden@Sun.COM "were updated to match "
133412578SGlenn.Faden@Sun.COM "the current RBAC configuration.\n"
133512578SGlenn.Faden@Sun.COM "Use \"info admin\" and \"revert\" to "
133612578SGlenn.Faden@Sun.COM "compare with the previous settings."));
133712578SGlenn.Faden@Sun.COM need_to_commit = B_TRUE;
133812578SGlenn.Faden@Sun.COM } else if (err != Z_NO_ENTRY) {
133912578SGlenn.Faden@Sun.COM zerr(gettext("failed to update "
134012578SGlenn.Faden@Sun.COM "admin rights."));
134112578SGlenn.Faden@Sun.COM exit(Z_ERR);
134212578SGlenn.Faden@Sun.COM } else if (need_to_commit) {
134312578SGlenn.Faden@Sun.COM zerr(gettext("admin rights were updated "
134412578SGlenn.Faden@Sun.COM "to match RBAC configuration."));
134512578SGlenn.Faden@Sun.COM }
134612578SGlenn.Faden@Sun.COM
13473247Sgjelinek } else if (global_zone && err == Z_NO_ZONE && !got_handle &&
13483247Sgjelinek !read_only_mode) {
13493247Sgjelinek /*
13503247Sgjelinek * We implicitly create the global zone config if it
13513247Sgjelinek * doesn't exist.
13523247Sgjelinek */
13533247Sgjelinek zone_dochandle_t tmphandle;
13543247Sgjelinek
13553247Sgjelinek if ((tmphandle = zonecfg_init_handle()) == NULL) {
13566215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
13573247Sgjelinek exit(Z_ERR);
13583247Sgjelinek }
13593247Sgjelinek
13603247Sgjelinek err = zonecfg_get_template_handle("SUNWblank", zone,
13613247Sgjelinek tmphandle);
13623247Sgjelinek
13633247Sgjelinek if (err != Z_OK) {
13643247Sgjelinek zonecfg_fini_handle(tmphandle);
13656215Sgjelinek zone_perror("SUNWblank", err, B_TRUE);
13663247Sgjelinek return (err);
13673247Sgjelinek }
13683247Sgjelinek
13696215Sgjelinek need_to_commit = B_TRUE;
13703247Sgjelinek zonecfg_fini_handle(handle);
13713247Sgjelinek handle = tmphandle;
13726215Sgjelinek got_handle = B_TRUE;
13733247Sgjelinek
13740Sstevel@tonic-gate } else {
13750Sstevel@tonic-gate zone_perror(zone, err, handle_expected || got_handle);
13760Sstevel@tonic-gate if (err == Z_NO_ZONE && !got_handle &&
13770Sstevel@tonic-gate interactive_mode && !read_only_mode)
13780Sstevel@tonic-gate (void) printf(gettext("Use '%s' to begin "
13790Sstevel@tonic-gate "configuring a new zone.\n"),
13800Sstevel@tonic-gate cmd_to_str(CMD_CREATE));
13810Sstevel@tonic-gate return (err);
13820Sstevel@tonic-gate }
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate return (Z_OK);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate
13876215Sgjelinek static boolean_t
state_atleast(zone_state_t state)1388565Sdp state_atleast(zone_state_t state)
1389565Sdp {
1390565Sdp zone_state_t state_num;
1391565Sdp int err;
1392565Sdp
1393565Sdp if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
1394565Sdp /* all states are greater than "non-existent" */
1395565Sdp if (err == Z_NO_ZONE)
1396565Sdp return (B_FALSE);
1397565Sdp zerr(gettext("Unexpectedly failed to determine state "
1398565Sdp "of zone %s: %s"), zone, zonecfg_strerror(err));
1399565Sdp exit(Z_ERR);
1400565Sdp }
1401565Sdp return (state_num >= state);
1402565Sdp }
1403565Sdp
14040Sstevel@tonic-gate /*
14050Sstevel@tonic-gate * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
14060Sstevel@tonic-gate */
14070Sstevel@tonic-gate
14080Sstevel@tonic-gate void
short_usage(int command)14090Sstevel@tonic-gate short_usage(int command)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate /* lex_lineno has already been incremented in the lexer; compensate */
14120Sstevel@tonic-gate if (cmd_file_mode) {
14130Sstevel@tonic-gate if (strcmp(cmd_file_name, "-") == 0)
14140Sstevel@tonic-gate (void) fprintf(stderr,
14150Sstevel@tonic-gate gettext("syntax error on line %d\n"),
14160Sstevel@tonic-gate lex_lineno - 1);
14170Sstevel@tonic-gate else
14180Sstevel@tonic-gate (void) fprintf(stderr,
14190Sstevel@tonic-gate gettext("syntax error on line %d of %s\n"),
14200Sstevel@tonic-gate lex_lineno - 1, cmd_file_name);
14210Sstevel@tonic-gate }
14220Sstevel@tonic-gate (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
14230Sstevel@tonic-gate helptab[command].short_usage);
14246215Sgjelinek saw_error = B_TRUE;
14250Sstevel@tonic-gate }
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate /*
14280Sstevel@tonic-gate * long_usage() is for bad semantics: e.g., wrong property type for a given
14290Sstevel@tonic-gate * resource type. It is also used by longer_usage() below.
14300Sstevel@tonic-gate */
14310Sstevel@tonic-gate
14320Sstevel@tonic-gate void
long_usage(uint_t cmd_num,boolean_t set_saw)14336215Sgjelinek long_usage(uint_t cmd_num, boolean_t set_saw)
14340Sstevel@tonic-gate {
14350Sstevel@tonic-gate (void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
14360Sstevel@tonic-gate helptab[cmd_num].short_usage);
14370Sstevel@tonic-gate (void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
14380Sstevel@tonic-gate if (set_saw)
14396215Sgjelinek saw_error = B_TRUE;
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate /*
14430Sstevel@tonic-gate * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
14440Sstevel@tonic-gate * any extra usage() flags as appropriate for whatever command.
14450Sstevel@tonic-gate */
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate void
longer_usage(uint_t cmd_num)14480Sstevel@tonic-gate longer_usage(uint_t cmd_num)
14490Sstevel@tonic-gate {
14506215Sgjelinek long_usage(cmd_num, B_FALSE);
14510Sstevel@tonic-gate if (helptab[cmd_num].flags != 0) {
14520Sstevel@tonic-gate (void) printf("\n");
14536215Sgjelinek usage(B_TRUE, helptab[cmd_num].flags);
14540Sstevel@tonic-gate }
14550Sstevel@tonic-gate }
14560Sstevel@tonic-gate
14570Sstevel@tonic-gate /*
14580Sstevel@tonic-gate * scope_usage() is simply used when a command is called from the wrong scope.
14590Sstevel@tonic-gate */
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate static void
scope_usage(uint_t cmd_num)14620Sstevel@tonic-gate scope_usage(uint_t cmd_num)
14630Sstevel@tonic-gate {
14640Sstevel@tonic-gate zerr(gettext("The %s command only makes sense in the %s scope."),
14650Sstevel@tonic-gate cmd_to_str(cmd_num),
14660Sstevel@tonic-gate global_scope ? gettext("resource") : gettext("global"));
14676215Sgjelinek saw_error = B_TRUE;
14680Sstevel@tonic-gate }
14690Sstevel@tonic-gate
14700Sstevel@tonic-gate /*
14716215Sgjelinek * On input, B_TRUE => yes, B_FALSE => no.
14726215Sgjelinek * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
14730Sstevel@tonic-gate */
14740Sstevel@tonic-gate
14750Sstevel@tonic-gate static int
ask_yesno(boolean_t default_answer,const char * question)14766215Sgjelinek ask_yesno(boolean_t default_answer, const char *question)
14770Sstevel@tonic-gate {
14780Sstevel@tonic-gate char line[64]; /* should be enough to answer yes or no */
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate if (!ok_to_prompt) {
14816215Sgjelinek saw_error = B_TRUE;
14820Sstevel@tonic-gate return (-1);
14830Sstevel@tonic-gate }
14840Sstevel@tonic-gate for (;;) {
1485565Sdp if (printf("%s (%s)? ", question,
1486565Sdp default_answer ? "[y]/n" : "y/[n]") < 0)
1487565Sdp return (-1);
1488565Sdp if (fgets(line, sizeof (line), stdin) == NULL)
1489565Sdp return (-1);
1490565Sdp
1491565Sdp if (line[0] == '\n')
14920Sstevel@tonic-gate return (default_answer ? 1 : 0);
14930Sstevel@tonic-gate if (tolower(line[0]) == 'y')
14940Sstevel@tonic-gate return (1);
14950Sstevel@tonic-gate if (tolower(line[0]) == 'n')
14960Sstevel@tonic-gate return (0);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate /*
15010Sstevel@tonic-gate * Prints warning if zone already exists.
15020Sstevel@tonic-gate * In interactive mode, prompts if we should continue anyway and returns Z_OK
15030Sstevel@tonic-gate * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
15040Sstevel@tonic-gate *
15050Sstevel@tonic-gate * Note that if a zone exists and its state is >= INSTALLED, an error message
15060Sstevel@tonic-gate * will be printed and this function will return Z_ERR regardless of mode.
15070Sstevel@tonic-gate */
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate static int
check_if_zone_already_exists(boolean_t force)15106215Sgjelinek check_if_zone_already_exists(boolean_t force)
15110Sstevel@tonic-gate {
15120Sstevel@tonic-gate char line[ZONENAME_MAX + 128]; /* enough to ask a question */
15130Sstevel@tonic-gate zone_dochandle_t tmphandle;
15140Sstevel@tonic-gate int res, answer;
15150Sstevel@tonic-gate
15160Sstevel@tonic-gate if ((tmphandle = zonecfg_init_handle()) == NULL) {
15176215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
15180Sstevel@tonic-gate exit(Z_ERR);
15190Sstevel@tonic-gate }
15200Sstevel@tonic-gate res = zonecfg_get_handle(zone, tmphandle);
15210Sstevel@tonic-gate zonecfg_fini_handle(tmphandle);
1522565Sdp if (res != Z_OK)
15230Sstevel@tonic-gate return (Z_OK);
1524565Sdp
1525565Sdp if (state_atleast(ZONE_STATE_INSTALLED)) {
15260Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s not allowed."),
15270Sstevel@tonic-gate zone, cmd_to_str(CMD_CREATE));
15280Sstevel@tonic-gate return (Z_ERR);
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate if (force) {
15320Sstevel@tonic-gate (void) printf(gettext("Zone %s already exists; overwriting.\n"),
15330Sstevel@tonic-gate zone);
15340Sstevel@tonic-gate return (Z_OK);
15350Sstevel@tonic-gate }
15360Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
15370Sstevel@tonic-gate gettext("Zone %s already exists; %s anyway"), zone,
15380Sstevel@tonic-gate cmd_to_str(CMD_CREATE));
15396215Sgjelinek if ((answer = ask_yesno(B_FALSE, line)) == -1) {
15400Sstevel@tonic-gate zerr(gettext("Zone exists, input not from terminal and -F not "
15410Sstevel@tonic-gate "specified:\n%s command ignored, exiting."),
15420Sstevel@tonic-gate cmd_to_str(CMD_CREATE));
15430Sstevel@tonic-gate exit(Z_ERR);
15440Sstevel@tonic-gate }
15450Sstevel@tonic-gate return (answer == 1 ? Z_OK : Z_ERR);
15460Sstevel@tonic-gate }
15470Sstevel@tonic-gate
15486215Sgjelinek static boolean_t
zone_is_read_only(int cmd_num)15490Sstevel@tonic-gate zone_is_read_only(int cmd_num)
15500Sstevel@tonic-gate {
15510Sstevel@tonic-gate if (strncmp(zone, "SUNW", 4) == 0) {
15520Sstevel@tonic-gate zerr(gettext("%s: zones beginning with SUNW are read-only."),
15530Sstevel@tonic-gate zone);
15546215Sgjelinek saw_error = B_TRUE;
15556215Sgjelinek return (B_TRUE);
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate if (read_only_mode) {
15580Sstevel@tonic-gate zerr(gettext("%s: cannot %s in read-only mode."), zone,
15590Sstevel@tonic-gate cmd_to_str(cmd_num));
15606215Sgjelinek saw_error = B_TRUE;
15616215Sgjelinek return (B_TRUE);
15626215Sgjelinek }
15636215Sgjelinek return (B_FALSE);
15640Sstevel@tonic-gate }
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate /*
15670Sstevel@tonic-gate * Create a new configuration.
15680Sstevel@tonic-gate */
15690Sstevel@tonic-gate void
create_func(cmd_t * cmd)15700Sstevel@tonic-gate create_func(cmd_t *cmd)
15710Sstevel@tonic-gate {
15720Sstevel@tonic-gate int err, arg;
15730Sstevel@tonic-gate char zone_template[ZONENAME_MAX];
15741507Sgjelinek char attach_path[MAXPATHLEN];
15750Sstevel@tonic-gate zone_dochandle_t tmphandle;
15766215Sgjelinek boolean_t force = B_FALSE;
15776215Sgjelinek boolean_t attach = B_FALSE;
15786215Sgjelinek boolean_t arg_err = B_FALSE;
15790Sstevel@tonic-gate
15800Sstevel@tonic-gate assert(cmd != NULL);
15810Sstevel@tonic-gate
15820Sstevel@tonic-gate /* This is the default if no arguments are given. */
15830Sstevel@tonic-gate (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate optind = 0;
15862712Snn35248 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
15872712Snn35248 != EOF) {
15880Sstevel@tonic-gate switch (arg) {
15890Sstevel@tonic-gate case '?':
15900Sstevel@tonic-gate if (optopt == '?')
15910Sstevel@tonic-gate longer_usage(CMD_CREATE);
15920Sstevel@tonic-gate else
15930Sstevel@tonic-gate short_usage(CMD_CREATE);
15946215Sgjelinek arg_err = B_TRUE;
15953691Sgjelinek break;
15961507Sgjelinek case 'a':
15971507Sgjelinek (void) strlcpy(attach_path, optarg,
15981507Sgjelinek sizeof (attach_path));
15996215Sgjelinek attach = B_TRUE;
16001507Sgjelinek break;
16010Sstevel@tonic-gate case 'b':
16020Sstevel@tonic-gate (void) strlcpy(zone_template, "SUNWblank",
16030Sstevel@tonic-gate sizeof (zone_template));
16040Sstevel@tonic-gate break;
16050Sstevel@tonic-gate case 'F':
16066215Sgjelinek force = B_TRUE;
16070Sstevel@tonic-gate break;
16080Sstevel@tonic-gate case 't':
16090Sstevel@tonic-gate (void) strlcpy(zone_template, optarg,
16100Sstevel@tonic-gate sizeof (zone_template));
16110Sstevel@tonic-gate break;
16120Sstevel@tonic-gate default:
16130Sstevel@tonic-gate short_usage(CMD_CREATE);
16146215Sgjelinek arg_err = B_TRUE;
16153691Sgjelinek break;
16163691Sgjelinek }
16173691Sgjelinek }
16183691Sgjelinek if (arg_err)
16193691Sgjelinek return;
16203691Sgjelinek
16210Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
16220Sstevel@tonic-gate short_usage(CMD_CREATE);
16230Sstevel@tonic-gate return;
16240Sstevel@tonic-gate }
16250Sstevel@tonic-gate
16260Sstevel@tonic-gate if (zone_is_read_only(CMD_CREATE))
16270Sstevel@tonic-gate return;
16280Sstevel@tonic-gate
16290Sstevel@tonic-gate if (check_if_zone_already_exists(force) != Z_OK)
16300Sstevel@tonic-gate return;
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate /*
16330Sstevel@tonic-gate * Get a temporary handle first. If that fails, the old handle
16340Sstevel@tonic-gate * will not be lost. Then finish whichever one we don't need,
16350Sstevel@tonic-gate * to avoid leaks. Then get the handle for zone_template, and
16360Sstevel@tonic-gate * set the name to zone: this "copy, rename" method is how
16370Sstevel@tonic-gate * create -[b|t] works.
16380Sstevel@tonic-gate */
16390Sstevel@tonic-gate if ((tmphandle = zonecfg_init_handle()) == NULL) {
16406215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
16410Sstevel@tonic-gate exit(Z_ERR);
16420Sstevel@tonic-gate }
16431507Sgjelinek
16441507Sgjelinek if (attach)
16457257Sgjelinek err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
16467257Sgjelinek zone, B_FALSE, tmphandle);
16471507Sgjelinek else
16481507Sgjelinek err = zonecfg_get_template_handle(zone_template, zone,
16491507Sgjelinek tmphandle);
16501507Sgjelinek
16511507Sgjelinek if (err != Z_OK) {
16520Sstevel@tonic-gate zonecfg_fini_handle(tmphandle);
16531507Sgjelinek if (attach && err == Z_NO_ZONE)
16541507Sgjelinek (void) fprintf(stderr, gettext("invalid path to "
16551507Sgjelinek "detached zone\n"));
16561507Sgjelinek else if (attach && err == Z_INVALID_DOCUMENT)
16571507Sgjelinek (void) fprintf(stderr, gettext("Cannot attach to an "
16581507Sgjelinek "earlier release of the operating system\n"));
16591507Sgjelinek else
16606215Sgjelinek zone_perror(zone_template, err, B_TRUE);
16616215Sgjelinek return;
16626215Sgjelinek }
16636215Sgjelinek
16646215Sgjelinek need_to_commit = B_TRUE;
16650Sstevel@tonic-gate zonecfg_fini_handle(handle);
16660Sstevel@tonic-gate handle = tmphandle;
16676215Sgjelinek got_handle = B_TRUE;
16680Sstevel@tonic-gate }
16690Sstevel@tonic-gate
16700Sstevel@tonic-gate /*
16710Sstevel@tonic-gate * This malloc()'s memory, which must be freed by the caller.
16720Sstevel@tonic-gate */
16730Sstevel@tonic-gate static char *
quoteit(char * instr)16740Sstevel@tonic-gate quoteit(char *instr)
16750Sstevel@tonic-gate {
16760Sstevel@tonic-gate char *outstr;
16770Sstevel@tonic-gate size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate if ((outstr = malloc(outstrsize)) == NULL) {
16806215Sgjelinek zone_perror(zone, Z_NOMEM, B_FALSE);
16810Sstevel@tonic-gate exit(Z_ERR);
16820Sstevel@tonic-gate }
16830Sstevel@tonic-gate if (strchr(instr, ' ') == NULL) {
16840Sstevel@tonic-gate (void) strlcpy(outstr, instr, outstrsize);
16850Sstevel@tonic-gate return (outstr);
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
16880Sstevel@tonic-gate return (outstr);
16890Sstevel@tonic-gate }
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate static void
export_prop(FILE * of,int prop_num,char * prop_id)16920Sstevel@tonic-gate export_prop(FILE *of, int prop_num, char *prop_id)
16930Sstevel@tonic-gate {
16940Sstevel@tonic-gate char *quote_str;
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate if (strlen(prop_id) == 0)
16970Sstevel@tonic-gate return;
16980Sstevel@tonic-gate quote_str = quoteit(prop_id);
16990Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17000Sstevel@tonic-gate pt_to_str(prop_num), quote_str);
17010Sstevel@tonic-gate free(quote_str);
17020Sstevel@tonic-gate }
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate void
export_func(cmd_t * cmd)17050Sstevel@tonic-gate export_func(cmd_t *cmd)
17060Sstevel@tonic-gate {
17070Sstevel@tonic-gate struct zone_nwiftab nwiftab;
17080Sstevel@tonic-gate struct zone_fstab fstab;
17090Sstevel@tonic-gate struct zone_devtab devtab;
17100Sstevel@tonic-gate struct zone_attrtab attrtab;
17110Sstevel@tonic-gate struct zone_rctltab rctltab;
1712789Sahrens struct zone_dstab dstab;
17133247Sgjelinek struct zone_psettab psettab;
17143247Sgjelinek struct zone_mcaptab mcaptab;
17150Sstevel@tonic-gate struct zone_rctlvaltab *valptr;
171612578SGlenn.Faden@Sun.COM struct zone_admintab admintab;
17170Sstevel@tonic-gate int err, arg;
17180Sstevel@tonic-gate char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
17192267Sdp char bootargs[BOOTARGS_MAX];
17203247Sgjelinek char sched[MAXNAMELEN];
17212712Snn35248 char brand[MAXNAMELEN];
17228662SJordan.Vaughan@Sun.com char hostidp[HW_HOSTID_LEN];
172312633Sjohn.levon@sun.com char fsallowedp[ZONE_FS_ALLOWED_MAX];
17241645Scomay char *limitpriv;
17250Sstevel@tonic-gate FILE *of;
17260Sstevel@tonic-gate boolean_t autoboot;
17273448Sdh155122 zone_iptype_t iptype;
17286215Sgjelinek boolean_t need_to_close = B_FALSE;
17296215Sgjelinek boolean_t arg_err = B_FALSE;
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate assert(cmd != NULL);
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate outfile[0] = '\0';
17340Sstevel@tonic-gate optind = 0;
17350Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
17360Sstevel@tonic-gate switch (arg) {
17370Sstevel@tonic-gate case '?':
17380Sstevel@tonic-gate if (optopt == '?')
17390Sstevel@tonic-gate longer_usage(CMD_EXPORT);
17400Sstevel@tonic-gate else
17410Sstevel@tonic-gate short_usage(CMD_EXPORT);
17426215Sgjelinek arg_err = B_TRUE;
17433691Sgjelinek break;
17440Sstevel@tonic-gate case 'f':
17450Sstevel@tonic-gate (void) strlcpy(outfile, optarg, sizeof (outfile));
17460Sstevel@tonic-gate break;
17470Sstevel@tonic-gate default:
17480Sstevel@tonic-gate short_usage(CMD_EXPORT);
17496215Sgjelinek arg_err = B_TRUE;
17503691Sgjelinek break;
17513691Sgjelinek }
17523691Sgjelinek }
17533691Sgjelinek if (arg_err)
17543691Sgjelinek return;
17553691Sgjelinek
17560Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
17570Sstevel@tonic-gate short_usage(CMD_EXPORT);
17580Sstevel@tonic-gate return;
17590Sstevel@tonic-gate }
17600Sstevel@tonic-gate if (strlen(outfile) == 0) {
17610Sstevel@tonic-gate of = stdout;
17620Sstevel@tonic-gate } else {
17630Sstevel@tonic-gate if ((of = fopen(outfile, "w")) == NULL) {
17640Sstevel@tonic-gate zerr(gettext("opening file %s: %s"),
17650Sstevel@tonic-gate outfile, strerror(errno));
17660Sstevel@tonic-gate goto done;
17670Sstevel@tonic-gate }
17680Sstevel@tonic-gate setbuf(of, NULL);
17696215Sgjelinek need_to_close = B_TRUE;
17706215Sgjelinek }
17716215Sgjelinek
17726215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
17730Sstevel@tonic-gate goto done;
17740Sstevel@tonic-gate
17750Sstevel@tonic-gate (void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
17780Sstevel@tonic-gate strlen(zonepath) > 0)
17790Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17800Sstevel@tonic-gate pt_to_str(PT_ZONEPATH), zonepath);
17810Sstevel@tonic-gate
17822712Snn35248 if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
17832712Snn35248 (strcmp(brand, NATIVE_BRAND_NAME) != 0))
17842712Snn35248 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17852712Snn35248 pt_to_str(PT_BRAND), brand);
17862712Snn35248
17870Sstevel@tonic-gate if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
17880Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17890Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
17900Sstevel@tonic-gate
17912267Sdp if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
17922267Sdp strlen(bootargs) > 0) {
17932267Sdp (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
17942267Sdp pt_to_str(PT_BOOTARGS), bootargs);
17952267Sdp }
17962267Sdp
17970Sstevel@tonic-gate if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
17980Sstevel@tonic-gate strlen(pool) > 0)
17990Sstevel@tonic-gate (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18000Sstevel@tonic-gate pt_to_str(PT_POOL), pool);
18010Sstevel@tonic-gate
18021645Scomay if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
18031645Scomay strlen(limitpriv) > 0) {
18041645Scomay (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18051645Scomay pt_to_str(PT_LIMITPRIV), limitpriv);
18061645Scomay free(limitpriv);
18071645Scomay }
18081645Scomay
18093247Sgjelinek if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
18103247Sgjelinek strlen(sched) > 0)
18113247Sgjelinek (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18123247Sgjelinek pt_to_str(PT_SCHED), sched);
18132267Sdp
18143448Sdh155122 if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
18153448Sdh155122 switch (iptype) {
18163448Sdh155122 case ZS_SHARED:
18173448Sdh155122 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18183448Sdh155122 pt_to_str(PT_IPTYPE), "shared");
18193448Sdh155122 break;
18203448Sdh155122 case ZS_EXCLUSIVE:
18213448Sdh155122 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18223448Sdh155122 pt_to_str(PT_IPTYPE), "exclusive");
18233448Sdh155122 break;
18243448Sdh155122 }
18253448Sdh155122 }
18263448Sdh155122
18278662SJordan.Vaughan@Sun.com if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
18288662SJordan.Vaughan@Sun.com (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
18298662SJordan.Vaughan@Sun.com pt_to_str(PT_HOSTID), hostidp);
18308662SJordan.Vaughan@Sun.com }
18318662SJordan.Vaughan@Sun.com
183212633Sjohn.levon@sun.com if (zonecfg_get_fs_allowed(handle, fsallowedp,
183312633Sjohn.levon@sun.com sizeof (fsallowedp)) == Z_OK) {
183412633Sjohn.levon@sun.com (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
183512633Sjohn.levon@sun.com pt_to_str(PT_FS_ALLOWED), fsallowedp);
183612633Sjohn.levon@sun.com }
183712633Sjohn.levon@sun.com
18380Sstevel@tonic-gate if ((err = zonecfg_setfsent(handle)) != Z_OK) {
18396215Sgjelinek zone_perror(zone, err, B_FALSE);
18400Sstevel@tonic-gate goto done;
18410Sstevel@tonic-gate }
18420Sstevel@tonic-gate while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
18430Sstevel@tonic-gate zone_fsopt_t *optptr;
18440Sstevel@tonic-gate
18450Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18460Sstevel@tonic-gate rt_to_str(RT_FS));
18470Sstevel@tonic-gate export_prop(of, PT_DIR, fstab.zone_fs_dir);
18480Sstevel@tonic-gate export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
18490Sstevel@tonic-gate export_prop(of, PT_RAW, fstab.zone_fs_raw);
18500Sstevel@tonic-gate export_prop(of, PT_TYPE, fstab.zone_fs_type);
18510Sstevel@tonic-gate for (optptr = fstab.zone_fs_options; optptr != NULL;
18520Sstevel@tonic-gate optptr = optptr->zone_fsopt_next) {
18530Sstevel@tonic-gate /*
18540Sstevel@tonic-gate * Simple property values with embedded equal signs
18550Sstevel@tonic-gate * need to be quoted to prevent the lexer from
18560Sstevel@tonic-gate * mis-parsing them as complex name=value pairs.
18570Sstevel@tonic-gate */
18580Sstevel@tonic-gate if (strchr(optptr->zone_fsopt_opt, '='))
18590Sstevel@tonic-gate (void) fprintf(of, "%s %s \"%s\"\n",
18600Sstevel@tonic-gate cmd_to_str(CMD_ADD),
18610Sstevel@tonic-gate pt_to_str(PT_OPTIONS),
18620Sstevel@tonic-gate optptr->zone_fsopt_opt);
18630Sstevel@tonic-gate else
18640Sstevel@tonic-gate (void) fprintf(of, "%s %s %s\n",
18650Sstevel@tonic-gate cmd_to_str(CMD_ADD),
18660Sstevel@tonic-gate pt_to_str(PT_OPTIONS),
18670Sstevel@tonic-gate optptr->zone_fsopt_opt);
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18700Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options);
18710Sstevel@tonic-gate }
18720Sstevel@tonic-gate (void) zonecfg_endfsent(handle);
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
18756215Sgjelinek zone_perror(zone, err, B_FALSE);
18760Sstevel@tonic-gate goto done;
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
18790Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18800Sstevel@tonic-gate rt_to_str(RT_NET));
18810Sstevel@tonic-gate export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
188212748SSowmini.Varadhan@oracle.COM export_prop(of, PT_ALLOWED_ADDRESS,
188312748SSowmini.Varadhan@oracle.COM nwiftab.zone_nwif_allowed_address);
18840Sstevel@tonic-gate export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
18856076Sgfaden export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
18860Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18870Sstevel@tonic-gate }
18880Sstevel@tonic-gate (void) zonecfg_endnwifent(handle);
18890Sstevel@tonic-gate
18900Sstevel@tonic-gate if ((err = zonecfg_setdevent(handle)) != Z_OK) {
18916215Sgjelinek zone_perror(zone, err, B_FALSE);
18920Sstevel@tonic-gate goto done;
18930Sstevel@tonic-gate }
18940Sstevel@tonic-gate while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
18950Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
18960Sstevel@tonic-gate rt_to_str(RT_DEVICE));
18970Sstevel@tonic-gate export_prop(of, PT_MATCH, devtab.zone_dev_match);
18980Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
18990Sstevel@tonic-gate }
19000Sstevel@tonic-gate (void) zonecfg_enddevent(handle);
19010Sstevel@tonic-gate
190212626SGerald.Jelinek@Sun.COM if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
190312626SGerald.Jelinek@Sun.COM char buf[128];
190412626SGerald.Jelinek@Sun.COM
190512626SGerald.Jelinek@Sun.COM (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
190612626SGerald.Jelinek@Sun.COM rt_to_str(RT_MCAP));
190712626SGerald.Jelinek@Sun.COM bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
190812626SGerald.Jelinek@Sun.COM (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
190912626SGerald.Jelinek@Sun.COM pt_to_str(PT_PHYSICAL), buf);
191012626SGerald.Jelinek@Sun.COM (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
191112626SGerald.Jelinek@Sun.COM }
191212626SGerald.Jelinek@Sun.COM
19130Sstevel@tonic-gate if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
19146215Sgjelinek zone_perror(zone, err, B_FALSE);
19150Sstevel@tonic-gate goto done;
19160Sstevel@tonic-gate }
19170Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
19180Sstevel@tonic-gate (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
19190Sstevel@tonic-gate export_prop(of, PT_NAME, rctltab.zone_rctl_name);
19200Sstevel@tonic-gate for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
19210Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) {
19220Sstevel@tonic-gate fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
19230Sstevel@tonic-gate cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
19240Sstevel@tonic-gate pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
19250Sstevel@tonic-gate pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
19260Sstevel@tonic-gate pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19290Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
19300Sstevel@tonic-gate }
19310Sstevel@tonic-gate (void) zonecfg_endrctlent(handle);
19320Sstevel@tonic-gate
19330Sstevel@tonic-gate if ((err = zonecfg_setattrent(handle)) != Z_OK) {
19346215Sgjelinek zone_perror(zone, err, B_FALSE);
19350Sstevel@tonic-gate goto done;
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
19380Sstevel@tonic-gate (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
19390Sstevel@tonic-gate rt_to_str(RT_ATTR));
19400Sstevel@tonic-gate export_prop(of, PT_NAME, attrtab.zone_attr_name);
19410Sstevel@tonic-gate export_prop(of, PT_TYPE, attrtab.zone_attr_type);
19420Sstevel@tonic-gate export_prop(of, PT_VALUE, attrtab.zone_attr_value);
19430Sstevel@tonic-gate (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19440Sstevel@tonic-gate }
19450Sstevel@tonic-gate (void) zonecfg_endattrent(handle);
19460Sstevel@tonic-gate
1947789Sahrens if ((err = zonecfg_setdsent(handle)) != Z_OK) {
19486215Sgjelinek zone_perror(zone, err, B_FALSE);
1949789Sahrens goto done;
1950789Sahrens }
1951789Sahrens while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
1952789Sahrens (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1953789Sahrens rt_to_str(RT_DATASET));
1954789Sahrens export_prop(of, PT_NAME, dstab.zone_dataset_name);
1955789Sahrens (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1956789Sahrens }
1957789Sahrens (void) zonecfg_enddsent(handle);
1958789Sahrens
19593247Sgjelinek if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
19603247Sgjelinek (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
19613247Sgjelinek rt_to_str(RT_DCPU));
19623247Sgjelinek if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
19633247Sgjelinek (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
19643247Sgjelinek pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
19653247Sgjelinek else
19663247Sgjelinek (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
19673247Sgjelinek pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
19683247Sgjelinek psettab.zone_ncpu_max);
19693247Sgjelinek if (psettab.zone_importance[0] != '\0')
19703247Sgjelinek (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
19713247Sgjelinek pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
19723247Sgjelinek (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
19733247Sgjelinek }
19743247Sgjelinek
197512578SGlenn.Faden@Sun.COM if ((err = zonecfg_setadminent(handle)) != Z_OK) {
197612578SGlenn.Faden@Sun.COM zone_perror(zone, err, B_FALSE);
197712578SGlenn.Faden@Sun.COM goto done;
197812578SGlenn.Faden@Sun.COM }
197912578SGlenn.Faden@Sun.COM while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
198012578SGlenn.Faden@Sun.COM (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
198112578SGlenn.Faden@Sun.COM rt_to_str(RT_ADMIN));
198212578SGlenn.Faden@Sun.COM export_prop(of, PT_USER, admintab.zone_admin_user);
198312578SGlenn.Faden@Sun.COM export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
198412578SGlenn.Faden@Sun.COM (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
198512578SGlenn.Faden@Sun.COM }
198612578SGlenn.Faden@Sun.COM (void) zonecfg_endadminent(handle);
198712578SGlenn.Faden@Sun.COM
19883792Sakolb /*
19893792Sakolb * There is nothing to export for pcap since this resource is just
19903792Sakolb * a container for an rctl alias.
19913792Sakolb */
19923792Sakolb
19930Sstevel@tonic-gate done:
19940Sstevel@tonic-gate if (need_to_close)
19950Sstevel@tonic-gate (void) fclose(of);
19960Sstevel@tonic-gate }
19970Sstevel@tonic-gate
19980Sstevel@tonic-gate void
exit_func(cmd_t * cmd)19990Sstevel@tonic-gate exit_func(cmd_t *cmd)
20000Sstevel@tonic-gate {
20010Sstevel@tonic-gate int arg, answer;
20026215Sgjelinek boolean_t arg_err = B_FALSE;
20030Sstevel@tonic-gate
20040Sstevel@tonic-gate optind = 0;
20050Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
20060Sstevel@tonic-gate switch (arg) {
20070Sstevel@tonic-gate case '?':
20080Sstevel@tonic-gate longer_usage(CMD_EXIT);
20096215Sgjelinek arg_err = B_TRUE;
20103691Sgjelinek break;
20110Sstevel@tonic-gate case 'F':
20126215Sgjelinek force_exit = B_TRUE;
20130Sstevel@tonic-gate break;
20140Sstevel@tonic-gate default:
20150Sstevel@tonic-gate short_usage(CMD_EXIT);
20166215Sgjelinek arg_err = B_TRUE;
20173691Sgjelinek break;
20183691Sgjelinek }
20193691Sgjelinek }
20203691Sgjelinek if (arg_err)
20213691Sgjelinek return;
20223691Sgjelinek
20230Sstevel@tonic-gate if (optind < cmd->cmd_argc) {
20240Sstevel@tonic-gate short_usage(CMD_EXIT);
20250Sstevel@tonic-gate return;
20260Sstevel@tonic-gate }
20270Sstevel@tonic-gate
20280Sstevel@tonic-gate if (global_scope || force_exit) {
20296215Sgjelinek time_to_exit = B_TRUE;
20306215Sgjelinek return;
20316215Sgjelinek }
20326215Sgjelinek
20336215Sgjelinek answer = ask_yesno(B_FALSE, "Resource incomplete; really quit");
20340Sstevel@tonic-gate if (answer == -1) {
20350Sstevel@tonic-gate zerr(gettext("Resource incomplete, input "
20360Sstevel@tonic-gate "not from terminal and -F not specified:\n%s command "
20370Sstevel@tonic-gate "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
20380Sstevel@tonic-gate exit(Z_ERR);
20390Sstevel@tonic-gate } else if (answer == 1) {
20406215Sgjelinek time_to_exit = B_TRUE;
20410Sstevel@tonic-gate }
20420Sstevel@tonic-gate /* (answer == 0) => just return */
20430Sstevel@tonic-gate }
20440Sstevel@tonic-gate
20450Sstevel@tonic-gate static int
validate_zonepath_syntax(char * path)20460Sstevel@tonic-gate validate_zonepath_syntax(char *path)
20470Sstevel@tonic-gate {
20480Sstevel@tonic-gate if (path[0] != '/') {
20490Sstevel@tonic-gate zerr(gettext("%s is not an absolute path."), path);
20500Sstevel@tonic-gate return (Z_ERR);
20510Sstevel@tonic-gate }
205212715SSusan.Kamm-Worrell@Sun.COM /* If path is all slashes, then fail */
205312715SSusan.Kamm-Worrell@Sun.COM if (strspn(path, "/") == strlen(path)) {
20540Sstevel@tonic-gate zerr(gettext("/ is not allowed as a %s."),
20550Sstevel@tonic-gate pt_to_str(PT_ZONEPATH));
20560Sstevel@tonic-gate return (Z_ERR);
20570Sstevel@tonic-gate }
20580Sstevel@tonic-gate return (Z_OK);
20590Sstevel@tonic-gate }
20600Sstevel@tonic-gate
20610Sstevel@tonic-gate static void
add_resource(cmd_t * cmd)20620Sstevel@tonic-gate add_resource(cmd_t *cmd)
20630Sstevel@tonic-gate {
20640Sstevel@tonic-gate int type;
20653247Sgjelinek struct zone_psettab tmp_psettab;
20663247Sgjelinek struct zone_mcaptab tmp_mcaptab;
20673792Sakolb uint64_t tmp;
20683247Sgjelinek uint64_t tmp_mcap;
20693247Sgjelinek char pool[MAXNAMELEN];
20700Sstevel@tonic-gate
20710Sstevel@tonic-gate if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
20726215Sgjelinek long_usage(CMD_ADD, B_TRUE);
20730Sstevel@tonic-gate goto bad;
20740Sstevel@tonic-gate }
20750Sstevel@tonic-gate
20760Sstevel@tonic-gate switch (type) {
20770Sstevel@tonic-gate case RT_FS:
20780Sstevel@tonic-gate bzero(&in_progress_fstab, sizeof (in_progress_fstab));
20790Sstevel@tonic-gate return;
20800Sstevel@tonic-gate case RT_NET:
20810Sstevel@tonic-gate bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
20820Sstevel@tonic-gate return;
20830Sstevel@tonic-gate case RT_DEVICE:
20840Sstevel@tonic-gate bzero(&in_progress_devtab, sizeof (in_progress_devtab));
20850Sstevel@tonic-gate return;
20860Sstevel@tonic-gate case RT_RCTL:
20873247Sgjelinek if (global_zone)
20883247Sgjelinek zerr(gettext("WARNING: Setting a global zone resource "
20893247Sgjelinek "control too low could deny\nservice "
20903247Sgjelinek "to even the root user; "
20913247Sgjelinek "this could render the system impossible\n"
20923247Sgjelinek "to administer. Please use caution."));
20930Sstevel@tonic-gate bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
20940Sstevel@tonic-gate return;
20950Sstevel@tonic-gate case RT_ATTR:
20960Sstevel@tonic-gate bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
20970Sstevel@tonic-gate return;
2098789Sahrens case RT_DATASET:
2099789Sahrens bzero(&in_progress_dstab, sizeof (in_progress_dstab));
2100789Sahrens return;
21013247Sgjelinek case RT_DCPU:
21023792Sakolb /* Make sure there isn't already a cpu-set or cpu-cap entry. */
21033247Sgjelinek if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
21043247Sgjelinek zerr(gettext("The %s resource already exists."),
21053247Sgjelinek rt_to_str(RT_DCPU));
21063247Sgjelinek goto bad;
21073247Sgjelinek }
21083792Sakolb if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
21093792Sakolb Z_NO_ENTRY) {
21103792Sakolb zerr(gettext("The %s resource already exists."),
21113792Sakolb rt_to_str(RT_PCAP));
21123792Sakolb goto bad;
21133792Sakolb }
21143247Sgjelinek
21153247Sgjelinek /* Make sure the pool property isn't set. */
21163247Sgjelinek if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
21173247Sgjelinek strlen(pool) > 0) {
21183247Sgjelinek zerr(gettext("The %s property is already set. "
21193247Sgjelinek "A persistent pool is incompatible with\nthe %s "
21203247Sgjelinek "resource."),
21213247Sgjelinek pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
21223247Sgjelinek goto bad;
21233247Sgjelinek }
21243247Sgjelinek
21253247Sgjelinek bzero(&in_progress_psettab, sizeof (in_progress_psettab));
21263247Sgjelinek return;
21273792Sakolb case RT_PCAP:
21283792Sakolb /*
21293792Sakolb * Make sure there isn't already a cpu-set or incompatible
21303792Sakolb * cpu-cap rctls.
21313792Sakolb */
21323792Sakolb if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
21333792Sakolb zerr(gettext("The %s resource already exists."),
21343792Sakolb rt_to_str(RT_DCPU));
21353792Sakolb goto bad;
21363792Sakolb }
21373792Sakolb
21383792Sakolb switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
21393792Sakolb case Z_ALIAS_DISALLOW:
21403792Sakolb zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
21416215Sgjelinek B_FALSE);
21423792Sakolb goto bad;
21433792Sakolb
21443792Sakolb case Z_OK:
21453792Sakolb zerr(gettext("The %s resource already exists."),
21463792Sakolb rt_to_str(RT_PCAP));
21473792Sakolb goto bad;
21483792Sakolb
21493792Sakolb default:
21503792Sakolb break;
21513792Sakolb }
21523792Sakolb return;
21533247Sgjelinek case RT_MCAP:
21543247Sgjelinek /*
21553247Sgjelinek * Make sure there isn't already a mem-cap entry or max-swap
21563247Sgjelinek * or max-locked rctl.
21573247Sgjelinek */
21583247Sgjelinek if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
21593247Sgjelinek zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
21603247Sgjelinek == Z_OK ||
21613247Sgjelinek zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
21623247Sgjelinek &tmp_mcap) == Z_OK) {
21633247Sgjelinek zerr(gettext("The %s resource or a related resource "
21643247Sgjelinek "control already exists."), rt_to_str(RT_MCAP));
21653247Sgjelinek goto bad;
21663247Sgjelinek }
21673247Sgjelinek if (global_zone)
21683247Sgjelinek zerr(gettext("WARNING: Setting a global zone memory "
21693247Sgjelinek "cap too low could deny\nservice "
21703247Sgjelinek "to even the root user; "
21713247Sgjelinek "this could render the system impossible\n"
21723247Sgjelinek "to administer. Please use caution."));
21733247Sgjelinek bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
21743247Sgjelinek return;
217512578SGlenn.Faden@Sun.COM case RT_ADMIN:
217612578SGlenn.Faden@Sun.COM bzero(&in_progress_admintab, sizeof (in_progress_admintab));
217712578SGlenn.Faden@Sun.COM return;
21780Sstevel@tonic-gate default:
21796215Sgjelinek zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
21806215Sgjelinek long_usage(CMD_ADD, B_TRUE);
21816215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
21820Sstevel@tonic-gate }
21830Sstevel@tonic-gate bad:
21846215Sgjelinek global_scope = B_TRUE;
21850Sstevel@tonic-gate end_op = -1;
21860Sstevel@tonic-gate }
21870Sstevel@tonic-gate
21880Sstevel@tonic-gate static void
do_complex_rctl_val(complex_property_ptr_t cp)21890Sstevel@tonic-gate do_complex_rctl_val(complex_property_ptr_t cp)
21900Sstevel@tonic-gate {
21910Sstevel@tonic-gate struct zone_rctlvaltab *rctlvaltab;
21920Sstevel@tonic-gate complex_property_ptr_t cx;
21936215Sgjelinek boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
21946215Sgjelinek seen_action = B_FALSE;
21950Sstevel@tonic-gate rctlblk_t *rctlblk;
21960Sstevel@tonic-gate int err;
21970Sstevel@tonic-gate
21980Sstevel@tonic-gate if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
21996215Sgjelinek zone_perror(zone, Z_NOMEM, B_TRUE);
22000Sstevel@tonic-gate exit(Z_ERR);
22010Sstevel@tonic-gate }
22020Sstevel@tonic-gate for (cx = cp; cx != NULL; cx = cx->cp_next) {
22030Sstevel@tonic-gate switch (cx->cp_type) {
22040Sstevel@tonic-gate case PT_PRIV:
22050Sstevel@tonic-gate if (seen_priv) {
22060Sstevel@tonic-gate zerr(gettext("%s already specified"),
22070Sstevel@tonic-gate pt_to_str(PT_PRIV));
22080Sstevel@tonic-gate goto bad;
22090Sstevel@tonic-gate }
22100Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_priv,
22110Sstevel@tonic-gate cx->cp_value,
22120Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_priv));
22136215Sgjelinek seen_priv = B_TRUE;
22140Sstevel@tonic-gate break;
22150Sstevel@tonic-gate case PT_LIMIT:
22160Sstevel@tonic-gate if (seen_limit) {
22170Sstevel@tonic-gate zerr(gettext("%s already specified"),
22180Sstevel@tonic-gate pt_to_str(PT_LIMIT));
22190Sstevel@tonic-gate goto bad;
22200Sstevel@tonic-gate }
22210Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_limit,
22220Sstevel@tonic-gate cx->cp_value,
22230Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_limit));
22246215Sgjelinek seen_limit = B_TRUE;
22250Sstevel@tonic-gate break;
22260Sstevel@tonic-gate case PT_ACTION:
22270Sstevel@tonic-gate if (seen_action) {
22280Sstevel@tonic-gate zerr(gettext("%s already specified"),
22290Sstevel@tonic-gate pt_to_str(PT_ACTION));
22300Sstevel@tonic-gate goto bad;
22310Sstevel@tonic-gate }
22320Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_action,
22330Sstevel@tonic-gate cx->cp_value,
22340Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_action));
22356215Sgjelinek seen_action = B_TRUE;
22360Sstevel@tonic-gate break;
22370Sstevel@tonic-gate default:
22380Sstevel@tonic-gate zone_perror(pt_to_str(PT_VALUE),
22396215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
22406215Sgjelinek long_usage(CMD_ADD, B_TRUE);
22416215Sgjelinek usage(B_FALSE, HELP_PROPS);
22420Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab);
22430Sstevel@tonic-gate return;
22440Sstevel@tonic-gate }
22450Sstevel@tonic-gate }
22460Sstevel@tonic-gate if (!seen_priv)
22470Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
22480Sstevel@tonic-gate if (!seen_limit)
22490Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
22500Sstevel@tonic-gate if (!seen_action)
22510Sstevel@tonic-gate zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
22520Sstevel@tonic-gate if (!seen_priv || !seen_limit || !seen_action)
22530Sstevel@tonic-gate goto bad;
22540Sstevel@tonic-gate rctlvaltab->zone_rctlval_next = NULL;
22550Sstevel@tonic-gate rctlblk = alloca(rctlblk_size());
22560Sstevel@tonic-gate /*
22570Sstevel@tonic-gate * Make sure the rctl value looks roughly correct; we won't know if
22580Sstevel@tonic-gate * it's truly OK until we verify the configuration on the target
22590Sstevel@tonic-gate * system.
22600Sstevel@tonic-gate */
22610Sstevel@tonic-gate if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
22620Sstevel@tonic-gate !zonecfg_valid_rctlblk(rctlblk)) {
22630Sstevel@tonic-gate zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
22640Sstevel@tonic-gate pt_to_str(PT_VALUE));
22650Sstevel@tonic-gate goto bad;
22660Sstevel@tonic-gate }
22670Sstevel@tonic-gate err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
22680Sstevel@tonic-gate if (err != Z_OK)
22696215Sgjelinek zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
22700Sstevel@tonic-gate return;
22710Sstevel@tonic-gate
22720Sstevel@tonic-gate bad:
22730Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab);
22740Sstevel@tonic-gate }
22750Sstevel@tonic-gate
22760Sstevel@tonic-gate static void
add_property(cmd_t * cmd)22770Sstevel@tonic-gate add_property(cmd_t *cmd)
22780Sstevel@tonic-gate {
22790Sstevel@tonic-gate char *prop_id;
22800Sstevel@tonic-gate int err, res_type, prop_type;
22810Sstevel@tonic-gate property_value_ptr_t pp;
22820Sstevel@tonic-gate list_property_ptr_t l;
22830Sstevel@tonic-gate
22840Sstevel@tonic-gate res_type = resource_scope;
22850Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0];
22860Sstevel@tonic-gate if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
22876215Sgjelinek long_usage(CMD_ADD, B_TRUE);
22880Sstevel@tonic-gate return;
22890Sstevel@tonic-gate }
22900Sstevel@tonic-gate
22910Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs != 1) {
22926215Sgjelinek long_usage(CMD_ADD, B_TRUE);
22936215Sgjelinek return;
22946215Sgjelinek }
22956215Sgjelinek
22966215Sgjelinek if (initialize(B_TRUE) != Z_OK)
22970Sstevel@tonic-gate return;
22980Sstevel@tonic-gate
22990Sstevel@tonic-gate switch (res_type) {
23000Sstevel@tonic-gate case RT_FS:
23010Sstevel@tonic-gate if (prop_type != PT_OPTIONS) {
23020Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
23036215Sgjelinek B_TRUE);
23046215Sgjelinek long_usage(CMD_ADD, B_TRUE);
23056215Sgjelinek usage(B_FALSE, HELP_PROPS);
23060Sstevel@tonic-gate return;
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0];
23090Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE &&
23100Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) {
23110Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."),
23120Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE),
23130Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST));
23146215Sgjelinek saw_error = B_TRUE;
23150Sstevel@tonic-gate return;
23160Sstevel@tonic-gate }
23170Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_SIMPLE) {
23180Sstevel@tonic-gate if (pp->pv_simple == NULL) {
23196215Sgjelinek long_usage(CMD_ADD, B_TRUE);
23200Sstevel@tonic-gate return;
23210Sstevel@tonic-gate }
23220Sstevel@tonic-gate prop_id = pp->pv_simple;
23230Sstevel@tonic-gate err = zonecfg_add_fs_option(&in_progress_fstab,
23240Sstevel@tonic-gate prop_id);
23250Sstevel@tonic-gate if (err != Z_OK)
23266215Sgjelinek zone_perror(pt_to_str(prop_type), err, B_TRUE);
23270Sstevel@tonic-gate } else {
23280Sstevel@tonic-gate list_property_ptr_t list;
23290Sstevel@tonic-gate
23300Sstevel@tonic-gate for (list = pp->pv_list; list != NULL;
23310Sstevel@tonic-gate list = list->lp_next) {
23320Sstevel@tonic-gate prop_id = list->lp_simple;
23330Sstevel@tonic-gate if (prop_id == NULL)
23340Sstevel@tonic-gate break;
23350Sstevel@tonic-gate err = zonecfg_add_fs_option(
23360Sstevel@tonic-gate &in_progress_fstab, prop_id);
23370Sstevel@tonic-gate if (err != Z_OK)
23380Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err,
23396215Sgjelinek B_TRUE);
23400Sstevel@tonic-gate }
23410Sstevel@tonic-gate }
23420Sstevel@tonic-gate return;
23430Sstevel@tonic-gate case RT_RCTL:
23440Sstevel@tonic-gate if (prop_type != PT_VALUE) {
23450Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
23466215Sgjelinek B_TRUE);
23476215Sgjelinek long_usage(CMD_ADD, B_TRUE);
23486215Sgjelinek usage(B_FALSE, HELP_PROPS);
23490Sstevel@tonic-gate return;
23500Sstevel@tonic-gate }
23510Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0];
23520Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX &&
23530Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) {
23540Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."),
23550Sstevel@tonic-gate pvt_to_str(PROP_VAL_COMPLEX),
23560Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST));
23576215Sgjelinek saw_error = B_TRUE;
23580Sstevel@tonic-gate return;
23590Sstevel@tonic-gate }
23600Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_COMPLEX) {
23610Sstevel@tonic-gate do_complex_rctl_val(pp->pv_complex);
23620Sstevel@tonic-gate return;
23630Sstevel@tonic-gate }
23640Sstevel@tonic-gate for (l = pp->pv_list; l != NULL; l = l->lp_next)
23650Sstevel@tonic-gate do_complex_rctl_val(l->lp_complex);
23660Sstevel@tonic-gate return;
23670Sstevel@tonic-gate default:
23686215Sgjelinek zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
23696215Sgjelinek long_usage(CMD_ADD, B_TRUE);
23706215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
23710Sstevel@tonic-gate return;
23720Sstevel@tonic-gate }
23730Sstevel@tonic-gate }
23740Sstevel@tonic-gate
23753247Sgjelinek static boolean_t
gz_invalid_resource(int type)23763247Sgjelinek gz_invalid_resource(int type)
23773247Sgjelinek {
237812734Sgary.pennington@oracle.com return (global_zone && (type == RT_FS ||
23793247Sgjelinek type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
23803247Sgjelinek type == RT_DATASET));
23813247Sgjelinek }
23823247Sgjelinek
23833247Sgjelinek static boolean_t
gz_invalid_rt_property(int type)23843247Sgjelinek gz_invalid_rt_property(int type)
23853247Sgjelinek {
23863247Sgjelinek return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
23873247Sgjelinek type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
23883448Sdh155122 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
238912633Sjohn.levon@sun.com type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
23903247Sgjelinek }
23913247Sgjelinek
23923247Sgjelinek static boolean_t
gz_invalid_property(int type)23933247Sgjelinek gz_invalid_property(int type)
23943247Sgjelinek {
23953247Sgjelinek return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
23963247Sgjelinek type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
23973448Sdh155122 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
239812633Sjohn.levon@sun.com type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
23993247Sgjelinek }
24003247Sgjelinek
24010Sstevel@tonic-gate void
add_func(cmd_t * cmd)24020Sstevel@tonic-gate add_func(cmd_t *cmd)
24030Sstevel@tonic-gate {
24040Sstevel@tonic-gate int arg;
24056215Sgjelinek boolean_t arg_err = B_FALSE;
24060Sstevel@tonic-gate
24070Sstevel@tonic-gate assert(cmd != NULL);
24080Sstevel@tonic-gate
24090Sstevel@tonic-gate optind = 0;
24103691Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
24110Sstevel@tonic-gate switch (arg) {
24120Sstevel@tonic-gate case '?':
24130Sstevel@tonic-gate longer_usage(CMD_ADD);
24146215Sgjelinek arg_err = B_TRUE;
24153691Sgjelinek break;
24160Sstevel@tonic-gate default:
24170Sstevel@tonic-gate short_usage(CMD_ADD);
24186215Sgjelinek arg_err = B_TRUE;
24193691Sgjelinek break;
24203691Sgjelinek }
24213691Sgjelinek }
24223691Sgjelinek if (arg_err)
24233691Sgjelinek return;
24243691Sgjelinek
24250Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
24260Sstevel@tonic-gate short_usage(CMD_ADD);
24270Sstevel@tonic-gate return;
24280Sstevel@tonic-gate }
24290Sstevel@tonic-gate
24300Sstevel@tonic-gate if (zone_is_read_only(CMD_ADD))
24310Sstevel@tonic-gate return;
24320Sstevel@tonic-gate
24336215Sgjelinek if (initialize(B_TRUE) != Z_OK)
24340Sstevel@tonic-gate return;
24350Sstevel@tonic-gate if (global_scope) {
24363247Sgjelinek if (gz_invalid_resource(cmd->cmd_res_type)) {
24373247Sgjelinek zerr(gettext("Cannot add a %s resource to the "
24383247Sgjelinek "global zone."), rt_to_str(cmd->cmd_res_type));
24396215Sgjelinek saw_error = B_TRUE;
24403247Sgjelinek return;
24413247Sgjelinek }
24423247Sgjelinek
24436215Sgjelinek global_scope = B_FALSE;
24440Sstevel@tonic-gate resource_scope = cmd->cmd_res_type;
24450Sstevel@tonic-gate end_op = CMD_ADD;
24460Sstevel@tonic-gate add_resource(cmd);
24470Sstevel@tonic-gate } else
24480Sstevel@tonic-gate add_property(cmd);
24490Sstevel@tonic-gate }
24500Sstevel@tonic-gate
2451565Sdp /*
2452565Sdp * This routine has an unusual implementation, because it tries very
2453565Sdp * hard to succeed in the face of a variety of failure modes.
2454565Sdp * The most common and most vexing occurs when the index file and
2455565Sdp * the /etc/zones/<zonename.xml> file are not both present. In
2456565Sdp * this case, delete must eradicate as much of the zone state as is left
2457565Sdp * so that the user can later create a new zone with the same name.
2458565Sdp */
24590Sstevel@tonic-gate void
delete_func(cmd_t * cmd)24600Sstevel@tonic-gate delete_func(cmd_t *cmd)
24610Sstevel@tonic-gate {
24620Sstevel@tonic-gate int err, arg, answer;
24630Sstevel@tonic-gate char line[ZONENAME_MAX + 128]; /* enough to ask a question */
24646215Sgjelinek boolean_t force = B_FALSE;
24656215Sgjelinek boolean_t arg_err = B_FALSE;
24660Sstevel@tonic-gate
24670Sstevel@tonic-gate optind = 0;
24680Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
24690Sstevel@tonic-gate switch (arg) {
24700Sstevel@tonic-gate case '?':
24710Sstevel@tonic-gate longer_usage(CMD_DELETE);
24726215Sgjelinek arg_err = B_TRUE;
24733691Sgjelinek break;
24740Sstevel@tonic-gate case 'F':
24756215Sgjelinek force = B_TRUE;
24760Sstevel@tonic-gate break;
24770Sstevel@tonic-gate default:
24780Sstevel@tonic-gate short_usage(CMD_DELETE);
24796215Sgjelinek arg_err = B_TRUE;
24803691Sgjelinek break;
24813691Sgjelinek }
24823691Sgjelinek }
24833691Sgjelinek if (arg_err)
24843691Sgjelinek return;
24853691Sgjelinek
24860Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
24870Sstevel@tonic-gate short_usage(CMD_DELETE);
24880Sstevel@tonic-gate return;
24890Sstevel@tonic-gate }
24900Sstevel@tonic-gate
24910Sstevel@tonic-gate if (zone_is_read_only(CMD_DELETE))
24920Sstevel@tonic-gate return;
24930Sstevel@tonic-gate
24940Sstevel@tonic-gate if (!force) {
2495565Sdp /*
2496565Sdp * Initialize sets up the global called "handle" and warns the
2497565Sdp * user if the zone is not configured. In force mode, we don't
2498565Sdp * trust that evaluation, and hence skip it. (We don't need the
2499565Sdp * handle to be loaded anyway, since zonecfg_destroy is done by
250012578SGlenn.Faden@Sun.COM * zonename). However, we also have to take care to emulate the
2501565Sdp * messages spit out by initialize; see below.
2502565Sdp */
25036215Sgjelinek if (initialize(B_TRUE) != Z_OK)
2504565Sdp return;
2505565Sdp
25060Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
25070Sstevel@tonic-gate gettext("Are you sure you want to delete zone %s"), zone);
25086215Sgjelinek if ((answer = ask_yesno(B_FALSE, line)) == -1) {
2509565Sdp zerr(gettext("Input not from terminal and -F not "
2510565Sdp "specified:\n%s command ignored, exiting."),
2511565Sdp cmd_to_str(CMD_DELETE));
25120Sstevel@tonic-gate exit(Z_ERR);
25130Sstevel@tonic-gate }
25140Sstevel@tonic-gate if (answer != 1)
25150Sstevel@tonic-gate return;
25160Sstevel@tonic-gate }
25170Sstevel@tonic-gate
251812578SGlenn.Faden@Sun.COM /*
251912578SGlenn.Faden@Sun.COM * This function removes the authorizations from user_attr
252012578SGlenn.Faden@Sun.COM * that correspond to those specified in the configuration
252112578SGlenn.Faden@Sun.COM */
252212578SGlenn.Faden@Sun.COM if (initialize(B_TRUE) == Z_OK) {
252312578SGlenn.Faden@Sun.COM (void) zonecfg_deauthorize_users(handle, zone);
252412578SGlenn.Faden@Sun.COM }
2525565Sdp if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
2526565Sdp if ((err == Z_BAD_ZONE_STATE) && !force) {
2527565Sdp zerr(gettext("Zone %s not in %s state; %s not "
2528565Sdp "allowed. Use -F to force %s."),
2529565Sdp zone, zone_state_str(ZONE_STATE_CONFIGURED),
2530565Sdp cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
2531565Sdp } else {
25326215Sgjelinek zone_perror(zone, err, B_TRUE);
25336215Sgjelinek }
25346215Sgjelinek }
25356215Sgjelinek need_to_commit = B_FALSE;
2536565Sdp
2537565Sdp /*
2538565Sdp * Emulate initialize's messaging; if there wasn't a valid handle to
2539565Sdp * begin with, then user had typed delete (or delete -F) multiple
2540565Sdp * times. So we emit a message.
2541565Sdp *
2542565Sdp * We only do this in the 'force' case because normally, initialize()
2543565Sdp * takes care of this for us.
2544565Sdp */
2545565Sdp if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
2546565Sdp (void) printf(gettext("Use '%s' to begin "
2547565Sdp "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
25480Sstevel@tonic-gate
25490Sstevel@tonic-gate /*
25500Sstevel@tonic-gate * Time for a new handle: finish the old one off first
25510Sstevel@tonic-gate * then get a new one properly to avoid leaks.
25520Sstevel@tonic-gate */
2553565Sdp if (got_handle) {
2554565Sdp zonecfg_fini_handle(handle);
2555565Sdp if ((handle = zonecfg_init_handle()) == NULL) {
25566215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
2557565Sdp exit(Z_ERR);
2558565Sdp }
2559565Sdp if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
2560565Sdp /* If there was no zone before, that's OK */
2561565Sdp if (err != Z_NO_ZONE)
25626215Sgjelinek zone_perror(zone, err, B_TRUE);
25636215Sgjelinek got_handle = B_FALSE;
2564565Sdp }
25650Sstevel@tonic-gate }
25660Sstevel@tonic-gate }
25670Sstevel@tonic-gate
25680Sstevel@tonic-gate static int
fill_in_fstab(cmd_t * cmd,struct zone_fstab * fstab,boolean_t fill_in_only)25696215Sgjelinek fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only)
25700Sstevel@tonic-gate {
25710Sstevel@tonic-gate int err, i;
25720Sstevel@tonic-gate property_value_ptr_t pp;
25730Sstevel@tonic-gate
25746215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
25750Sstevel@tonic-gate return (err);
25760Sstevel@tonic-gate
25771086Svp157776 bzero(fstab, sizeof (*fstab));
25780Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
25790Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i];
25800Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
25810Sstevel@tonic-gate zerr(gettext("A simple value was expected here."));
25826215Sgjelinek saw_error = B_TRUE;
25830Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
25840Sstevel@tonic-gate }
25850Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) {
25860Sstevel@tonic-gate case PT_DIR:
25870Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
25880Sstevel@tonic-gate sizeof (fstab->zone_fs_dir));
25890Sstevel@tonic-gate break;
25900Sstevel@tonic-gate case PT_SPECIAL:
25910Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
25920Sstevel@tonic-gate sizeof (fstab->zone_fs_special));
25930Sstevel@tonic-gate break;
25940Sstevel@tonic-gate case PT_RAW:
25950Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
25960Sstevel@tonic-gate sizeof (fstab->zone_fs_raw));
25970Sstevel@tonic-gate break;
25980Sstevel@tonic-gate case PT_TYPE:
25990Sstevel@tonic-gate (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
26000Sstevel@tonic-gate sizeof (fstab->zone_fs_type));
26010Sstevel@tonic-gate break;
26020Sstevel@tonic-gate default:
26030Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26046215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
26050Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
26060Sstevel@tonic-gate }
26070Sstevel@tonic-gate }
26080Sstevel@tonic-gate if (fill_in_only)
26090Sstevel@tonic-gate return (Z_OK);
26100Sstevel@tonic-gate return (zonecfg_lookup_filesystem(handle, fstab));
26110Sstevel@tonic-gate }
26120Sstevel@tonic-gate
26130Sstevel@tonic-gate static int
fill_in_nwiftab(cmd_t * cmd,struct zone_nwiftab * nwiftab,boolean_t fill_in_only)26146215Sgjelinek fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
26156215Sgjelinek boolean_t fill_in_only)
26160Sstevel@tonic-gate {
26170Sstevel@tonic-gate int err, i;
26180Sstevel@tonic-gate property_value_ptr_t pp;
26190Sstevel@tonic-gate
26206215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
26210Sstevel@tonic-gate return (err);
26220Sstevel@tonic-gate
26231086Svp157776 bzero(nwiftab, sizeof (*nwiftab));
26240Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
26250Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i];
26260Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
26270Sstevel@tonic-gate zerr(gettext("A simple value was expected here."));
26286215Sgjelinek saw_error = B_TRUE;
26290Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
26300Sstevel@tonic-gate }
26310Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) {
26320Sstevel@tonic-gate case PT_ADDRESS:
26330Sstevel@tonic-gate (void) strlcpy(nwiftab->zone_nwif_address,
26340Sstevel@tonic-gate pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
26350Sstevel@tonic-gate break;
263612748SSowmini.Varadhan@oracle.COM case PT_ALLOWED_ADDRESS:
263712748SSowmini.Varadhan@oracle.COM (void) strlcpy(nwiftab->zone_nwif_allowed_address,
263812748SSowmini.Varadhan@oracle.COM pp->pv_simple,
263912748SSowmini.Varadhan@oracle.COM sizeof (nwiftab->zone_nwif_allowed_address));
264012748SSowmini.Varadhan@oracle.COM break;
26410Sstevel@tonic-gate case PT_PHYSICAL:
26420Sstevel@tonic-gate (void) strlcpy(nwiftab->zone_nwif_physical,
26430Sstevel@tonic-gate pp->pv_simple,
26440Sstevel@tonic-gate sizeof (nwiftab->zone_nwif_physical));
26450Sstevel@tonic-gate break;
26466076Sgfaden case PT_DEFROUTER:
26476076Sgfaden (void) strlcpy(nwiftab->zone_nwif_defrouter,
26486076Sgfaden pp->pv_simple,
26496076Sgfaden sizeof (nwiftab->zone_nwif_defrouter));
26506076Sgfaden break;
26510Sstevel@tonic-gate default:
26520Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26536215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
26540Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
26550Sstevel@tonic-gate }
26560Sstevel@tonic-gate }
26570Sstevel@tonic-gate if (fill_in_only)
26580Sstevel@tonic-gate return (Z_OK);
26590Sstevel@tonic-gate err = zonecfg_lookup_nwif(handle, nwiftab);
26600Sstevel@tonic-gate return (err);
26610Sstevel@tonic-gate }
26620Sstevel@tonic-gate
26630Sstevel@tonic-gate static int
fill_in_devtab(cmd_t * cmd,struct zone_devtab * devtab,boolean_t fill_in_only)26646215Sgjelinek fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
26650Sstevel@tonic-gate {
26660Sstevel@tonic-gate int err, i;
26670Sstevel@tonic-gate property_value_ptr_t pp;
26680Sstevel@tonic-gate
26696215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
26700Sstevel@tonic-gate return (err);
26710Sstevel@tonic-gate
26721086Svp157776 bzero(devtab, sizeof (*devtab));
26730Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
26740Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i];
26750Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
26760Sstevel@tonic-gate zerr(gettext("A simple value was expected here."));
26776215Sgjelinek saw_error = B_TRUE;
26780Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
26790Sstevel@tonic-gate }
26800Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) {
26810Sstevel@tonic-gate case PT_MATCH:
26820Sstevel@tonic-gate (void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
26830Sstevel@tonic-gate sizeof (devtab->zone_dev_match));
26840Sstevel@tonic-gate break;
26850Sstevel@tonic-gate default:
26860Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
26876215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
26880Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
26890Sstevel@tonic-gate }
26900Sstevel@tonic-gate }
26910Sstevel@tonic-gate if (fill_in_only)
26920Sstevel@tonic-gate return (Z_OK);
26930Sstevel@tonic-gate err = zonecfg_lookup_dev(handle, devtab);
26940Sstevel@tonic-gate return (err);
26950Sstevel@tonic-gate }
26960Sstevel@tonic-gate
26970Sstevel@tonic-gate static int
fill_in_rctltab(cmd_t * cmd,struct zone_rctltab * rctltab,boolean_t fill_in_only)26986215Sgjelinek fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab,
26996215Sgjelinek boolean_t fill_in_only)
27000Sstevel@tonic-gate {
27010Sstevel@tonic-gate int err, i;
27020Sstevel@tonic-gate property_value_ptr_t pp;
27030Sstevel@tonic-gate
27046215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
27050Sstevel@tonic-gate return (err);
27060Sstevel@tonic-gate
27071086Svp157776 bzero(rctltab, sizeof (*rctltab));
27080Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
27090Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i];
27100Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
27110Sstevel@tonic-gate zerr(gettext("A simple value was expected here."));
27126215Sgjelinek saw_error = B_TRUE;
27130Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
27140Sstevel@tonic-gate }
27150Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) {
27160Sstevel@tonic-gate case PT_NAME:
27170Sstevel@tonic-gate (void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
27180Sstevel@tonic-gate sizeof (rctltab->zone_rctl_name));
27190Sstevel@tonic-gate break;
27200Sstevel@tonic-gate default:
27210Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27226215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
27230Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
27240Sstevel@tonic-gate }
27250Sstevel@tonic-gate }
27260Sstevel@tonic-gate if (fill_in_only)
27270Sstevel@tonic-gate return (Z_OK);
27280Sstevel@tonic-gate err = zonecfg_lookup_rctl(handle, rctltab);
27290Sstevel@tonic-gate return (err);
27300Sstevel@tonic-gate }
27310Sstevel@tonic-gate
27320Sstevel@tonic-gate static int
fill_in_attrtab(cmd_t * cmd,struct zone_attrtab * attrtab,boolean_t fill_in_only)27336215Sgjelinek fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab,
27346215Sgjelinek boolean_t fill_in_only)
27350Sstevel@tonic-gate {
27360Sstevel@tonic-gate int err, i;
27370Sstevel@tonic-gate property_value_ptr_t pp;
27380Sstevel@tonic-gate
27396215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
27400Sstevel@tonic-gate return (err);
27410Sstevel@tonic-gate
27421086Svp157776 bzero(attrtab, sizeof (*attrtab));
27430Sstevel@tonic-gate for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
27440Sstevel@tonic-gate pp = cmd->cmd_property_ptr[i];
27450Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
27460Sstevel@tonic-gate zerr(gettext("A simple value was expected here."));
27476215Sgjelinek saw_error = B_TRUE;
27480Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
27490Sstevel@tonic-gate }
27500Sstevel@tonic-gate switch (cmd->cmd_prop_name[i]) {
27510Sstevel@tonic-gate case PT_NAME:
27520Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
27530Sstevel@tonic-gate sizeof (attrtab->zone_attr_name));
27540Sstevel@tonic-gate break;
27550Sstevel@tonic-gate case PT_TYPE:
27560Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
27570Sstevel@tonic-gate sizeof (attrtab->zone_attr_type));
27580Sstevel@tonic-gate break;
27590Sstevel@tonic-gate case PT_VALUE:
27600Sstevel@tonic-gate (void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
27610Sstevel@tonic-gate sizeof (attrtab->zone_attr_value));
27620Sstevel@tonic-gate break;
27630Sstevel@tonic-gate default:
27640Sstevel@tonic-gate zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27656215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
27660Sstevel@tonic-gate return (Z_INSUFFICIENT_SPEC);
27670Sstevel@tonic-gate }
27680Sstevel@tonic-gate }
27690Sstevel@tonic-gate if (fill_in_only)
27700Sstevel@tonic-gate return (Z_OK);
27710Sstevel@tonic-gate err = zonecfg_lookup_attr(handle, attrtab);
27720Sstevel@tonic-gate return (err);
27730Sstevel@tonic-gate }
27740Sstevel@tonic-gate
2775789Sahrens static int
fill_in_dstab(cmd_t * cmd,struct zone_dstab * dstab,boolean_t fill_in_only)27766215Sgjelinek fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
2777789Sahrens {
2778789Sahrens int err, i;
2779789Sahrens property_value_ptr_t pp;
2780789Sahrens
27816215Sgjelinek if ((err = initialize(B_TRUE)) != Z_OK)
2782789Sahrens return (err);
2783789Sahrens
2784789Sahrens dstab->zone_dataset_name[0] = '\0';
2785789Sahrens for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2786789Sahrens pp = cmd->cmd_property_ptr[i];
2787789Sahrens if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2788789Sahrens zerr(gettext("A simple value was expected here."));
27896215Sgjelinek saw_error = B_TRUE;
2790789Sahrens return (Z_INSUFFICIENT_SPEC);
2791789Sahrens }
2792789Sahrens switch (cmd->cmd_prop_name[i]) {
2793789Sahrens case PT_NAME:
2794789Sahrens (void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
2795789Sahrens sizeof (dstab->zone_dataset_name));
2796789Sahrens break;
2797789Sahrens default:
2798789Sahrens zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
27996215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
2800789Sahrens return (Z_INSUFFICIENT_SPEC);
2801789Sahrens }
2802789Sahrens }
2803789Sahrens if (fill_in_only)
2804789Sahrens return (Z_OK);
2805789Sahrens return (zonecfg_lookup_ds(handle, dstab));
2806789Sahrens }
2807789Sahrens
280812578SGlenn.Faden@Sun.COM static int
fill_in_admintab(cmd_t * cmd,struct zone_admintab * admintab,boolean_t fill_in_only)280912578SGlenn.Faden@Sun.COM fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
281012578SGlenn.Faden@Sun.COM boolean_t fill_in_only)
281112578SGlenn.Faden@Sun.COM {
281212578SGlenn.Faden@Sun.COM int err, i;
281312578SGlenn.Faden@Sun.COM property_value_ptr_t pp;
281412578SGlenn.Faden@Sun.COM
281512578SGlenn.Faden@Sun.COM if ((err = initialize(B_TRUE)) != Z_OK)
281612578SGlenn.Faden@Sun.COM return (err);
281712578SGlenn.Faden@Sun.COM
281812578SGlenn.Faden@Sun.COM bzero(admintab, sizeof (*admintab));
281912578SGlenn.Faden@Sun.COM for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
282012578SGlenn.Faden@Sun.COM pp = cmd->cmd_property_ptr[i];
282112578SGlenn.Faden@Sun.COM if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
282212578SGlenn.Faden@Sun.COM zerr(gettext("A simple value was expected here."));
282312578SGlenn.Faden@Sun.COM saw_error = B_TRUE;
282412578SGlenn.Faden@Sun.COM return (Z_INSUFFICIENT_SPEC);
282512578SGlenn.Faden@Sun.COM }
282612578SGlenn.Faden@Sun.COM switch (cmd->cmd_prop_name[i]) {
282712578SGlenn.Faden@Sun.COM case PT_USER:
282812578SGlenn.Faden@Sun.COM (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
282912578SGlenn.Faden@Sun.COM sizeof (admintab->zone_admin_user));
283012578SGlenn.Faden@Sun.COM break;
283112578SGlenn.Faden@Sun.COM case PT_AUTHS:
283212578SGlenn.Faden@Sun.COM (void) strlcpy(admintab->zone_admin_auths,
283312578SGlenn.Faden@Sun.COM pp->pv_simple, sizeof (admintab->zone_admin_auths));
283412578SGlenn.Faden@Sun.COM break;
283512578SGlenn.Faden@Sun.COM default:
283612578SGlenn.Faden@Sun.COM zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
283712578SGlenn.Faden@Sun.COM Z_NO_PROPERTY_TYPE, B_TRUE);
283812578SGlenn.Faden@Sun.COM return (Z_INSUFFICIENT_SPEC);
283912578SGlenn.Faden@Sun.COM }
284012578SGlenn.Faden@Sun.COM }
284112578SGlenn.Faden@Sun.COM if (fill_in_only)
284212578SGlenn.Faden@Sun.COM return (Z_OK);
284312578SGlenn.Faden@Sun.COM err = zonecfg_lookup_admin(handle, admintab);
284412578SGlenn.Faden@Sun.COM return (err);
284512578SGlenn.Faden@Sun.COM }
284612578SGlenn.Faden@Sun.COM
28470Sstevel@tonic-gate static void
remove_aliased_rctl(int type,char * name)28483247Sgjelinek remove_aliased_rctl(int type, char *name)
28493247Sgjelinek {
28503247Sgjelinek int err;
28513247Sgjelinek uint64_t tmp;
28523247Sgjelinek
28533247Sgjelinek if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
28543247Sgjelinek zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
28553247Sgjelinek zonecfg_strerror(err));
28566215Sgjelinek saw_error = B_TRUE;
28573247Sgjelinek return;
28583247Sgjelinek }
28593247Sgjelinek if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
28603247Sgjelinek zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
28613247Sgjelinek zonecfg_strerror(err));
28626215Sgjelinek saw_error = B_TRUE;
28633247Sgjelinek } else {
28646215Sgjelinek need_to_commit = B_TRUE;
28653247Sgjelinek }
28663247Sgjelinek }
28673247Sgjelinek
28683247Sgjelinek static boolean_t
prompt_remove_resource(cmd_t * cmd,char * rsrc)28693247Sgjelinek prompt_remove_resource(cmd_t *cmd, char *rsrc)
28700Sstevel@tonic-gate {
28713247Sgjelinek int num;
28723247Sgjelinek int answer;
28733247Sgjelinek int arg;
28743247Sgjelinek boolean_t force = B_FALSE;
28753247Sgjelinek char prompt[128];
28766215Sgjelinek boolean_t arg_err = B_FALSE;
28773247Sgjelinek
28783247Sgjelinek optind = 0;
28793247Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
28803247Sgjelinek switch (arg) {
28813247Sgjelinek case 'F':
28823247Sgjelinek force = B_TRUE;
28833247Sgjelinek break;
28843247Sgjelinek default:
28856215Sgjelinek arg_err = B_TRUE;
28863691Sgjelinek break;
28873691Sgjelinek }
28883691Sgjelinek }
28893691Sgjelinek if (arg_err)
28903691Sgjelinek return (B_FALSE);
28913691Sgjelinek
28923247Sgjelinek
28933247Sgjelinek num = zonecfg_num_resources(handle, rsrc);
28943247Sgjelinek
28953247Sgjelinek if (num == 0) {
28963247Sgjelinek z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
28976215Sgjelinek B_TRUE);
28983247Sgjelinek return (B_FALSE);
28993247Sgjelinek }
29003247Sgjelinek if (num > 1 && !force) {
29013247Sgjelinek if (!interactive_mode) {
29023247Sgjelinek zerr(gettext("There are multiple instances of this "
29033247Sgjelinek "resource. Either qualify the resource to\n"
29043247Sgjelinek "remove a single instance or use the -F option to "
29053247Sgjelinek "remove all instances."));
29066215Sgjelinek saw_error = B_TRUE;
29073247Sgjelinek return (B_FALSE);
29083247Sgjelinek }
29093247Sgjelinek (void) snprintf(prompt, sizeof (prompt), gettext(
29103247Sgjelinek "Are you sure you want to remove ALL '%s' resources"),
29113247Sgjelinek rsrc);
29126215Sgjelinek answer = ask_yesno(B_FALSE, prompt);
29133247Sgjelinek if (answer == -1) {
29143247Sgjelinek zerr(gettext("Resource incomplete."));
29153247Sgjelinek return (B_FALSE);
29163247Sgjelinek }
29173247Sgjelinek if (answer != 1)
29183247Sgjelinek return (B_FALSE);
29193247Sgjelinek }
29203247Sgjelinek return (B_TRUE);
29213247Sgjelinek }
29223247Sgjelinek
29233247Sgjelinek static void
remove_fs(cmd_t * cmd)29243247Sgjelinek remove_fs(cmd_t *cmd)
29253247Sgjelinek {
29263247Sgjelinek int err;
29273247Sgjelinek
29283247Sgjelinek /* traditional, qualified fs removal */
29293247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
29303247Sgjelinek struct zone_fstab fstab;
29313247Sgjelinek
29326215Sgjelinek if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
29336215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29340Sstevel@tonic-gate return;
29350Sstevel@tonic-gate }
29360Sstevel@tonic-gate if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
29376215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29380Sstevel@tonic-gate else
29396215Sgjelinek need_to_commit = B_TRUE;
29400Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options);
29410Sstevel@tonic-gate return;
29423247Sgjelinek }
29433247Sgjelinek
29443247Sgjelinek /*
29453247Sgjelinek * unqualified fs removal. remove all fs's but prompt if more
29463247Sgjelinek * than one.
29473247Sgjelinek */
29483247Sgjelinek if (!prompt_remove_resource(cmd, "fs"))
29493247Sgjelinek return;
29503247Sgjelinek
29513247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
29526215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
29533247Sgjelinek else
29546215Sgjelinek need_to_commit = B_TRUE;
29553247Sgjelinek }
29563247Sgjelinek
29573247Sgjelinek static void
remove_net(cmd_t * cmd)29583247Sgjelinek remove_net(cmd_t *cmd)
29593247Sgjelinek {
29603247Sgjelinek int err;
29613247Sgjelinek
29623247Sgjelinek /* traditional, qualified net removal */
29633247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
29643247Sgjelinek struct zone_nwiftab nwiftab;
29653247Sgjelinek
29666215Sgjelinek if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
29676215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29680Sstevel@tonic-gate return;
29690Sstevel@tonic-gate }
29700Sstevel@tonic-gate if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
29716215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29720Sstevel@tonic-gate else
29736215Sgjelinek need_to_commit = B_TRUE;
29740Sstevel@tonic-gate return;
29753247Sgjelinek }
29763247Sgjelinek
29773247Sgjelinek /*
29783247Sgjelinek * unqualified net removal. remove all nets but prompt if more
29793247Sgjelinek * than one.
29803247Sgjelinek */
29813247Sgjelinek if (!prompt_remove_resource(cmd, "net"))
29823247Sgjelinek return;
29833247Sgjelinek
29843247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
29856215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
29863247Sgjelinek else
29876215Sgjelinek need_to_commit = B_TRUE;
29883247Sgjelinek }
29893247Sgjelinek
29903247Sgjelinek static void
remove_device(cmd_t * cmd)29913247Sgjelinek remove_device(cmd_t *cmd)
29923247Sgjelinek {
29933247Sgjelinek int err;
29943247Sgjelinek
29953247Sgjelinek /* traditional, qualified device removal */
29963247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
29973247Sgjelinek struct zone_devtab devtab;
29983247Sgjelinek
29996215Sgjelinek if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
30006215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30010Sstevel@tonic-gate return;
30020Sstevel@tonic-gate }
30030Sstevel@tonic-gate if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
30046215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30050Sstevel@tonic-gate else
30066215Sgjelinek need_to_commit = B_TRUE;
30070Sstevel@tonic-gate return;
30083247Sgjelinek }
30093247Sgjelinek
30103247Sgjelinek /*
30113247Sgjelinek * unqualified device removal. remove all devices but prompt if more
30123247Sgjelinek * than one.
30133247Sgjelinek */
30143247Sgjelinek if (!prompt_remove_resource(cmd, "device"))
30153247Sgjelinek return;
30163247Sgjelinek
30173247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
30186215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
30193247Sgjelinek else
30206215Sgjelinek need_to_commit = B_TRUE;
30213247Sgjelinek }
30223247Sgjelinek
30233247Sgjelinek static void
remove_attr(cmd_t * cmd)30243247Sgjelinek remove_attr(cmd_t *cmd)
30253247Sgjelinek {
30263247Sgjelinek int err;
30273247Sgjelinek
30283247Sgjelinek /* traditional, qualified attr removal */
30293247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
30303247Sgjelinek struct zone_attrtab attrtab;
30313247Sgjelinek
30326215Sgjelinek if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
30336215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30343247Sgjelinek return;
30353247Sgjelinek }
30363247Sgjelinek if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
30376215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30383247Sgjelinek else
30396215Sgjelinek need_to_commit = B_TRUE;
30403247Sgjelinek return;
30413247Sgjelinek }
30423247Sgjelinek
30433247Sgjelinek /*
30443247Sgjelinek * unqualified attr removal. remove all attrs but prompt if more
30453247Sgjelinek * than one.
30463247Sgjelinek */
30473247Sgjelinek if (!prompt_remove_resource(cmd, "attr"))
30483247Sgjelinek return;
30493247Sgjelinek
30503247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
30516215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
30523247Sgjelinek else
30536215Sgjelinek need_to_commit = B_TRUE;
30543247Sgjelinek }
30553247Sgjelinek
30563247Sgjelinek static void
remove_dataset(cmd_t * cmd)30573247Sgjelinek remove_dataset(cmd_t *cmd)
30583247Sgjelinek {
30593247Sgjelinek int err;
30603247Sgjelinek
30613247Sgjelinek /* traditional, qualified dataset removal */
30623247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
30633247Sgjelinek struct zone_dstab dstab;
30643247Sgjelinek
30656215Sgjelinek if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
30666215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30673247Sgjelinek return;
30683247Sgjelinek }
30693247Sgjelinek if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
30706215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30713247Sgjelinek else
30726215Sgjelinek need_to_commit = B_TRUE;
30733247Sgjelinek return;
30743247Sgjelinek }
30753247Sgjelinek
30763247Sgjelinek /*
30773247Sgjelinek * unqualified dataset removal. remove all datasets but prompt if more
30783247Sgjelinek * than one.
30793247Sgjelinek */
30803247Sgjelinek if (!prompt_remove_resource(cmd, "dataset"))
30813247Sgjelinek return;
30823247Sgjelinek
30833247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
30846215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
30853247Sgjelinek else
30866215Sgjelinek need_to_commit = B_TRUE;
30873247Sgjelinek }
30883247Sgjelinek
30893247Sgjelinek static void
remove_rctl(cmd_t * cmd)30903247Sgjelinek remove_rctl(cmd_t *cmd)
30913247Sgjelinek {
30923247Sgjelinek int err;
30933247Sgjelinek
30943247Sgjelinek /* traditional, qualified rctl removal */
30953247Sgjelinek if (cmd->cmd_prop_nv_pairs > 0) {
30963247Sgjelinek struct zone_rctltab rctltab;
30973247Sgjelinek
30986215Sgjelinek if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
30996215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31000Sstevel@tonic-gate return;
31010Sstevel@tonic-gate }
31020Sstevel@tonic-gate if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
31036215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31040Sstevel@tonic-gate else
31056215Sgjelinek need_to_commit = B_TRUE;
31060Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
31070Sstevel@tonic-gate return;
31083247Sgjelinek }
31093247Sgjelinek
31103247Sgjelinek /*
31113247Sgjelinek * unqualified rctl removal. remove all rctls but prompt if more
31123247Sgjelinek * than one.
31133247Sgjelinek */
31143247Sgjelinek if (!prompt_remove_resource(cmd, "rctl"))
31153247Sgjelinek return;
31163247Sgjelinek
31173247Sgjelinek if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
31186215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
31193247Sgjelinek else
31206215Sgjelinek need_to_commit = B_TRUE;
31213247Sgjelinek }
31223247Sgjelinek
31233247Sgjelinek static void
remove_pset()31243247Sgjelinek remove_pset()
31253247Sgjelinek {
31263247Sgjelinek int err;
31273247Sgjelinek struct zone_psettab psettab;
31283247Sgjelinek
31293247Sgjelinek if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
31306215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
31313247Sgjelinek return;
31323247Sgjelinek }
31333247Sgjelinek if ((err = zonecfg_delete_pset(handle)) != Z_OK)
31346215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
31353247Sgjelinek else
31366215Sgjelinek need_to_commit = B_TRUE;
31373247Sgjelinek }
31383247Sgjelinek
31393247Sgjelinek static void
remove_pcap()31403792Sakolb remove_pcap()
31413792Sakolb {
31423792Sakolb int err;
31433792Sakolb uint64_t tmp;
31443792Sakolb
31453792Sakolb if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
31463792Sakolb zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
31473792Sakolb zonecfg_strerror(Z_NO_RESOURCE_TYPE));
31486215Sgjelinek saw_error = B_TRUE;
31493792Sakolb return;
31503792Sakolb }
31513792Sakolb
31523792Sakolb if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
31536215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
31543792Sakolb else
31556215Sgjelinek need_to_commit = B_TRUE;
31563792Sakolb }
31573792Sakolb
31583792Sakolb static void
remove_mcap()31593247Sgjelinek remove_mcap()
31603247Sgjelinek {
31613247Sgjelinek int err, res1, res2, res3;
31623247Sgjelinek uint64_t tmp;
31633247Sgjelinek struct zone_mcaptab mcaptab;
31643247Sgjelinek boolean_t revert = B_FALSE;
31653247Sgjelinek
31663247Sgjelinek res1 = zonecfg_lookup_mcap(handle, &mcaptab);
31673247Sgjelinek res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
31683247Sgjelinek res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
31693247Sgjelinek
31703247Sgjelinek /* if none of these exist, there is no resource to remove */
31713247Sgjelinek if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
31723247Sgjelinek zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
31733247Sgjelinek zonecfg_strerror(Z_NO_RESOURCE_TYPE));
31746215Sgjelinek saw_error = B_TRUE;
31753247Sgjelinek return;
31763247Sgjelinek }
31773247Sgjelinek if (res1 == Z_OK) {
31783247Sgjelinek if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
31796215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31803247Sgjelinek revert = B_TRUE;
31813247Sgjelinek } else {
31826215Sgjelinek need_to_commit = B_TRUE;
31833247Sgjelinek }
31843247Sgjelinek }
31853247Sgjelinek if (res2 == Z_OK) {
31863247Sgjelinek if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
31873247Sgjelinek != Z_OK) {
31886215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31893247Sgjelinek revert = B_TRUE;
31903247Sgjelinek } else {
31916215Sgjelinek need_to_commit = B_TRUE;
31923247Sgjelinek }
31933247Sgjelinek }
31943247Sgjelinek if (res3 == Z_OK) {
31953247Sgjelinek if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
31963247Sgjelinek != Z_OK) {
31976215Sgjelinek z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
31983247Sgjelinek revert = B_TRUE;
31993247Sgjelinek } else {
32006215Sgjelinek need_to_commit = B_TRUE;
32013247Sgjelinek }
32023247Sgjelinek }
32033247Sgjelinek
32043247Sgjelinek if (revert)
32056215Sgjelinek need_to_commit = B_FALSE;
32063247Sgjelinek }
32073247Sgjelinek
32083247Sgjelinek static void
remove_admin(cmd_t * cmd)320912578SGlenn.Faden@Sun.COM remove_admin(cmd_t *cmd)
321012578SGlenn.Faden@Sun.COM {
321112578SGlenn.Faden@Sun.COM int err;
321212578SGlenn.Faden@Sun.COM
321312578SGlenn.Faden@Sun.COM /* traditional, qualified attr removal */
321412578SGlenn.Faden@Sun.COM if (cmd->cmd_prop_nv_pairs > 0) {
321512578SGlenn.Faden@Sun.COM struct zone_admintab admintab;
321612578SGlenn.Faden@Sun.COM
321712578SGlenn.Faden@Sun.COM if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
321812578SGlenn.Faden@Sun.COM z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
321912578SGlenn.Faden@Sun.COM err, B_TRUE);
322012578SGlenn.Faden@Sun.COM return;
322112578SGlenn.Faden@Sun.COM }
322212578SGlenn.Faden@Sun.COM if ((err = zonecfg_delete_admin(handle, &admintab,
322312578SGlenn.Faden@Sun.COM zone))
322412578SGlenn.Faden@Sun.COM != Z_OK)
322512578SGlenn.Faden@Sun.COM z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
322612578SGlenn.Faden@Sun.COM err, B_TRUE);
322712578SGlenn.Faden@Sun.COM else
322812578SGlenn.Faden@Sun.COM need_to_commit = B_TRUE;
322912578SGlenn.Faden@Sun.COM return;
323012578SGlenn.Faden@Sun.COM } else {
323112578SGlenn.Faden@Sun.COM /*
323212578SGlenn.Faden@Sun.COM * unqualified admin removal.
323312578SGlenn.Faden@Sun.COM * remove all admins but prompt if more
323412578SGlenn.Faden@Sun.COM * than one.
323512578SGlenn.Faden@Sun.COM */
323612578SGlenn.Faden@Sun.COM if (!prompt_remove_resource(cmd, "admin"))
323712578SGlenn.Faden@Sun.COM return;
323812578SGlenn.Faden@Sun.COM
323912578SGlenn.Faden@Sun.COM if ((err = zonecfg_delete_admins(handle, zone))
324012578SGlenn.Faden@Sun.COM != Z_OK)
324112578SGlenn.Faden@Sun.COM z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
324212578SGlenn.Faden@Sun.COM err, B_TRUE);
324312578SGlenn.Faden@Sun.COM else
324412578SGlenn.Faden@Sun.COM need_to_commit = B_TRUE;
324512578SGlenn.Faden@Sun.COM }
324612578SGlenn.Faden@Sun.COM }
324712578SGlenn.Faden@Sun.COM
324812578SGlenn.Faden@Sun.COM static void
remove_resource(cmd_t * cmd)32493247Sgjelinek remove_resource(cmd_t *cmd)
32503247Sgjelinek {
32513247Sgjelinek int type;
32523247Sgjelinek int arg;
32536215Sgjelinek boolean_t arg_err = B_FALSE;
32543247Sgjelinek
32553247Sgjelinek if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
32566215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
32573247Sgjelinek return;
32583247Sgjelinek }
32593247Sgjelinek
32603247Sgjelinek optind = 0;
32613247Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
32623247Sgjelinek switch (arg) {
32633247Sgjelinek case '?':
32643247Sgjelinek longer_usage(CMD_REMOVE);
32656215Sgjelinek arg_err = B_TRUE;
32663691Sgjelinek break;
32673247Sgjelinek case 'F':
32683247Sgjelinek break;
32693247Sgjelinek default:
32703247Sgjelinek short_usage(CMD_REMOVE);
32716215Sgjelinek arg_err = B_TRUE;
32723691Sgjelinek break;
32733691Sgjelinek }
32743691Sgjelinek }
32753691Sgjelinek if (arg_err)
32763691Sgjelinek return;
32773247Sgjelinek
32786215Sgjelinek if (initialize(B_TRUE) != Z_OK)
32793247Sgjelinek return;
32803247Sgjelinek
32813247Sgjelinek switch (type) {
32823247Sgjelinek case RT_FS:
32833247Sgjelinek remove_fs(cmd);
32843247Sgjelinek return;
32853247Sgjelinek case RT_NET:
32863247Sgjelinek remove_net(cmd);
32873247Sgjelinek return;
32883247Sgjelinek case RT_DEVICE:
32893247Sgjelinek remove_device(cmd);
32903247Sgjelinek return;
32913247Sgjelinek case RT_RCTL:
32923247Sgjelinek remove_rctl(cmd);
32933247Sgjelinek return;
32943247Sgjelinek case RT_ATTR:
32953247Sgjelinek remove_attr(cmd);
32960Sstevel@tonic-gate return;
3297789Sahrens case RT_DATASET:
32983247Sgjelinek remove_dataset(cmd);
32993247Sgjelinek return;
33003247Sgjelinek case RT_DCPU:
33013247Sgjelinek remove_pset();
33023247Sgjelinek return;
33033792Sakolb case RT_PCAP:
33043792Sakolb remove_pcap();
33053792Sakolb return;
33063247Sgjelinek case RT_MCAP:
33073247Sgjelinek remove_mcap();
3308789Sahrens return;
330912578SGlenn.Faden@Sun.COM case RT_ADMIN:
331012578SGlenn.Faden@Sun.COM remove_admin(cmd);
331112578SGlenn.Faden@Sun.COM return;
33120Sstevel@tonic-gate default:
33136215Sgjelinek zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
33146215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
33156215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
33160Sstevel@tonic-gate return;
33170Sstevel@tonic-gate }
33180Sstevel@tonic-gate }
33190Sstevel@tonic-gate
33200Sstevel@tonic-gate static void
remove_property(cmd_t * cmd)33210Sstevel@tonic-gate remove_property(cmd_t *cmd)
33220Sstevel@tonic-gate {
33230Sstevel@tonic-gate char *prop_id;
33240Sstevel@tonic-gate int err, res_type, prop_type;
33250Sstevel@tonic-gate property_value_ptr_t pp;
33260Sstevel@tonic-gate struct zone_rctlvaltab *rctlvaltab;
33270Sstevel@tonic-gate complex_property_ptr_t cx;
33280Sstevel@tonic-gate
33290Sstevel@tonic-gate res_type = resource_scope;
33300Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0];
33310Sstevel@tonic-gate if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
33326215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
33330Sstevel@tonic-gate return;
33340Sstevel@tonic-gate }
33350Sstevel@tonic-gate
33360Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs != 1) {
33376215Sgjelinek long_usage(CMD_ADD, B_TRUE);
33386215Sgjelinek return;
33396215Sgjelinek }
33406215Sgjelinek
33416215Sgjelinek if (initialize(B_TRUE) != Z_OK)
33420Sstevel@tonic-gate return;
33430Sstevel@tonic-gate
33440Sstevel@tonic-gate switch (res_type) {
33450Sstevel@tonic-gate case RT_FS:
33460Sstevel@tonic-gate if (prop_type != PT_OPTIONS) {
33470Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
33486215Sgjelinek B_TRUE);
33496215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
33506215Sgjelinek usage(B_FALSE, HELP_PROPS);
33510Sstevel@tonic-gate return;
33520Sstevel@tonic-gate }
33530Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0];
33540Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_COMPLEX) {
33550Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected here."),
33560Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE),
33570Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST));
33586215Sgjelinek saw_error = B_TRUE;
33590Sstevel@tonic-gate return;
33600Sstevel@tonic-gate }
33610Sstevel@tonic-gate if (pp->pv_type == PROP_VAL_SIMPLE) {
33620Sstevel@tonic-gate if (pp->pv_simple == NULL) {
33636215Sgjelinek long_usage(CMD_ADD, B_TRUE);
33640Sstevel@tonic-gate return;
33650Sstevel@tonic-gate }
33660Sstevel@tonic-gate prop_id = pp->pv_simple;
33670Sstevel@tonic-gate err = zonecfg_remove_fs_option(&in_progress_fstab,
33680Sstevel@tonic-gate prop_id);
33690Sstevel@tonic-gate if (err != Z_OK)
33706215Sgjelinek zone_perror(pt_to_str(prop_type), err, B_TRUE);
33710Sstevel@tonic-gate } else {
33720Sstevel@tonic-gate list_property_ptr_t list;
33730Sstevel@tonic-gate
33740Sstevel@tonic-gate for (list = pp->pv_list; list != NULL;
33750Sstevel@tonic-gate list = list->lp_next) {
33760Sstevel@tonic-gate prop_id = list->lp_simple;
33770Sstevel@tonic-gate if (prop_id == NULL)
33780Sstevel@tonic-gate break;
33790Sstevel@tonic-gate err = zonecfg_remove_fs_option(
33800Sstevel@tonic-gate &in_progress_fstab, prop_id);
33810Sstevel@tonic-gate if (err != Z_OK)
33820Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), err,
33836215Sgjelinek B_TRUE);
33840Sstevel@tonic-gate }
33850Sstevel@tonic-gate }
33860Sstevel@tonic-gate return;
33870Sstevel@tonic-gate case RT_RCTL:
33880Sstevel@tonic-gate if (prop_type != PT_VALUE) {
33890Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
33906215Sgjelinek B_TRUE);
33916215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
33926215Sgjelinek usage(B_FALSE, HELP_PROPS);
33930Sstevel@tonic-gate return;
33940Sstevel@tonic-gate }
33950Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0];
33960Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX) {
33970Sstevel@tonic-gate zerr(gettext("A %s value was expected here."),
33980Sstevel@tonic-gate pvt_to_str(PROP_VAL_COMPLEX));
33996215Sgjelinek saw_error = B_TRUE;
34000Sstevel@tonic-gate return;
34010Sstevel@tonic-gate }
34020Sstevel@tonic-gate if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
34036215Sgjelinek zone_perror(zone, Z_NOMEM, B_TRUE);
34040Sstevel@tonic-gate exit(Z_ERR);
34050Sstevel@tonic-gate }
34060Sstevel@tonic-gate for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
34070Sstevel@tonic-gate switch (cx->cp_type) {
34080Sstevel@tonic-gate case PT_PRIV:
34090Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_priv,
34100Sstevel@tonic-gate cx->cp_value,
34110Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_priv));
34120Sstevel@tonic-gate break;
34130Sstevel@tonic-gate case PT_LIMIT:
34140Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_limit,
34150Sstevel@tonic-gate cx->cp_value,
34160Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_limit));
34170Sstevel@tonic-gate break;
34180Sstevel@tonic-gate case PT_ACTION:
34190Sstevel@tonic-gate (void) strlcpy(rctlvaltab->zone_rctlval_action,
34200Sstevel@tonic-gate cx->cp_value,
34210Sstevel@tonic-gate sizeof (rctlvaltab->zone_rctlval_action));
34220Sstevel@tonic-gate break;
34230Sstevel@tonic-gate default:
34240Sstevel@tonic-gate zone_perror(pt_to_str(prop_type),
34256215Sgjelinek Z_NO_PROPERTY_TYPE, B_TRUE);
34266215Sgjelinek long_usage(CMD_ADD, B_TRUE);
34276215Sgjelinek usage(B_FALSE, HELP_PROPS);
34280Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab);
34290Sstevel@tonic-gate return;
34300Sstevel@tonic-gate }
34310Sstevel@tonic-gate }
34320Sstevel@tonic-gate rctlvaltab->zone_rctlval_next = NULL;
34330Sstevel@tonic-gate err = zonecfg_remove_rctl_value(&in_progress_rctltab,
34340Sstevel@tonic-gate rctlvaltab);
34350Sstevel@tonic-gate if (err != Z_OK)
34366215Sgjelinek zone_perror(pt_to_str(prop_type), err, B_TRUE);
34370Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctlvaltab);
34380Sstevel@tonic-gate return;
34396076Sgfaden case RT_NET:
34406076Sgfaden if (prop_type != PT_DEFROUTER) {
34416076Sgfaden zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
34426215Sgjelinek B_TRUE);
34436215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
34446215Sgjelinek usage(B_FALSE, HELP_PROPS);
34456076Sgfaden return;
34466076Sgfaden } else {
34476076Sgfaden bzero(&in_progress_nwiftab.zone_nwif_defrouter,
34486076Sgfaden sizeof (in_progress_nwiftab.zone_nwif_defrouter));
34496076Sgfaden return;
34506076Sgfaden }
34510Sstevel@tonic-gate default:
34526215Sgjelinek zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
34536215Sgjelinek long_usage(CMD_REMOVE, B_TRUE);
34546215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
34550Sstevel@tonic-gate return;
34560Sstevel@tonic-gate }
34570Sstevel@tonic-gate }
34580Sstevel@tonic-gate
34590Sstevel@tonic-gate void
remove_func(cmd_t * cmd)34600Sstevel@tonic-gate remove_func(cmd_t *cmd)
34610Sstevel@tonic-gate {
34620Sstevel@tonic-gate if (zone_is_read_only(CMD_REMOVE))
34630Sstevel@tonic-gate return;
34640Sstevel@tonic-gate
34650Sstevel@tonic-gate assert(cmd != NULL);
34660Sstevel@tonic-gate
34673247Sgjelinek if (global_scope) {
34683247Sgjelinek if (gz_invalid_resource(cmd->cmd_res_type)) {
34693247Sgjelinek zerr(gettext("%s is not a valid resource for the "
34703247Sgjelinek "global zone."), rt_to_str(cmd->cmd_res_type));
34716215Sgjelinek saw_error = B_TRUE;
34723247Sgjelinek return;
34733247Sgjelinek }
34740Sstevel@tonic-gate remove_resource(cmd);
34753247Sgjelinek } else {
34760Sstevel@tonic-gate remove_property(cmd);
34773247Sgjelinek }
34783247Sgjelinek }
34793247Sgjelinek
34803247Sgjelinek static void
clear_property(cmd_t * cmd)34813247Sgjelinek clear_property(cmd_t *cmd)
34823247Sgjelinek {
34833247Sgjelinek int res_type, prop_type;
34843247Sgjelinek
34853247Sgjelinek res_type = resource_scope;
34863247Sgjelinek prop_type = cmd->cmd_res_type;
34873247Sgjelinek if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
34886215Sgjelinek long_usage(CMD_CLEAR, B_TRUE);
34896215Sgjelinek return;
34906215Sgjelinek }
34916215Sgjelinek
34926215Sgjelinek if (initialize(B_TRUE) != Z_OK)
34933247Sgjelinek return;
34943247Sgjelinek
34953247Sgjelinek switch (res_type) {
34963247Sgjelinek case RT_FS:
34973247Sgjelinek if (prop_type == PT_RAW) {
34983247Sgjelinek in_progress_fstab.zone_fs_raw[0] = '\0';
34996215Sgjelinek need_to_commit = B_TRUE;
35003247Sgjelinek return;
35013247Sgjelinek }
35023247Sgjelinek break;
35033247Sgjelinek case RT_DCPU:
35043247Sgjelinek if (prop_type == PT_IMPORTANCE) {
35053247Sgjelinek in_progress_psettab.zone_importance[0] = '\0';
35066215Sgjelinek need_to_commit = B_TRUE;
35073247Sgjelinek return;
35083247Sgjelinek }
35093247Sgjelinek break;
35103247Sgjelinek case RT_MCAP:
35113247Sgjelinek switch (prop_type) {
35123247Sgjelinek case PT_PHYSICAL:
35133247Sgjelinek in_progress_mcaptab.zone_physmem_cap[0] = '\0';
35146215Sgjelinek need_to_commit = B_TRUE;
35153247Sgjelinek return;
35163247Sgjelinek case PT_SWAP:
35173247Sgjelinek remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
35183247Sgjelinek return;
35193247Sgjelinek case PT_LOCKED:
35203247Sgjelinek remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
35213247Sgjelinek return;
35223247Sgjelinek }
35233247Sgjelinek break;
35243247Sgjelinek default:
35253247Sgjelinek break;
35263247Sgjelinek }
35273247Sgjelinek
35286215Sgjelinek zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
35293247Sgjelinek }
35303247Sgjelinek
35313247Sgjelinek static void
clear_global(cmd_t * cmd)35323247Sgjelinek clear_global(cmd_t *cmd)
35333247Sgjelinek {
35343247Sgjelinek int err, type;
35353247Sgjelinek
35363247Sgjelinek if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
35376215Sgjelinek long_usage(CMD_CLEAR, B_TRUE);
35386215Sgjelinek return;
35396215Sgjelinek }
35406215Sgjelinek
35416215Sgjelinek if (initialize(B_TRUE) != Z_OK)
35423247Sgjelinek return;
35433247Sgjelinek
35443247Sgjelinek switch (type) {
35453247Sgjelinek case PT_ZONENAME:
35463247Sgjelinek /* FALLTHRU */
35473247Sgjelinek case PT_ZONEPATH:
35483247Sgjelinek /* FALLTHRU */
35493247Sgjelinek case PT_BRAND:
35506215Sgjelinek zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
35513247Sgjelinek return;
35523247Sgjelinek case PT_AUTOBOOT:
35533247Sgjelinek /* false is default; we'll treat as equivalent to clearing */
35543247Sgjelinek if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
35556215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
35563247Sgjelinek else
35576215Sgjelinek need_to_commit = B_TRUE;
35583247Sgjelinek return;
35593247Sgjelinek case PT_POOL:
35603247Sgjelinek if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
35616215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
35623247Sgjelinek else
35636215Sgjelinek need_to_commit = B_TRUE;
35643247Sgjelinek return;
35653247Sgjelinek case PT_LIMITPRIV:
35663247Sgjelinek if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
35676215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
35683247Sgjelinek else
35696215Sgjelinek need_to_commit = B_TRUE;
35703247Sgjelinek return;
35713247Sgjelinek case PT_BOOTARGS:
35723247Sgjelinek if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK)
35736215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, B_TRUE);
35743247Sgjelinek else
35756215Sgjelinek need_to_commit = B_TRUE;
35763247Sgjelinek return;
35773247Sgjelinek case PT_SCHED:
35783247Sgjelinek if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK)
35796215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, B_TRUE);
35803247Sgjelinek else
35816215Sgjelinek need_to_commit = B_TRUE;
35823247Sgjelinek return;
35833448Sdh155122 case PT_IPTYPE:
35843448Sdh155122 /* shared is default; we'll treat as equivalent to clearing */
35853448Sdh155122 if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
35866215Sgjelinek z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, B_TRUE);
35873448Sdh155122 else
35886215Sgjelinek need_to_commit = B_TRUE;
35893448Sdh155122 return;
35903247Sgjelinek case PT_MAXLWPS:
35913247Sgjelinek remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
35923247Sgjelinek return;
359312725SMenno.Lageman@Sun.COM case PT_MAXPROCS:
359412725SMenno.Lageman@Sun.COM remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
359512725SMenno.Lageman@Sun.COM return;
35963247Sgjelinek case PT_MAXSHMMEM:
35973247Sgjelinek remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
35983247Sgjelinek return;
35993247Sgjelinek case PT_MAXSHMIDS:
36003247Sgjelinek remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
36013247Sgjelinek return;
36023247Sgjelinek case PT_MAXMSGIDS:
36033247Sgjelinek remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
36043247Sgjelinek return;
36053247Sgjelinek case PT_MAXSEMIDS:
36063247Sgjelinek remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
36073247Sgjelinek return;
36083247Sgjelinek case PT_SHARES:
36093247Sgjelinek remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
36103247Sgjelinek return;
36118662SJordan.Vaughan@Sun.com case PT_HOSTID:
36128662SJordan.Vaughan@Sun.com if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
36138662SJordan.Vaughan@Sun.com z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
36148662SJordan.Vaughan@Sun.com else
36158662SJordan.Vaughan@Sun.com need_to_commit = B_TRUE;
36168662SJordan.Vaughan@Sun.com return;
361712633Sjohn.levon@sun.com case PT_FS_ALLOWED:
361812633Sjohn.levon@sun.com if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
361912633Sjohn.levon@sun.com z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
362012633Sjohn.levon@sun.com else
362112633Sjohn.levon@sun.com need_to_commit = B_TRUE;
362212633Sjohn.levon@sun.com return;
36233247Sgjelinek default:
36246215Sgjelinek zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
36256215Sgjelinek long_usage(CMD_CLEAR, B_TRUE);
36266215Sgjelinek usage(B_FALSE, HELP_PROPS);
36273247Sgjelinek return;
36283247Sgjelinek }
36293247Sgjelinek }
36303247Sgjelinek
36313247Sgjelinek void
clear_func(cmd_t * cmd)36323247Sgjelinek clear_func(cmd_t *cmd)
36333247Sgjelinek {
36343247Sgjelinek if (zone_is_read_only(CMD_CLEAR))
36353247Sgjelinek return;
36363247Sgjelinek
36373247Sgjelinek assert(cmd != NULL);
36383247Sgjelinek
36393247Sgjelinek if (global_scope) {
36403247Sgjelinek if (gz_invalid_property(cmd->cmd_res_type)) {
36413247Sgjelinek zerr(gettext("%s is not a valid property for the "
36423247Sgjelinek "global zone."), pt_to_str(cmd->cmd_res_type));
36436215Sgjelinek saw_error = B_TRUE;
36443247Sgjelinek return;
36453247Sgjelinek }
36463247Sgjelinek
36473247Sgjelinek clear_global(cmd);
36483247Sgjelinek } else {
36493247Sgjelinek clear_property(cmd);
36503247Sgjelinek }
36510Sstevel@tonic-gate }
36520Sstevel@tonic-gate
36530Sstevel@tonic-gate void
select_func(cmd_t * cmd)36540Sstevel@tonic-gate select_func(cmd_t *cmd)
36550Sstevel@tonic-gate {
36563247Sgjelinek int type, err, res;
36573247Sgjelinek uint64_t limit;
36583792Sakolb uint64_t tmp;
36590Sstevel@tonic-gate
36600Sstevel@tonic-gate if (zone_is_read_only(CMD_SELECT))
36610Sstevel@tonic-gate return;
36620Sstevel@tonic-gate
36630Sstevel@tonic-gate assert(cmd != NULL);
36640Sstevel@tonic-gate
36650Sstevel@tonic-gate if (global_scope) {
36666215Sgjelinek global_scope = B_FALSE;
36670Sstevel@tonic-gate resource_scope = cmd->cmd_res_type;
36680Sstevel@tonic-gate end_op = CMD_SELECT;
36690Sstevel@tonic-gate } else {
36700Sstevel@tonic-gate scope_usage(CMD_SELECT);
36710Sstevel@tonic-gate return;
36720Sstevel@tonic-gate }
36730Sstevel@tonic-gate
36740Sstevel@tonic-gate if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
36756215Sgjelinek long_usage(CMD_SELECT, B_TRUE);
36766215Sgjelinek return;
36776215Sgjelinek }
36786215Sgjelinek
36796215Sgjelinek if (initialize(B_TRUE) != Z_OK)
36800Sstevel@tonic-gate return;
36810Sstevel@tonic-gate
36820Sstevel@tonic-gate switch (type) {
36830Sstevel@tonic-gate case RT_FS:
36846215Sgjelinek if ((err = fill_in_fstab(cmd, &old_fstab, B_FALSE)) != Z_OK) {
36856215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_FS, err, B_TRUE);
36866215Sgjelinek global_scope = B_TRUE;
36870Sstevel@tonic-gate }
36880Sstevel@tonic-gate bcopy(&old_fstab, &in_progress_fstab,
36890Sstevel@tonic-gate sizeof (struct zone_fstab));
36900Sstevel@tonic-gate return;
36910Sstevel@tonic-gate case RT_NET:
36926215Sgjelinek if ((err = fill_in_nwiftab(cmd, &old_nwiftab, B_FALSE))
36936215Sgjelinek != Z_OK) {
36946215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_NET, err, B_TRUE);
36956215Sgjelinek global_scope = B_TRUE;
36960Sstevel@tonic-gate }
36970Sstevel@tonic-gate bcopy(&old_nwiftab, &in_progress_nwiftab,
36980Sstevel@tonic-gate sizeof (struct zone_nwiftab));
36990Sstevel@tonic-gate return;
37000Sstevel@tonic-gate case RT_DEVICE:
37016215Sgjelinek if ((err = fill_in_devtab(cmd, &old_devtab, B_FALSE)) != Z_OK) {
37026215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, B_TRUE);
37036215Sgjelinek global_scope = B_TRUE;
37040Sstevel@tonic-gate }
37050Sstevel@tonic-gate bcopy(&old_devtab, &in_progress_devtab,
37060Sstevel@tonic-gate sizeof (struct zone_devtab));
37070Sstevel@tonic-gate return;
37080Sstevel@tonic-gate case RT_RCTL:
37096215Sgjelinek if ((err = fill_in_rctltab(cmd, &old_rctltab, B_FALSE))
37106215Sgjelinek != Z_OK) {
37116215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, B_TRUE);
37126215Sgjelinek global_scope = B_TRUE;
37130Sstevel@tonic-gate }
37140Sstevel@tonic-gate bcopy(&old_rctltab, &in_progress_rctltab,
37150Sstevel@tonic-gate sizeof (struct zone_rctltab));
37160Sstevel@tonic-gate return;
37170Sstevel@tonic-gate case RT_ATTR:
37186215Sgjelinek if ((err = fill_in_attrtab(cmd, &old_attrtab, B_FALSE))
37196215Sgjelinek != Z_OK) {
37206215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, B_TRUE);
37216215Sgjelinek global_scope = B_TRUE;
37220Sstevel@tonic-gate }
37230Sstevel@tonic-gate bcopy(&old_attrtab, &in_progress_attrtab,
37240Sstevel@tonic-gate sizeof (struct zone_attrtab));
37250Sstevel@tonic-gate return;
3726789Sahrens case RT_DATASET:
37276215Sgjelinek if ((err = fill_in_dstab(cmd, &old_dstab, B_FALSE)) != Z_OK) {
37286215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, B_TRUE);
37296215Sgjelinek global_scope = B_TRUE;
3730789Sahrens }
3731789Sahrens bcopy(&old_dstab, &in_progress_dstab,
3732789Sahrens sizeof (struct zone_dstab));
3733789Sahrens return;
37343247Sgjelinek case RT_DCPU:
37353247Sgjelinek if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
37366215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
37376215Sgjelinek global_scope = B_TRUE;
37383247Sgjelinek }
37393247Sgjelinek bcopy(&old_psettab, &in_progress_psettab,
37403247Sgjelinek sizeof (struct zone_psettab));
37413247Sgjelinek return;
37423792Sakolb case RT_PCAP:
37433792Sakolb if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
37443792Sakolb != Z_OK) {
37456215Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
37466215Sgjelinek global_scope = B_TRUE;
37473792Sakolb }
37483792Sakolb return;
37493247Sgjelinek case RT_MCAP:
37503247Sgjelinek /* if none of these exist, there is no resource to select */
37513247Sgjelinek if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
37523247Sgjelinek zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
37533247Sgjelinek != Z_OK &&
37543247Sgjelinek zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
37553247Sgjelinek != Z_OK) {
37563247Sgjelinek z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
37576215Sgjelinek B_TRUE);
37586215Sgjelinek global_scope = B_TRUE;
37593247Sgjelinek }
37603247Sgjelinek if (res == Z_OK)
37613247Sgjelinek bcopy(&old_mcaptab, &in_progress_mcaptab,
37623247Sgjelinek sizeof (struct zone_mcaptab));
37633247Sgjelinek else
37643247Sgjelinek bzero(&in_progress_mcaptab,
37653247Sgjelinek sizeof (in_progress_mcaptab));
37663247Sgjelinek return;
376712578SGlenn.Faden@Sun.COM case RT_ADMIN:
376812578SGlenn.Faden@Sun.COM if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
376912578SGlenn.Faden@Sun.COM != Z_OK) {
377012578SGlenn.Faden@Sun.COM z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
377112578SGlenn.Faden@Sun.COM B_TRUE);
377212578SGlenn.Faden@Sun.COM global_scope = B_TRUE;
377312578SGlenn.Faden@Sun.COM }
377412578SGlenn.Faden@Sun.COM bcopy(&old_admintab, &in_progress_admintab,
377512578SGlenn.Faden@Sun.COM sizeof (struct zone_admintab));
377612578SGlenn.Faden@Sun.COM return;
37770Sstevel@tonic-gate default:
37786215Sgjelinek zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
37796215Sgjelinek long_usage(CMD_SELECT, B_TRUE);
37806215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
37810Sstevel@tonic-gate return;
37820Sstevel@tonic-gate }
37830Sstevel@tonic-gate }
37840Sstevel@tonic-gate
37850Sstevel@tonic-gate /*
37860Sstevel@tonic-gate * Network "addresses" can be one of the following forms:
37870Sstevel@tonic-gate * <IPv4 address>
37880Sstevel@tonic-gate * <IPv4 address>/<prefix length>
37890Sstevel@tonic-gate * <IPv6 address>/<prefix length>
37900Sstevel@tonic-gate * <host name>
37910Sstevel@tonic-gate * <host name>/<prefix length>
37920Sstevel@tonic-gate * In other words, the "/" followed by a prefix length is allowed but not
37930Sstevel@tonic-gate * required for IPv4 addresses and host names, and required for IPv6 addresses.
37940Sstevel@tonic-gate * If a prefix length is given, it must be in the allowable range: 0 to 32 for
37950Sstevel@tonic-gate * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
37960Sstevel@tonic-gate * Host names must start with an alpha-numeric character, and all subsequent
37970Sstevel@tonic-gate * characters must be either alpha-numeric or "-".
379812748SSowmini.Varadhan@oracle.COM *
379912748SSowmini.Varadhan@oracle.COM * In some cases, e.g., the nexthop for the defrouter, the context indicates
380012748SSowmini.Varadhan@oracle.COM * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
380112748SSowmini.Varadhan@oracle.COM * require the /<prefix length> (and should ignore it if provided).
38020Sstevel@tonic-gate */
38030Sstevel@tonic-gate
38040Sstevel@tonic-gate static int
validate_net_address_syntax(char * address,boolean_t ishost)380512748SSowmini.Varadhan@oracle.COM validate_net_address_syntax(char *address, boolean_t ishost)
38060Sstevel@tonic-gate {
38070Sstevel@tonic-gate char *slashp, part1[MAXHOSTNAMELEN];
38080Sstevel@tonic-gate struct in6_addr in6;
38090Sstevel@tonic-gate struct in_addr in4;
38100Sstevel@tonic-gate int prefixlen, i;
38110Sstevel@tonic-gate
38120Sstevel@tonic-gate /*
38130Sstevel@tonic-gate * Copy the part before any '/' into part1 or copy the whole
38140Sstevel@tonic-gate * thing if there is no '/'.
38150Sstevel@tonic-gate */
38160Sstevel@tonic-gate if ((slashp = strchr(address, '/')) != NULL) {
38170Sstevel@tonic-gate *slashp = '\0';
38180Sstevel@tonic-gate (void) strlcpy(part1, address, sizeof (part1));
38190Sstevel@tonic-gate *slashp = '/';
38200Sstevel@tonic-gate prefixlen = atoi(++slashp);
38210Sstevel@tonic-gate } else {
38220Sstevel@tonic-gate (void) strlcpy(part1, address, sizeof (part1));
38230Sstevel@tonic-gate }
38240Sstevel@tonic-gate
382512748SSowmini.Varadhan@oracle.COM if (ishost && slashp != NULL) {
382612748SSowmini.Varadhan@oracle.COM zerr(gettext("Warning: prefix length in %s is not required and "
382712748SSowmini.Varadhan@oracle.COM "will be ignored. The default host-prefix length "
382812748SSowmini.Varadhan@oracle.COM "will be used"), address);
382912748SSowmini.Varadhan@oracle.COM }
383012748SSowmini.Varadhan@oracle.COM
383112748SSowmini.Varadhan@oracle.COM
38320Sstevel@tonic-gate if (inet_pton(AF_INET6, part1, &in6) == 1) {
383312748SSowmini.Varadhan@oracle.COM if (ishost) {
383412748SSowmini.Varadhan@oracle.COM prefixlen = IPV6_ABITS;
383512748SSowmini.Varadhan@oracle.COM } else if (slashp == NULL) {
38360Sstevel@tonic-gate zerr(gettext("%s: IPv6 addresses "
38370Sstevel@tonic-gate "require /prefix-length suffix."), address);
38380Sstevel@tonic-gate return (Z_ERR);
38390Sstevel@tonic-gate }
38400Sstevel@tonic-gate if (prefixlen < 0 || prefixlen > 128) {
38410Sstevel@tonic-gate zerr(gettext("%s: IPv6 address "
38420Sstevel@tonic-gate "prefix lengths must be 0 - 128."), address);
38430Sstevel@tonic-gate return (Z_ERR);
38440Sstevel@tonic-gate }
38450Sstevel@tonic-gate return (Z_OK);
38460Sstevel@tonic-gate }
38470Sstevel@tonic-gate
38480Sstevel@tonic-gate /* At this point, any /prefix must be for IPv4. */
384912748SSowmini.Varadhan@oracle.COM if (ishost)
385012748SSowmini.Varadhan@oracle.COM prefixlen = IPV4_ABITS;
385112748SSowmini.Varadhan@oracle.COM else if (slashp != NULL) {
38520Sstevel@tonic-gate if (prefixlen < 0 || prefixlen > 32) {
38530Sstevel@tonic-gate zerr(gettext("%s: IPv4 address "
38540Sstevel@tonic-gate "prefix lengths must be 0 - 32."), address);
38550Sstevel@tonic-gate return (Z_ERR);
38560Sstevel@tonic-gate }
38570Sstevel@tonic-gate }
385812748SSowmini.Varadhan@oracle.COM
38590Sstevel@tonic-gate if (inet_pton(AF_INET, part1, &in4) == 1)
38600Sstevel@tonic-gate return (Z_OK);
38610Sstevel@tonic-gate
38620Sstevel@tonic-gate /* address may also be a host name */
38630Sstevel@tonic-gate if (!isalnum(part1[0])) {
38640Sstevel@tonic-gate zerr(gettext("%s: bogus host name or network address syntax"),
38650Sstevel@tonic-gate part1);
38666215Sgjelinek saw_error = B_TRUE;
38676215Sgjelinek usage(B_FALSE, HELP_NETADDR);
38680Sstevel@tonic-gate return (Z_ERR);
38690Sstevel@tonic-gate }
38700Sstevel@tonic-gate for (i = 1; part1[i]; i++)
38710Sstevel@tonic-gate if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
38720Sstevel@tonic-gate zerr(gettext("%s: bogus host name or "
38730Sstevel@tonic-gate "network address syntax"), part1);
38746215Sgjelinek saw_error = B_TRUE;
38756215Sgjelinek usage(B_FALSE, HELP_NETADDR);
38760Sstevel@tonic-gate return (Z_ERR);
38770Sstevel@tonic-gate }
38780Sstevel@tonic-gate return (Z_OK);
38790Sstevel@tonic-gate }
38800Sstevel@tonic-gate
38810Sstevel@tonic-gate static int
validate_net_physical_syntax(const char * ifname)38828083SJordan.Vaughan@Sun.com validate_net_physical_syntax(const char *ifname)
38830Sstevel@tonic-gate {
38848083SJordan.Vaughan@Sun.com ifspec_t ifnameprop;
38858083SJordan.Vaughan@Sun.com zone_iptype_t iptype;
38868087SJordan.Vaughan@Sun.com
38878087SJordan.Vaughan@Sun.com if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
38888083SJordan.Vaughan@Sun.com zerr(gettext("zone configuration has an invalid or nonexistent "
38898083SJordan.Vaughan@Sun.com "ip-type property"));
38908083SJordan.Vaughan@Sun.com return (Z_ERR);
38918083SJordan.Vaughan@Sun.com }
38928083SJordan.Vaughan@Sun.com switch (iptype) {
38938083SJordan.Vaughan@Sun.com case ZS_SHARED:
38948083SJordan.Vaughan@Sun.com if (ifparse_ifspec(ifname, &ifnameprop) == B_FALSE) {
38958083SJordan.Vaughan@Sun.com zerr(gettext("%s: invalid physical interface name"),
38968083SJordan.Vaughan@Sun.com ifname);
38978083SJordan.Vaughan@Sun.com return (Z_ERR);
38988083SJordan.Vaughan@Sun.com }
38998083SJordan.Vaughan@Sun.com if (ifnameprop.ifsp_lunvalid) {
39008083SJordan.Vaughan@Sun.com zerr(gettext("%s: LUNs not allowed in physical "
39018083SJordan.Vaughan@Sun.com "interface names"), ifname);
39028083SJordan.Vaughan@Sun.com return (Z_ERR);
39038083SJordan.Vaughan@Sun.com }
39048083SJordan.Vaughan@Sun.com break;
39058083SJordan.Vaughan@Sun.com case ZS_EXCLUSIVE:
39068083SJordan.Vaughan@Sun.com if (dladm_valid_linkname(ifname) == B_FALSE) {
39078083SJordan.Vaughan@Sun.com if (strchr(ifname, ':') != NULL)
39088083SJordan.Vaughan@Sun.com zerr(gettext("%s: physical interface name "
39098083SJordan.Vaughan@Sun.com "required; logical interface name not "
39108083SJordan.Vaughan@Sun.com "allowed"), ifname);
39118083SJordan.Vaughan@Sun.com else
39128083SJordan.Vaughan@Sun.com zerr(gettext("%s: invalid physical interface "
39138083SJordan.Vaughan@Sun.com "name"), ifname);
39148083SJordan.Vaughan@Sun.com return (Z_ERR);
39158083SJordan.Vaughan@Sun.com }
39168083SJordan.Vaughan@Sun.com break;
39178083SJordan.Vaughan@Sun.com }
39188083SJordan.Vaughan@Sun.com return (Z_OK);
39190Sstevel@tonic-gate }
39200Sstevel@tonic-gate
39210Sstevel@tonic-gate static boolean_t
valid_fs_type(const char * type)39220Sstevel@tonic-gate valid_fs_type(const char *type)
39230Sstevel@tonic-gate {
39240Sstevel@tonic-gate /*
39250Sstevel@tonic-gate * Is this a valid path component?
39260Sstevel@tonic-gate */
39270Sstevel@tonic-gate if (strlen(type) + 1 > MAXNAMELEN)
39280Sstevel@tonic-gate return (B_FALSE);
39290Sstevel@tonic-gate /*
39300Sstevel@tonic-gate * Make sure a bad value for "type" doesn't make
39310Sstevel@tonic-gate * /usr/lib/fs/<type>/mount turn into something else.
39320Sstevel@tonic-gate */
39330Sstevel@tonic-gate if (strchr(type, '/') != NULL || type[0] == '\0' ||
39340Sstevel@tonic-gate strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
3935565Sdp return (B_FALSE);
39360Sstevel@tonic-gate /*
39370Sstevel@tonic-gate * More detailed verification happens later by zoneadm(1m).
39380Sstevel@tonic-gate */
39390Sstevel@tonic-gate return (B_TRUE);
39400Sstevel@tonic-gate }
39410Sstevel@tonic-gate
39423448Sdh155122 static boolean_t
allow_exclusive()39433448Sdh155122 allow_exclusive()
39443448Sdh155122 {
39453448Sdh155122 brand_handle_t bh;
39463448Sdh155122 char brand[MAXNAMELEN];
39473448Sdh155122 boolean_t ret;
39483448Sdh155122
39493448Sdh155122 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
39503448Sdh155122 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
39513448Sdh155122 return (B_FALSE);
39523448Sdh155122 }
39533448Sdh155122 if ((bh = brand_open(brand)) == NULL) {
39543448Sdh155122 zerr("%s: %s\n", zone, gettext("unknown brand."));
39553448Sdh155122 return (B_FALSE);
39563448Sdh155122 }
39573448Sdh155122 ret = brand_allow_exclusive_ip(bh);
39583448Sdh155122 brand_close(bh);
39593448Sdh155122 if (!ret)
39603448Sdh155122 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
39613448Sdh155122 pt_to_str(PT_IPTYPE), "exclusive",
39623448Sdh155122 pt_to_str(PT_BRAND), brand);
39633448Sdh155122 return (ret);
39643448Sdh155122 }
39653448Sdh155122
39663247Sgjelinek static void
set_aliased_rctl(char * alias,int prop_type,char * s)39673247Sgjelinek set_aliased_rctl(char *alias, int prop_type, char *s)
39683247Sgjelinek {
39693247Sgjelinek uint64_t limit;
39703247Sgjelinek int err;
39713247Sgjelinek char tmp[128];
39723247Sgjelinek
39733247Sgjelinek if (global_zone && strcmp(alias, ALIAS_SHARES) != 0)
39743247Sgjelinek zerr(gettext("WARNING: Setting a global zone resource "
39753247Sgjelinek "control too low could deny\nservice "
39763247Sgjelinek "to even the root user; "
39773247Sgjelinek "this could render the system impossible\n"
39783247Sgjelinek "to administer. Please use caution."));
39793247Sgjelinek
39803247Sgjelinek /* convert memory based properties */
39813247Sgjelinek if (prop_type == PT_MAXSHMMEM) {
39823247Sgjelinek if (!zonecfg_valid_memlimit(s, &limit)) {
39833247Sgjelinek zerr(gettext("A non-negative number with a required "
39843247Sgjelinek "scale suffix (K, M, G or T) was expected\nhere."));
39856215Sgjelinek saw_error = B_TRUE;
39863247Sgjelinek return;
39873247Sgjelinek }
39883247Sgjelinek
39893247Sgjelinek (void) snprintf(tmp, sizeof (tmp), "%llu", limit);
39903247Sgjelinek s = tmp;
39913247Sgjelinek }
39923247Sgjelinek
39933247Sgjelinek if (!zonecfg_aliased_rctl_ok(handle, alias)) {
39946215Sgjelinek zone_perror(pt_to_str(prop_type), Z_ALIAS_DISALLOW, B_FALSE);
39956215Sgjelinek saw_error = B_TRUE;
39963247Sgjelinek } else if (!zonecfg_valid_alias_limit(alias, s, &limit)) {
39973247Sgjelinek zerr(gettext("%s property is out of range."),
39983247Sgjelinek pt_to_str(prop_type));
39996215Sgjelinek saw_error = B_TRUE;
40003247Sgjelinek } else if ((err = zonecfg_set_aliased_rctl(handle, alias, limit))
40013247Sgjelinek != Z_OK) {
40026215Sgjelinek zone_perror(zone, err, B_TRUE);
40036215Sgjelinek saw_error = B_TRUE;
40043247Sgjelinek } else {
40056215Sgjelinek need_to_commit = B_TRUE;
40063247Sgjelinek }
40073247Sgjelinek }
40083247Sgjelinek
400912748SSowmini.Varadhan@oracle.COM static void
set_in_progress_nwiftab_address(char * prop_id,int prop_type)401012748SSowmini.Varadhan@oracle.COM set_in_progress_nwiftab_address(char *prop_id, int prop_type)
401112748SSowmini.Varadhan@oracle.COM {
401212748SSowmini.Varadhan@oracle.COM if (prop_type == PT_ADDRESS) {
401312748SSowmini.Varadhan@oracle.COM (void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
401412748SSowmini.Varadhan@oracle.COM sizeof (in_progress_nwiftab.zone_nwif_address));
401512748SSowmini.Varadhan@oracle.COM } else {
401612748SSowmini.Varadhan@oracle.COM assert(prop_type == PT_ALLOWED_ADDRESS);
401712748SSowmini.Varadhan@oracle.COM (void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
401812748SSowmini.Varadhan@oracle.COM prop_id,
401912748SSowmini.Varadhan@oracle.COM sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
402012748SSowmini.Varadhan@oracle.COM }
402112748SSowmini.Varadhan@oracle.COM }
402212748SSowmini.Varadhan@oracle.COM
40230Sstevel@tonic-gate void
set_func(cmd_t * cmd)40240Sstevel@tonic-gate set_func(cmd_t *cmd)
40250Sstevel@tonic-gate {
40260Sstevel@tonic-gate char *prop_id;
40272303Scarlsonj int arg, err, res_type, prop_type;
40280Sstevel@tonic-gate property_value_ptr_t pp;
40290Sstevel@tonic-gate boolean_t autoboot;
40303448Sdh155122 zone_iptype_t iptype;
40316215Sgjelinek boolean_t force_set = B_FALSE;
40323247Sgjelinek size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
40333247Sgjelinek uint64_t mem_cap, mem_limit;
40343792Sakolb float cap;
40353792Sakolb char *unitp;
40363247Sgjelinek struct zone_psettab tmp_psettab;
40376215Sgjelinek boolean_t arg_err = B_FALSE;
40380Sstevel@tonic-gate
40390Sstevel@tonic-gate if (zone_is_read_only(CMD_SET))
40400Sstevel@tonic-gate return;
40410Sstevel@tonic-gate
40420Sstevel@tonic-gate assert(cmd != NULL);
40430Sstevel@tonic-gate
40442303Scarlsonj optind = opterr = 0;
40452303Scarlsonj while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
40462303Scarlsonj switch (arg) {
40472303Scarlsonj case 'F':
40486215Sgjelinek force_set = B_TRUE;
40492303Scarlsonj break;
40502303Scarlsonj default:
40512303Scarlsonj if (optopt == '?')
40522303Scarlsonj longer_usage(CMD_SET);
40532303Scarlsonj else
40542303Scarlsonj short_usage(CMD_SET);
40556215Sgjelinek arg_err = B_TRUE;
40563691Sgjelinek break;
40573691Sgjelinek }
40583691Sgjelinek }
40593691Sgjelinek if (arg_err)
40603691Sgjelinek return;
40612303Scarlsonj
40620Sstevel@tonic-gate prop_type = cmd->cmd_prop_name[0];
40630Sstevel@tonic-gate if (global_scope) {
40643247Sgjelinek if (gz_invalid_property(prop_type)) {
40653247Sgjelinek zerr(gettext("%s is not a valid property for the "
40663247Sgjelinek "global zone."), pt_to_str(prop_type));
40676215Sgjelinek saw_error = B_TRUE;
40683247Sgjelinek return;
40693247Sgjelinek }
40703247Sgjelinek
4071565Sdp if (prop_type == PT_ZONENAME) {
4072565Sdp res_type = RT_ZONENAME;
4073565Sdp } else if (prop_type == PT_ZONEPATH) {
40740Sstevel@tonic-gate res_type = RT_ZONEPATH;
40750Sstevel@tonic-gate } else if (prop_type == PT_AUTOBOOT) {
40760Sstevel@tonic-gate res_type = RT_AUTOBOOT;
40772712Snn35248 } else if (prop_type == PT_BRAND) {
40782712Snn35248 res_type = RT_BRAND;
40790Sstevel@tonic-gate } else if (prop_type == PT_POOL) {
40800Sstevel@tonic-gate res_type = RT_POOL;
40811645Scomay } else if (prop_type == PT_LIMITPRIV) {
40821645Scomay res_type = RT_LIMITPRIV;
40832267Sdp } else if (prop_type == PT_BOOTARGS) {
40842267Sdp res_type = RT_BOOTARGS;
40853247Sgjelinek } else if (prop_type == PT_SCHED) {
40863247Sgjelinek res_type = RT_SCHED;
40873448Sdh155122 } else if (prop_type == PT_IPTYPE) {
40883448Sdh155122 res_type = RT_IPTYPE;
40893247Sgjelinek } else if (prop_type == PT_MAXLWPS) {
40903247Sgjelinek res_type = RT_MAXLWPS;
409112725SMenno.Lageman@Sun.COM } else if (prop_type == PT_MAXPROCS) {
409212725SMenno.Lageman@Sun.COM res_type = RT_MAXPROCS;
40933247Sgjelinek } else if (prop_type == PT_MAXSHMMEM) {
40943247Sgjelinek res_type = RT_MAXSHMMEM;
40953247Sgjelinek } else if (prop_type == PT_MAXSHMIDS) {
40963247Sgjelinek res_type = RT_MAXSHMIDS;
40973247Sgjelinek } else if (prop_type == PT_MAXMSGIDS) {
40983247Sgjelinek res_type = RT_MAXMSGIDS;
40993247Sgjelinek } else if (prop_type == PT_MAXSEMIDS) {
41003247Sgjelinek res_type = RT_MAXSEMIDS;
41013247Sgjelinek } else if (prop_type == PT_SHARES) {
41023247Sgjelinek res_type = RT_SHARES;
41038662SJordan.Vaughan@Sun.com } else if (prop_type == PT_HOSTID) {
41048662SJordan.Vaughan@Sun.com res_type = RT_HOSTID;
410512633Sjohn.levon@sun.com } else if (prop_type == PT_FS_ALLOWED) {
410612633Sjohn.levon@sun.com res_type = RT_FS_ALLOWED;
41070Sstevel@tonic-gate } else {
41080Sstevel@tonic-gate zerr(gettext("Cannot set a resource-specific property "
41090Sstevel@tonic-gate "from the global scope."));
41106215Sgjelinek saw_error = B_TRUE;
41110Sstevel@tonic-gate return;
41120Sstevel@tonic-gate }
41130Sstevel@tonic-gate } else {
41140Sstevel@tonic-gate res_type = resource_scope;
41150Sstevel@tonic-gate }
41160Sstevel@tonic-gate
41172303Scarlsonj if (force_set) {
41182303Scarlsonj if (res_type != RT_ZONEPATH) {
41192303Scarlsonj zerr(gettext("Only zonepath setting can be forced."));
41206215Sgjelinek saw_error = B_TRUE;
41212303Scarlsonj return;
41222303Scarlsonj }
41232303Scarlsonj if (!zonecfg_in_alt_root()) {
41242303Scarlsonj zerr(gettext("Zonepath is changeable only in an "
41252303Scarlsonj "alternate root."));
41266215Sgjelinek saw_error = B_TRUE;
41272303Scarlsonj return;
41282303Scarlsonj }
41292303Scarlsonj }
41302303Scarlsonj
41310Sstevel@tonic-gate pp = cmd->cmd_property_ptr[0];
41320Sstevel@tonic-gate /*
41330Sstevel@tonic-gate * A nasty expression but not that complicated:
41340Sstevel@tonic-gate * 1. fs options are simple or list (tested below)
41350Sstevel@tonic-gate * 2. rctl value's are complex or list (tested below)
41360Sstevel@tonic-gate * Anything else should be simple.
41370Sstevel@tonic-gate */
41380Sstevel@tonic-gate if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
41390Sstevel@tonic-gate !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
41400Sstevel@tonic-gate (pp->pv_type != PROP_VAL_SIMPLE ||
41410Sstevel@tonic-gate (prop_id = pp->pv_simple) == NULL)) {
41420Sstevel@tonic-gate zerr(gettext("A %s value was expected here."),
41430Sstevel@tonic-gate pvt_to_str(PROP_VAL_SIMPLE));
41446215Sgjelinek saw_error = B_TRUE;
41450Sstevel@tonic-gate return;
41460Sstevel@tonic-gate }
41470Sstevel@tonic-gate if (prop_type == PT_UNKNOWN) {
41486215Sgjelinek long_usage(CMD_SET, B_TRUE);
41490Sstevel@tonic-gate return;
41500Sstevel@tonic-gate }
41510Sstevel@tonic-gate
4152565Sdp /*
4153565Sdp * Special case: the user can change the zone name prior to 'create';
4154565Sdp * if the zone already exists, we fall through letting initialize()
4155565Sdp * and the rest of the logic run.
4156565Sdp */
41576215Sgjelinek if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4158565Sdp !state_atleast(ZONE_STATE_CONFIGURED)) {
41591497Sdp if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
41606215Sgjelinek zone_perror(prop_id, err, B_TRUE);
41616215Sgjelinek usage(B_FALSE, HELP_SYNTAX);
41621497Sdp return;
41631497Sdp }
4164565Sdp (void) strlcpy(zone, prop_id, sizeof (zone));
4165565Sdp return;
4166565Sdp }
4167565Sdp
41686215Sgjelinek if (initialize(B_TRUE) != Z_OK)
41690Sstevel@tonic-gate return;
41700Sstevel@tonic-gate
41710Sstevel@tonic-gate switch (res_type) {
4172565Sdp case RT_ZONENAME:
4173565Sdp if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
4174565Sdp /*
4175565Sdp * Use prop_id instead of 'zone' here, since we're
4176565Sdp * reporting a problem about the *new* zonename.
4177565Sdp */
41786215Sgjelinek zone_perror(prop_id, err, B_TRUE);
41796215Sgjelinek usage(B_FALSE, HELP_SYNTAX);
4180565Sdp } else {
41816215Sgjelinek need_to_commit = B_TRUE;
4182565Sdp (void) strlcpy(zone, prop_id, sizeof (zone));
4183565Sdp }
4184565Sdp return;
41850Sstevel@tonic-gate case RT_ZONEPATH:
41862303Scarlsonj if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
41870Sstevel@tonic-gate zerr(gettext("Zone %s already installed; %s %s not "
41880Sstevel@tonic-gate "allowed."), zone, cmd_to_str(CMD_SET),
41890Sstevel@tonic-gate rt_to_str(RT_ZONEPATH));
41900Sstevel@tonic-gate return;
41910Sstevel@tonic-gate }
41920Sstevel@tonic-gate if (validate_zonepath_syntax(prop_id) != Z_OK) {
41936215Sgjelinek saw_error = B_TRUE;
41940Sstevel@tonic-gate return;
41950Sstevel@tonic-gate }
41960Sstevel@tonic-gate if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
41976215Sgjelinek zone_perror(zone, err, B_TRUE);
41980Sstevel@tonic-gate else
41996215Sgjelinek need_to_commit = B_TRUE;
42000Sstevel@tonic-gate return;
42012712Snn35248 case RT_BRAND:
42022712Snn35248 if (state_atleast(ZONE_STATE_INSTALLED)) {
42032712Snn35248 zerr(gettext("Zone %s already installed; %s %s not "
42042712Snn35248 "allowed."), zone, cmd_to_str(CMD_SET),
42052712Snn35248 rt_to_str(RT_BRAND));
42062712Snn35248 return;
42072712Snn35248 }
42082712Snn35248 if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
42096215Sgjelinek zone_perror(zone, err, B_TRUE);
42102712Snn35248 else
42116215Sgjelinek need_to_commit = B_TRUE;
42122712Snn35248 return;
42130Sstevel@tonic-gate case RT_AUTOBOOT:
42140Sstevel@tonic-gate if (strcmp(prop_id, "true") == 0) {
42150Sstevel@tonic-gate autoboot = B_TRUE;
42160Sstevel@tonic-gate } else if (strcmp(prop_id, "false") == 0) {
42170Sstevel@tonic-gate autoboot = B_FALSE;
42180Sstevel@tonic-gate } else {
42190Sstevel@tonic-gate zerr(gettext("%s value must be '%s' or '%s'."),
42200Sstevel@tonic-gate pt_to_str(PT_AUTOBOOT), "true", "false");
42216215Sgjelinek saw_error = B_TRUE;
42220Sstevel@tonic-gate return;
42230Sstevel@tonic-gate }
42240Sstevel@tonic-gate if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
42256215Sgjelinek zone_perror(zone, err, B_TRUE);
42260Sstevel@tonic-gate else
42276215Sgjelinek need_to_commit = B_TRUE;
42280Sstevel@tonic-gate return;
42290Sstevel@tonic-gate case RT_POOL:
42303247Sgjelinek /* don't allow use of the reserved temporary pool names */
42313247Sgjelinek if (strncmp("SUNW", prop_id, 4) == 0) {
42323247Sgjelinek zerr(gettext("pool names starting with SUNW are "
42333247Sgjelinek "reserved."));
42346215Sgjelinek saw_error = B_TRUE;
42353247Sgjelinek return;
42363247Sgjelinek }
42373247Sgjelinek
42383247Sgjelinek /* can't set pool if dedicated-cpu exists */
42393247Sgjelinek if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
42403247Sgjelinek zerr(gettext("The %s resource already exists. "
42413247Sgjelinek "A persistent pool is incompatible\nwith the %s "
42423247Sgjelinek "resource."), rt_to_str(RT_DCPU),
42433247Sgjelinek rt_to_str(RT_DCPU));
42446215Sgjelinek saw_error = B_TRUE;
42453247Sgjelinek return;
42463247Sgjelinek }
42473247Sgjelinek
42480Sstevel@tonic-gate if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
42496215Sgjelinek zone_perror(zone, err, B_TRUE);
42500Sstevel@tonic-gate else
42516215Sgjelinek need_to_commit = B_TRUE;
42520Sstevel@tonic-gate return;
42531645Scomay case RT_LIMITPRIV:
42541645Scomay if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
42556215Sgjelinek zone_perror(zone, err, B_TRUE);
42561645Scomay else
42576215Sgjelinek need_to_commit = B_TRUE;
42581645Scomay return;
42592267Sdp case RT_BOOTARGS:
42602267Sdp if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
42616215Sgjelinek zone_perror(zone, err, B_TRUE);
42622267Sdp else
42636215Sgjelinek need_to_commit = B_TRUE;
42642267Sdp return;
42653247Sgjelinek case RT_SCHED:
42663247Sgjelinek if ((err = zonecfg_set_sched(handle, prop_id)) != Z_OK)
42676215Sgjelinek zone_perror(zone, err, B_TRUE);
42683247Sgjelinek else
42696215Sgjelinek need_to_commit = B_TRUE;
42703247Sgjelinek return;
42713448Sdh155122 case RT_IPTYPE:
42723448Sdh155122 if (strcmp(prop_id, "shared") == 0) {
42733448Sdh155122 iptype = ZS_SHARED;
42743448Sdh155122 } else if (strcmp(prop_id, "exclusive") == 0) {
42753448Sdh155122 iptype = ZS_EXCLUSIVE;
42763448Sdh155122 } else {
42773448Sdh155122 zerr(gettext("%s value must be '%s' or '%s'."),
42783448Sdh155122 pt_to_str(PT_IPTYPE), "shared", "exclusive");
42796215Sgjelinek saw_error = B_TRUE;
42803448Sdh155122 return;
42813448Sdh155122 }
42823448Sdh155122 if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
42836215Sgjelinek saw_error = B_TRUE;
42843448Sdh155122 return;
42853448Sdh155122 }
42863448Sdh155122 if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
42876215Sgjelinek zone_perror(zone, err, B_TRUE);
42883448Sdh155122 else
42896215Sgjelinek need_to_commit = B_TRUE;
42903448Sdh155122 return;
42913247Sgjelinek case RT_MAXLWPS:
42923247Sgjelinek set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
42933247Sgjelinek return;
429412725SMenno.Lageman@Sun.COM case RT_MAXPROCS:
429512725SMenno.Lageman@Sun.COM set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
429612725SMenno.Lageman@Sun.COM return;
42973247Sgjelinek case RT_MAXSHMMEM:
42983247Sgjelinek set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
42993247Sgjelinek return;
43003247Sgjelinek case RT_MAXSHMIDS:
43013247Sgjelinek set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
43023247Sgjelinek return;
43033247Sgjelinek case RT_MAXMSGIDS:
43043247Sgjelinek set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
43053247Sgjelinek return;
43063247Sgjelinek case RT_MAXSEMIDS:
43073247Sgjelinek set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
43083247Sgjelinek return;
43093247Sgjelinek case RT_SHARES:
43103247Sgjelinek set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
43113247Sgjelinek return;
43128662SJordan.Vaughan@Sun.com case RT_HOSTID:
43138662SJordan.Vaughan@Sun.com if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
43148662SJordan.Vaughan@Sun.com if (err == Z_TOO_BIG) {
43158662SJordan.Vaughan@Sun.com zerr(gettext("hostid string is too large: %s"),
43168662SJordan.Vaughan@Sun.com prop_id);
43178662SJordan.Vaughan@Sun.com saw_error = B_TRUE;
43188662SJordan.Vaughan@Sun.com } else {
43198662SJordan.Vaughan@Sun.com zone_perror(pt_to_str(prop_type), err, B_TRUE);
43208662SJordan.Vaughan@Sun.com }
43218662SJordan.Vaughan@Sun.com return;
43228662SJordan.Vaughan@Sun.com }
43238662SJordan.Vaughan@Sun.com need_to_commit = B_TRUE;
43248662SJordan.Vaughan@Sun.com return;
432512633Sjohn.levon@sun.com case RT_FS_ALLOWED:
432612633Sjohn.levon@sun.com if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
432712633Sjohn.levon@sun.com zone_perror(zone, err, B_TRUE);
432812633Sjohn.levon@sun.com else
432912633Sjohn.levon@sun.com need_to_commit = B_TRUE;
433012633Sjohn.levon@sun.com return;
43310Sstevel@tonic-gate case RT_FS:
43320Sstevel@tonic-gate switch (prop_type) {
43330Sstevel@tonic-gate case PT_DIR:
43340Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
43350Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_dir));
43360Sstevel@tonic-gate return;
43370Sstevel@tonic-gate case PT_SPECIAL:
43380Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_special,
43390Sstevel@tonic-gate prop_id,
43400Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_special));
43410Sstevel@tonic-gate return;
43420Sstevel@tonic-gate case PT_RAW:
43430Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_raw,
43440Sstevel@tonic-gate prop_id, sizeof (in_progress_fstab.zone_fs_raw));
43450Sstevel@tonic-gate return;
43460Sstevel@tonic-gate case PT_TYPE:
43470Sstevel@tonic-gate if (!valid_fs_type(prop_id)) {
43480Sstevel@tonic-gate zerr(gettext("\"%s\" is not a valid %s."),
43490Sstevel@tonic-gate prop_id, pt_to_str(PT_TYPE));
43506215Sgjelinek saw_error = B_TRUE;
43510Sstevel@tonic-gate return;
43520Sstevel@tonic-gate }
43530Sstevel@tonic-gate (void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
43540Sstevel@tonic-gate sizeof (in_progress_fstab.zone_fs_type));
43550Sstevel@tonic-gate return;
43560Sstevel@tonic-gate case PT_OPTIONS:
43570Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_SIMPLE &&
43580Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) {
43590Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected "
43600Sstevel@tonic-gate "here."), pvt_to_str(PROP_VAL_SIMPLE),
43610Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST));
43626215Sgjelinek saw_error = B_TRUE;
43630Sstevel@tonic-gate return;
43640Sstevel@tonic-gate }
43650Sstevel@tonic-gate zonecfg_free_fs_option_list(
43660Sstevel@tonic-gate in_progress_fstab.zone_fs_options);
43670Sstevel@tonic-gate in_progress_fstab.zone_fs_options = NULL;
43680Sstevel@tonic-gate if (!(pp->pv_type == PROP_VAL_LIST &&
43690Sstevel@tonic-gate pp->pv_list == NULL))
43700Sstevel@tonic-gate add_property(cmd);
43710Sstevel@tonic-gate return;
43720Sstevel@tonic-gate default:
43730Sstevel@tonic-gate break;
43740Sstevel@tonic-gate }
43756215Sgjelinek zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
43766215Sgjelinek long_usage(CMD_SET, B_TRUE);
43776215Sgjelinek usage(B_FALSE, HELP_PROPS);
43780Sstevel@tonic-gate return;
43790Sstevel@tonic-gate case RT_NET:
43800Sstevel@tonic-gate switch (prop_type) {
43810Sstevel@tonic-gate case PT_ADDRESS:
438212748SSowmini.Varadhan@oracle.COM case PT_ALLOWED_ADDRESS:
438312748SSowmini.Varadhan@oracle.COM if (validate_net_address_syntax(prop_id, B_FALSE)
438412748SSowmini.Varadhan@oracle.COM != Z_OK) {
43856215Sgjelinek saw_error = B_TRUE;
43860Sstevel@tonic-gate return;
43870Sstevel@tonic-gate }
438812748SSowmini.Varadhan@oracle.COM set_in_progress_nwiftab_address(prop_id, prop_type);
43890Sstevel@tonic-gate break;
43900Sstevel@tonic-gate case PT_PHYSICAL:
43910Sstevel@tonic-gate if (validate_net_physical_syntax(prop_id) != Z_OK) {
43926215Sgjelinek saw_error = B_TRUE;
43930Sstevel@tonic-gate return;
43940Sstevel@tonic-gate }
43950Sstevel@tonic-gate (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
43960Sstevel@tonic-gate prop_id,
43970Sstevel@tonic-gate sizeof (in_progress_nwiftab.zone_nwif_physical));
43980Sstevel@tonic-gate break;
43996076Sgfaden case PT_DEFROUTER:
440012748SSowmini.Varadhan@oracle.COM if (validate_net_address_syntax(prop_id, B_TRUE)
440112748SSowmini.Varadhan@oracle.COM != Z_OK) {
44026215Sgjelinek saw_error = B_TRUE;
44036076Sgfaden return;
44046076Sgfaden }
44056076Sgfaden (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
44066076Sgfaden prop_id,
44076076Sgfaden sizeof (in_progress_nwiftab.zone_nwif_defrouter));
44086076Sgfaden break;
44090Sstevel@tonic-gate default:
44100Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44116215Sgjelinek B_TRUE);
44126215Sgjelinek long_usage(CMD_SET, B_TRUE);
44136215Sgjelinek usage(B_FALSE, HELP_PROPS);
44140Sstevel@tonic-gate return;
44150Sstevel@tonic-gate }
44160Sstevel@tonic-gate return;
44170Sstevel@tonic-gate case RT_DEVICE:
44180Sstevel@tonic-gate switch (prop_type) {
44190Sstevel@tonic-gate case PT_MATCH:
44200Sstevel@tonic-gate (void) strlcpy(in_progress_devtab.zone_dev_match,
44210Sstevel@tonic-gate prop_id,
44220Sstevel@tonic-gate sizeof (in_progress_devtab.zone_dev_match));
44230Sstevel@tonic-gate break;
44240Sstevel@tonic-gate default:
44250Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44266215Sgjelinek B_TRUE);
44276215Sgjelinek long_usage(CMD_SET, B_TRUE);
44286215Sgjelinek usage(B_FALSE, HELP_PROPS);
44290Sstevel@tonic-gate return;
44300Sstevel@tonic-gate }
44310Sstevel@tonic-gate return;
44320Sstevel@tonic-gate case RT_RCTL:
44330Sstevel@tonic-gate switch (prop_type) {
44340Sstevel@tonic-gate case PT_NAME:
44350Sstevel@tonic-gate if (!zonecfg_valid_rctlname(prop_id)) {
44360Sstevel@tonic-gate zerr(gettext("'%s' is not a valid zone %s "
44370Sstevel@tonic-gate "name."), prop_id, rt_to_str(RT_RCTL));
44380Sstevel@tonic-gate return;
44390Sstevel@tonic-gate }
44400Sstevel@tonic-gate (void) strlcpy(in_progress_rctltab.zone_rctl_name,
44410Sstevel@tonic-gate prop_id,
44420Sstevel@tonic-gate sizeof (in_progress_rctltab.zone_rctl_name));
44430Sstevel@tonic-gate break;
44440Sstevel@tonic-gate case PT_VALUE:
44450Sstevel@tonic-gate if (pp->pv_type != PROP_VAL_COMPLEX &&
44460Sstevel@tonic-gate pp->pv_type != PROP_VAL_LIST) {
44470Sstevel@tonic-gate zerr(gettext("A %s or %s value was expected "
44480Sstevel@tonic-gate "here."), pvt_to_str(PROP_VAL_COMPLEX),
44490Sstevel@tonic-gate pvt_to_str(PROP_VAL_LIST));
44506215Sgjelinek saw_error = B_TRUE;
44510Sstevel@tonic-gate return;
44520Sstevel@tonic-gate }
44530Sstevel@tonic-gate zonecfg_free_rctl_value_list(
44540Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr);
44550Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr = NULL;
44560Sstevel@tonic-gate if (!(pp->pv_type == PROP_VAL_LIST &&
44570Sstevel@tonic-gate pp->pv_list == NULL))
44580Sstevel@tonic-gate add_property(cmd);
44590Sstevel@tonic-gate break;
44600Sstevel@tonic-gate default:
44610Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44626215Sgjelinek B_TRUE);
44636215Sgjelinek long_usage(CMD_SET, B_TRUE);
44646215Sgjelinek usage(B_FALSE, HELP_PROPS);
44650Sstevel@tonic-gate return;
44660Sstevel@tonic-gate }
44670Sstevel@tonic-gate return;
44680Sstevel@tonic-gate case RT_ATTR:
44690Sstevel@tonic-gate switch (prop_type) {
44700Sstevel@tonic-gate case PT_NAME:
44710Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_name,
44720Sstevel@tonic-gate prop_id,
44730Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_name));
44740Sstevel@tonic-gate break;
44750Sstevel@tonic-gate case PT_TYPE:
44760Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_type,
44770Sstevel@tonic-gate prop_id,
44780Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_type));
44790Sstevel@tonic-gate break;
44800Sstevel@tonic-gate case PT_VALUE:
44810Sstevel@tonic-gate (void) strlcpy(in_progress_attrtab.zone_attr_value,
44820Sstevel@tonic-gate prop_id,
44830Sstevel@tonic-gate sizeof (in_progress_attrtab.zone_attr_value));
44840Sstevel@tonic-gate break;
44850Sstevel@tonic-gate default:
44860Sstevel@tonic-gate zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
44876215Sgjelinek B_TRUE);
44886215Sgjelinek long_usage(CMD_SET, B_TRUE);
44896215Sgjelinek usage(B_FALSE, HELP_PROPS);
44900Sstevel@tonic-gate return;
44910Sstevel@tonic-gate }
44920Sstevel@tonic-gate return;
4493789Sahrens case RT_DATASET:
4494789Sahrens switch (prop_type) {
4495789Sahrens case PT_NAME:
4496789Sahrens (void) strlcpy(in_progress_dstab.zone_dataset_name,
4497789Sahrens prop_id,
4498789Sahrens sizeof (in_progress_dstab.zone_dataset_name));
4499789Sahrens return;
4500789Sahrens default:
4501789Sahrens break;
4502789Sahrens }
45036215Sgjelinek zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
45046215Sgjelinek long_usage(CMD_SET, B_TRUE);
45056215Sgjelinek usage(B_FALSE, HELP_PROPS);
4506789Sahrens return;
45073247Sgjelinek case RT_DCPU:
45083247Sgjelinek switch (prop_type) {
45093247Sgjelinek char *lowp, *highp;
45103247Sgjelinek
45113247Sgjelinek case PT_NCPUS:
45123247Sgjelinek lowp = prop_id;
45133247Sgjelinek if ((highp = strchr(prop_id, '-')) != NULL)
45143247Sgjelinek *highp++ = '\0';
45153247Sgjelinek else
45163247Sgjelinek highp = lowp;
45173247Sgjelinek
45183247Sgjelinek /* Make sure the input makes sense. */
45193247Sgjelinek if (!zonecfg_valid_ncpus(lowp, highp)) {
45203247Sgjelinek zerr(gettext("%s property is out of range."),
45213247Sgjelinek pt_to_str(PT_NCPUS));
45226215Sgjelinek saw_error = B_TRUE;
45233247Sgjelinek return;
45243247Sgjelinek }
45253247Sgjelinek
45263247Sgjelinek (void) strlcpy(
45273247Sgjelinek in_progress_psettab.zone_ncpu_min, lowp,
45283247Sgjelinek sizeof (in_progress_psettab.zone_ncpu_min));
45293247Sgjelinek (void) strlcpy(
45303247Sgjelinek in_progress_psettab.zone_ncpu_max, highp,
45313247Sgjelinek sizeof (in_progress_psettab.zone_ncpu_max));
45323247Sgjelinek return;
45333247Sgjelinek case PT_IMPORTANCE:
45343247Sgjelinek /* Make sure the value makes sense. */
45353247Sgjelinek if (!zonecfg_valid_importance(prop_id)) {
45363247Sgjelinek zerr(gettext("%s property is out of range."),
45373247Sgjelinek pt_to_str(PT_IMPORTANCE));
45386215Sgjelinek saw_error = B_TRUE;
45393247Sgjelinek return;
45403247Sgjelinek }
45413247Sgjelinek
45423247Sgjelinek (void) strlcpy(in_progress_psettab.zone_importance,
45433247Sgjelinek prop_id,
45443247Sgjelinek sizeof (in_progress_psettab.zone_importance));
45453247Sgjelinek return;
45463247Sgjelinek default:
45473247Sgjelinek break;
45483247Sgjelinek }
45496215Sgjelinek zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
45506215Sgjelinek long_usage(CMD_SET, B_TRUE);
45516215Sgjelinek usage(B_FALSE, HELP_PROPS);
45523247Sgjelinek return;
45533792Sakolb case RT_PCAP:
45543792Sakolb if (prop_type != PT_NCPUS) {
45553792Sakolb zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
45566215Sgjelinek B_TRUE);
45576215Sgjelinek long_usage(CMD_SET, B_TRUE);
45586215Sgjelinek usage(B_FALSE, HELP_PROPS);
45593792Sakolb return;
45603792Sakolb }
45613792Sakolb
45623792Sakolb /*
45633792Sakolb * We already checked that an rctl alias is allowed in
45643792Sakolb * the add_resource() function.
45653792Sakolb */
45663792Sakolb
45673792Sakolb if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
45683792Sakolb (int)(cap * 100) < 1) {
45693792Sakolb zerr(gettext("%s property is out of range."),
45703792Sakolb pt_to_str(PT_NCPUS));
45716215Sgjelinek saw_error = B_TRUE;
45723792Sakolb return;
45733792Sakolb }
45743792Sakolb
45753792Sakolb if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
45763792Sakolb (int)(cap * 100))) != Z_OK)
45776215Sgjelinek zone_perror(zone, err, B_TRUE);
45783792Sakolb else
45796215Sgjelinek need_to_commit = B_TRUE;
45803792Sakolb return;
45813247Sgjelinek case RT_MCAP:
45823247Sgjelinek switch (prop_type) {
45833247Sgjelinek case PT_PHYSICAL:
45843247Sgjelinek if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
45853247Sgjelinek zerr(gettext("A positive number with a "
45863247Sgjelinek "required scale suffix (K, M, G or T) was "
45873247Sgjelinek "expected here."));
45886215Sgjelinek saw_error = B_TRUE;
45893247Sgjelinek } else if (mem_cap < ONE_MB) {
45903247Sgjelinek zerr(gettext("%s value is too small. It must "
45913247Sgjelinek "be at least 1M."), pt_to_str(PT_PHYSICAL));
45926215Sgjelinek saw_error = B_TRUE;
45933247Sgjelinek } else {
45943247Sgjelinek snprintf(in_progress_mcaptab.zone_physmem_cap,
45953247Sgjelinek physmem_size, "%llu", mem_cap);
45963247Sgjelinek }
45973247Sgjelinek break;
45983247Sgjelinek case PT_SWAP:
45993247Sgjelinek /*
46003247Sgjelinek * We have to check if an rctl is allowed here since
46013247Sgjelinek * there might already be a rctl defined that blocks
46023247Sgjelinek * the alias.
46033247Sgjelinek */
46043247Sgjelinek if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
46053247Sgjelinek zone_perror(pt_to_str(PT_MAXSWAP),
46066215Sgjelinek Z_ALIAS_DISALLOW, B_FALSE);
46076215Sgjelinek saw_error = B_TRUE;
46083247Sgjelinek return;
46093247Sgjelinek }
46103247Sgjelinek
46113247Sgjelinek if (global_zone)
46123247Sgjelinek mem_limit = ONE_MB * 100;
46133247Sgjelinek else
46143247Sgjelinek mem_limit = ONE_MB * 50;
46153247Sgjelinek
46163247Sgjelinek if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
46173247Sgjelinek zerr(gettext("A positive number with a "
46183247Sgjelinek "required scale suffix (K, M, G or T) was "
46193247Sgjelinek "expected here."));
46206215Sgjelinek saw_error = B_TRUE;
46213247Sgjelinek } else if (mem_cap < mem_limit) {
46223247Sgjelinek char buf[128];
46233247Sgjelinek
46243247Sgjelinek (void) snprintf(buf, sizeof (buf), "%llu",
46253247Sgjelinek mem_limit);
46263247Sgjelinek bytes_to_units(buf, buf, sizeof (buf));
46273247Sgjelinek zerr(gettext("%s value is too small. It must "
46283247Sgjelinek "be at least %s."), pt_to_str(PT_SWAP),
46293247Sgjelinek buf);
46306215Sgjelinek saw_error = B_TRUE;
46313247Sgjelinek } else {
46323247Sgjelinek if ((err = zonecfg_set_aliased_rctl(handle,
46333247Sgjelinek ALIAS_MAXSWAP, mem_cap)) != Z_OK)
46346215Sgjelinek zone_perror(zone, err, B_TRUE);
46353247Sgjelinek else
46366215Sgjelinek need_to_commit = B_TRUE;
46373247Sgjelinek }
46383247Sgjelinek break;
46393247Sgjelinek case PT_LOCKED:
46403247Sgjelinek /*
46413247Sgjelinek * We have to check if an rctl is allowed here since
46423247Sgjelinek * there might already be a rctl defined that blocks
46433247Sgjelinek * the alias.
46443247Sgjelinek */
46453247Sgjelinek if (!zonecfg_aliased_rctl_ok(handle,
46463247Sgjelinek ALIAS_MAXLOCKEDMEM)) {
46473247Sgjelinek zone_perror(pt_to_str(PT_LOCKED),
46486215Sgjelinek Z_ALIAS_DISALLOW, B_FALSE);
46496215Sgjelinek saw_error = B_TRUE;
46503247Sgjelinek return;
46513247Sgjelinek }
46523247Sgjelinek
46533247Sgjelinek if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
46543247Sgjelinek zerr(gettext("A non-negative number with a "
46553247Sgjelinek "required scale suffix (K, M, G or T) was "
46563247Sgjelinek "expected\nhere."));
46576215Sgjelinek saw_error = B_TRUE;
46583247Sgjelinek } else {
46593247Sgjelinek if ((err = zonecfg_set_aliased_rctl(handle,
46603247Sgjelinek ALIAS_MAXLOCKEDMEM, mem_cap)) != Z_OK)
46616215Sgjelinek zone_perror(zone, err, B_TRUE);
46623247Sgjelinek else
46636215Sgjelinek need_to_commit = B_TRUE;
46643247Sgjelinek }
46653247Sgjelinek break;
46663247Sgjelinek default:
46673247Sgjelinek zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
46686215Sgjelinek B_TRUE);
46696215Sgjelinek long_usage(CMD_SET, B_TRUE);
46706215Sgjelinek usage(B_FALSE, HELP_PROPS);
46713247Sgjelinek return;
46723247Sgjelinek }
467312578SGlenn.Faden@Sun.COM return;
467412578SGlenn.Faden@Sun.COM case RT_ADMIN:
467512578SGlenn.Faden@Sun.COM switch (prop_type) {
467612578SGlenn.Faden@Sun.COM case PT_USER:
467712578SGlenn.Faden@Sun.COM (void) strlcpy(in_progress_admintab.zone_admin_user,
467812578SGlenn.Faden@Sun.COM prop_id,
467912578SGlenn.Faden@Sun.COM sizeof (in_progress_admintab.zone_admin_user));
468012578SGlenn.Faden@Sun.COM return;
468112578SGlenn.Faden@Sun.COM case PT_AUTHS:
468212578SGlenn.Faden@Sun.COM (void) strlcpy(in_progress_admintab.zone_admin_auths,
468312578SGlenn.Faden@Sun.COM prop_id,
468412578SGlenn.Faden@Sun.COM sizeof (in_progress_admintab.zone_admin_auths));
468512578SGlenn.Faden@Sun.COM return;
468612578SGlenn.Faden@Sun.COM default:
468712578SGlenn.Faden@Sun.COM zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
468812578SGlenn.Faden@Sun.COM B_TRUE);
468912578SGlenn.Faden@Sun.COM long_usage(CMD_SET, B_TRUE);
469012578SGlenn.Faden@Sun.COM usage(B_FALSE, HELP_PROPS);
469112578SGlenn.Faden@Sun.COM return;
469212578SGlenn.Faden@Sun.COM }
46930Sstevel@tonic-gate default:
46946215Sgjelinek zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
46956215Sgjelinek long_usage(CMD_SET, B_TRUE);
46966215Sgjelinek usage(B_FALSE, HELP_RESOURCES);
46970Sstevel@tonic-gate return;
46980Sstevel@tonic-gate }
46990Sstevel@tonic-gate }
47000Sstevel@tonic-gate
47010Sstevel@tonic-gate static void
output_prop(FILE * fp,int pnum,char * pval,boolean_t print_notspec)47026215Sgjelinek output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
47030Sstevel@tonic-gate {
47040Sstevel@tonic-gate char *qstr;
47050Sstevel@tonic-gate
47060Sstevel@tonic-gate if (*pval != '\0') {
47070Sstevel@tonic-gate qstr = quoteit(pval);
47083247Sgjelinek if (pnum == PT_SWAP || pnum == PT_LOCKED)
47093247Sgjelinek (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
47103247Sgjelinek qstr);
47113247Sgjelinek else
47123247Sgjelinek (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
47130Sstevel@tonic-gate free(qstr);
47140Sstevel@tonic-gate } else if (print_notspec)
4715565Sdp (void) fprintf(fp, gettext("\t%s not specified\n"),
4716565Sdp pt_to_str(pnum));
4717565Sdp }
4718565Sdp
4719565Sdp static void
info_zonename(zone_dochandle_t handle,FILE * fp)4720565Sdp info_zonename(zone_dochandle_t handle, FILE *fp)
4721565Sdp {
4722565Sdp char zonename[ZONENAME_MAX];
4723565Sdp
4724565Sdp if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
4725565Sdp (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
4726565Sdp zonename);
4727565Sdp else
4728565Sdp (void) fprintf(fp, gettext("%s not specified\n"),
4729565Sdp pt_to_str(PT_ZONENAME));
47300Sstevel@tonic-gate }
47310Sstevel@tonic-gate
47320Sstevel@tonic-gate static void
info_zonepath(zone_dochandle_t handle,FILE * fp)47330Sstevel@tonic-gate info_zonepath(zone_dochandle_t handle, FILE *fp)
47340Sstevel@tonic-gate {
47350Sstevel@tonic-gate char zonepath[MAXPATHLEN];
47360Sstevel@tonic-gate
47370Sstevel@tonic-gate if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
47380Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
47390Sstevel@tonic-gate zonepath);
4740565Sdp else {
4741565Sdp (void) fprintf(fp, gettext("%s not specified\n"),
4742565Sdp pt_to_str(PT_ZONEPATH));
4743565Sdp }
47440Sstevel@tonic-gate }
47450Sstevel@tonic-gate
47460Sstevel@tonic-gate static void
info_brand(zone_dochandle_t handle,FILE * fp)47472712Snn35248 info_brand(zone_dochandle_t handle, FILE *fp)
47482712Snn35248 {
47492712Snn35248 char brand[MAXNAMELEN];
47502712Snn35248
47512712Snn35248 if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
47522712Snn35248 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
47532712Snn35248 brand);
47542712Snn35248 else
47552712Snn35248 (void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
47562712Snn35248 gettext("not specified"));
47572712Snn35248 }
47582712Snn35248
47592712Snn35248 static void
info_autoboot(zone_dochandle_t handle,FILE * fp)47600Sstevel@tonic-gate info_autoboot(zone_dochandle_t handle, FILE *fp)
47610Sstevel@tonic-gate {
47620Sstevel@tonic-gate boolean_t autoboot;
47630Sstevel@tonic-gate int err;
47640Sstevel@tonic-gate
47650Sstevel@tonic-gate if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
47660Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
47670Sstevel@tonic-gate autoboot ? "true" : "false");
47680Sstevel@tonic-gate else
47696215Sgjelinek zone_perror(zone, err, B_TRUE);
47700Sstevel@tonic-gate }
47710Sstevel@tonic-gate
47720Sstevel@tonic-gate static void
info_pool(zone_dochandle_t handle,FILE * fp)47730Sstevel@tonic-gate info_pool(zone_dochandle_t handle, FILE *fp)
47740Sstevel@tonic-gate {
47750Sstevel@tonic-gate char pool[MAXNAMELEN];
47760Sstevel@tonic-gate int err;
47770Sstevel@tonic-gate
47780Sstevel@tonic-gate if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
47790Sstevel@tonic-gate (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
47800Sstevel@tonic-gate else
47816215Sgjelinek zone_perror(zone, err, B_TRUE);
47820Sstevel@tonic-gate }
47830Sstevel@tonic-gate
47840Sstevel@tonic-gate static void
info_limitpriv(zone_dochandle_t handle,FILE * fp)47851645Scomay info_limitpriv(zone_dochandle_t handle, FILE *fp)
47861645Scomay {
47871645Scomay char *limitpriv;
47881645Scomay int err;
47891645Scomay
47901645Scomay if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
47911645Scomay (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
47921645Scomay limitpriv);
47931645Scomay free(limitpriv);
47941645Scomay } else {
47956215Sgjelinek zone_perror(zone, err, B_TRUE);
47961645Scomay }
47971645Scomay }
47981645Scomay
47991645Scomay static void
info_bootargs(zone_dochandle_t handle,FILE * fp)48002267Sdp info_bootargs(zone_dochandle_t handle, FILE *fp)
48012267Sdp {
48022267Sdp char bootargs[BOOTARGS_MAX];
48032267Sdp int err;
48042267Sdp
48052267Sdp if ((err = zonecfg_get_bootargs(handle, bootargs,
48062267Sdp sizeof (bootargs))) == Z_OK) {
48072267Sdp (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
48082267Sdp bootargs);
48092267Sdp } else {
48106215Sgjelinek zone_perror(zone, err, B_TRUE);
48112267Sdp }
48122267Sdp }
48132267Sdp
48142267Sdp static void
info_sched(zone_dochandle_t handle,FILE * fp)48153247Sgjelinek info_sched(zone_dochandle_t handle, FILE *fp)
48163247Sgjelinek {
48173247Sgjelinek char sched[MAXNAMELEN];
48183247Sgjelinek int err;
48193247Sgjelinek
48203247Sgjelinek if ((err = zonecfg_get_sched_class(handle, sched, sizeof (sched)))
48213247Sgjelinek == Z_OK) {
48223247Sgjelinek (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_SCHED), sched);
48233247Sgjelinek } else {
48246215Sgjelinek zone_perror(zone, err, B_TRUE);
48253247Sgjelinek }
48263247Sgjelinek }
48273247Sgjelinek
48283247Sgjelinek static void
info_iptype(zone_dochandle_t handle,FILE * fp)48293448Sdh155122 info_iptype(zone_dochandle_t handle, FILE *fp)
48303448Sdh155122 {
48313448Sdh155122 zone_iptype_t iptype;
48323448Sdh155122 int err;
48333448Sdh155122
48343448Sdh155122 if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
48353448Sdh155122 switch (iptype) {
48363448Sdh155122 case ZS_SHARED:
48373448Sdh155122 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
48383448Sdh155122 "shared");
48393448Sdh155122 break;
48403448Sdh155122 case ZS_EXCLUSIVE:
48413448Sdh155122 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
48423448Sdh155122 "exclusive");
48433448Sdh155122 break;
48443448Sdh155122 }
48453448Sdh155122 } else {
48466215Sgjelinek zone_perror(zone, err, B_TRUE);
48473448Sdh155122 }
48483448Sdh155122 }
48493448Sdh155122
48503448Sdh155122 static void
info_hostid(zone_dochandle_t handle,FILE * fp)48518662SJordan.Vaughan@Sun.com info_hostid(zone_dochandle_t handle, FILE *fp)
48528662SJordan.Vaughan@Sun.com {
48538662SJordan.Vaughan@Sun.com char hostidp[HW_HOSTID_LEN];
485412633Sjohn.levon@sun.com int err;
485512633Sjohn.levon@sun.com
485612633Sjohn.levon@sun.com if ((err = zonecfg_get_hostid(handle, hostidp,
485712633Sjohn.levon@sun.com sizeof (hostidp))) == Z_OK) {
485812633Sjohn.levon@sun.com (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
485912633Sjohn.levon@sun.com } else if (err == Z_BAD_PROPERTY) {
486012633Sjohn.levon@sun.com (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
486112633Sjohn.levon@sun.com } else {
486212633Sjohn.levon@sun.com zone_perror(zone, err, B_TRUE);
486312633Sjohn.levon@sun.com }
486412633Sjohn.levon@sun.com }
486512633Sjohn.levon@sun.com
486612633Sjohn.levon@sun.com static void
info_fs_allowed(zone_dochandle_t handle,FILE * fp)486712633Sjohn.levon@sun.com info_fs_allowed(zone_dochandle_t handle, FILE *fp)
486812633Sjohn.levon@sun.com {
486912633Sjohn.levon@sun.com char fsallowedp[ZONE_FS_ALLOWED_MAX];
487012633Sjohn.levon@sun.com int err;
487112633Sjohn.levon@sun.com
487212633Sjohn.levon@sun.com if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
487312633Sjohn.levon@sun.com sizeof (fsallowedp))) == Z_OK) {
487412633Sjohn.levon@sun.com (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
487512633Sjohn.levon@sun.com fsallowedp);
487612633Sjohn.levon@sun.com } else if (err == Z_BAD_PROPERTY) {
487712633Sjohn.levon@sun.com (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
487812633Sjohn.levon@sun.com } else {
487912633Sjohn.levon@sun.com zone_perror(zone, err, B_TRUE);
488012633Sjohn.levon@sun.com }
48818662SJordan.Vaughan@Sun.com }
48828662SJordan.Vaughan@Sun.com
48838662SJordan.Vaughan@Sun.com static void
output_fs(FILE * fp,struct zone_fstab * fstab)48840Sstevel@tonic-gate output_fs(FILE *fp, struct zone_fstab *fstab)
48850Sstevel@tonic-gate {
48860Sstevel@tonic-gate zone_fsopt_t *this;
48870Sstevel@tonic-gate
48880Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
48890Sstevel@tonic-gate output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
48900Sstevel@tonic-gate output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
48910Sstevel@tonic-gate output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
48920Sstevel@tonic-gate output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
48930Sstevel@tonic-gate (void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
48940Sstevel@tonic-gate for (this = fstab->zone_fs_options; this != NULL;
48950Sstevel@tonic-gate this = this->zone_fsopt_next) {
48960Sstevel@tonic-gate if (strchr(this->zone_fsopt_opt, '='))
48970Sstevel@tonic-gate (void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
48980Sstevel@tonic-gate else
48990Sstevel@tonic-gate (void) fprintf(fp, "%s", this->zone_fsopt_opt);
49000Sstevel@tonic-gate if (this->zone_fsopt_next != NULL)
49010Sstevel@tonic-gate (void) fprintf(fp, ",");
49020Sstevel@tonic-gate }
49030Sstevel@tonic-gate (void) fprintf(fp, "]\n");
49040Sstevel@tonic-gate }
49050Sstevel@tonic-gate
49060Sstevel@tonic-gate static void
info_fs(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)49070Sstevel@tonic-gate info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
49080Sstevel@tonic-gate {
49090Sstevel@tonic-gate struct zone_fstab lookup, user;
49106215Sgjelinek boolean_t output = B_FALSE;
49110Sstevel@tonic-gate
49120Sstevel@tonic-gate if (zonecfg_setfsent(handle) != Z_OK)
49130Sstevel@tonic-gate return;
49140Sstevel@tonic-gate while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
49150Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) {
49160Sstevel@tonic-gate output_fs(fp, &lookup);
49170Sstevel@tonic-gate goto loopend;
49180Sstevel@tonic-gate }
49196215Sgjelinek if (fill_in_fstab(cmd, &user, B_TRUE) != Z_OK)
49200Sstevel@tonic-gate goto loopend;
49210Sstevel@tonic-gate if (strlen(user.zone_fs_dir) > 0 &&
49220Sstevel@tonic-gate strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
49230Sstevel@tonic-gate goto loopend; /* no match */
49240Sstevel@tonic-gate if (strlen(user.zone_fs_special) > 0 &&
49250Sstevel@tonic-gate strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
49260Sstevel@tonic-gate goto loopend; /* no match */
49270Sstevel@tonic-gate if (strlen(user.zone_fs_type) > 0 &&
49280Sstevel@tonic-gate strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
49290Sstevel@tonic-gate goto loopend; /* no match */
49300Sstevel@tonic-gate output_fs(fp, &lookup);
49316215Sgjelinek output = B_TRUE;
49320Sstevel@tonic-gate loopend:
49330Sstevel@tonic-gate zonecfg_free_fs_option_list(lookup.zone_fs_options);
49340Sstevel@tonic-gate }
49350Sstevel@tonic-gate (void) zonecfg_endfsent(handle);
49360Sstevel@tonic-gate /*
49370Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was
49380Sstevel@tonic-gate * nothing to output.
49390Sstevel@tonic-gate */
49400Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0)
49410Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"),
49420Sstevel@tonic-gate rt_to_str(RT_FS));
49430Sstevel@tonic-gate }
49440Sstevel@tonic-gate
49450Sstevel@tonic-gate static void
output_net(FILE * fp,struct zone_nwiftab * nwiftab)49460Sstevel@tonic-gate output_net(FILE *fp, struct zone_nwiftab *nwiftab)
49470Sstevel@tonic-gate {
49480Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
49490Sstevel@tonic-gate output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
495012748SSowmini.Varadhan@oracle.COM output_prop(fp, PT_ALLOWED_ADDRESS,
495112748SSowmini.Varadhan@oracle.COM nwiftab->zone_nwif_allowed_address, B_TRUE);
49520Sstevel@tonic-gate output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
49536076Sgfaden output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
49540Sstevel@tonic-gate }
49550Sstevel@tonic-gate
49560Sstevel@tonic-gate static void
info_net(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)49570Sstevel@tonic-gate info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
49580Sstevel@tonic-gate {
49590Sstevel@tonic-gate struct zone_nwiftab lookup, user;
49606215Sgjelinek boolean_t output = B_FALSE;
49610Sstevel@tonic-gate
49620Sstevel@tonic-gate if (zonecfg_setnwifent(handle) != Z_OK)
49630Sstevel@tonic-gate return;
49640Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
49650Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) {
49660Sstevel@tonic-gate output_net(fp, &lookup);
49670Sstevel@tonic-gate continue;
49680Sstevel@tonic-gate }
49696215Sgjelinek if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
49700Sstevel@tonic-gate continue;
49710Sstevel@tonic-gate if (strlen(user.zone_nwif_physical) > 0 &&
49720Sstevel@tonic-gate strcmp(user.zone_nwif_physical,
49730Sstevel@tonic-gate lookup.zone_nwif_physical) != 0)
49740Sstevel@tonic-gate continue; /* no match */
49753448Sdh155122 /* If present make sure it matches */
49760Sstevel@tonic-gate if (strlen(user.zone_nwif_address) > 0 &&
49770Sstevel@tonic-gate !zonecfg_same_net_address(user.zone_nwif_address,
49780Sstevel@tonic-gate lookup.zone_nwif_address))
49790Sstevel@tonic-gate continue; /* no match */
49800Sstevel@tonic-gate output_net(fp, &lookup);
49816215Sgjelinek output = B_TRUE;
49820Sstevel@tonic-gate }
49830Sstevel@tonic-gate (void) zonecfg_endnwifent(handle);
49840Sstevel@tonic-gate /*
49850Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was
49860Sstevel@tonic-gate * nothing to output.
49870Sstevel@tonic-gate */
49880Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0)
49890Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"),
49900Sstevel@tonic-gate rt_to_str(RT_NET));
49910Sstevel@tonic-gate }
49920Sstevel@tonic-gate
49930Sstevel@tonic-gate static void
output_dev(FILE * fp,struct zone_devtab * devtab)49940Sstevel@tonic-gate output_dev(FILE *fp, struct zone_devtab *devtab)
49950Sstevel@tonic-gate {
49963813Sdp (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
49970Sstevel@tonic-gate output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
49980Sstevel@tonic-gate }
49990Sstevel@tonic-gate
50000Sstevel@tonic-gate static void
info_dev(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50010Sstevel@tonic-gate info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50020Sstevel@tonic-gate {
50030Sstevel@tonic-gate struct zone_devtab lookup, user;
50046215Sgjelinek boolean_t output = B_FALSE;
50050Sstevel@tonic-gate
50060Sstevel@tonic-gate if (zonecfg_setdevent(handle) != Z_OK)
50070Sstevel@tonic-gate return;
50080Sstevel@tonic-gate while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
50090Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) {
50100Sstevel@tonic-gate output_dev(fp, &lookup);
50110Sstevel@tonic-gate continue;
50120Sstevel@tonic-gate }
50136215Sgjelinek if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
50140Sstevel@tonic-gate continue;
50150Sstevel@tonic-gate if (strlen(user.zone_dev_match) > 0 &&
50160Sstevel@tonic-gate strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
50170Sstevel@tonic-gate continue; /* no match */
50180Sstevel@tonic-gate output_dev(fp, &lookup);
50196215Sgjelinek output = B_TRUE;
50200Sstevel@tonic-gate }
50210Sstevel@tonic-gate (void) zonecfg_enddevent(handle);
50220Sstevel@tonic-gate /*
50230Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was
50240Sstevel@tonic-gate * nothing to output.
50250Sstevel@tonic-gate */
50260Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0)
50270Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"),
50280Sstevel@tonic-gate rt_to_str(RT_DEVICE));
50290Sstevel@tonic-gate }
50300Sstevel@tonic-gate
50310Sstevel@tonic-gate static void
output_rctl(FILE * fp,struct zone_rctltab * rctltab)50320Sstevel@tonic-gate output_rctl(FILE *fp, struct zone_rctltab *rctltab)
50330Sstevel@tonic-gate {
50340Sstevel@tonic-gate struct zone_rctlvaltab *valptr;
50350Sstevel@tonic-gate
50360Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
50370Sstevel@tonic-gate output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
50380Sstevel@tonic-gate for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
50390Sstevel@tonic-gate valptr = valptr->zone_rctlval_next) {
50400Sstevel@tonic-gate fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
50410Sstevel@tonic-gate pt_to_str(PT_VALUE),
50420Sstevel@tonic-gate pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
50430Sstevel@tonic-gate pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
50440Sstevel@tonic-gate pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
50450Sstevel@tonic-gate }
50460Sstevel@tonic-gate }
50470Sstevel@tonic-gate
50480Sstevel@tonic-gate static void
info_rctl(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50490Sstevel@tonic-gate info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50500Sstevel@tonic-gate {
50510Sstevel@tonic-gate struct zone_rctltab lookup, user;
50526215Sgjelinek boolean_t output = B_FALSE;
50530Sstevel@tonic-gate
50540Sstevel@tonic-gate if (zonecfg_setrctlent(handle) != Z_OK)
50550Sstevel@tonic-gate return;
50560Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
50570Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) {
50580Sstevel@tonic-gate output_rctl(fp, &lookup);
50596215Sgjelinek } else if (fill_in_rctltab(cmd, &user, B_TRUE) == Z_OK &&
50600Sstevel@tonic-gate (strlen(user.zone_rctl_name) == 0 ||
50610Sstevel@tonic-gate strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
50620Sstevel@tonic-gate output_rctl(fp, &lookup);
50636215Sgjelinek output = B_TRUE;
50640Sstevel@tonic-gate }
50650Sstevel@tonic-gate zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
50660Sstevel@tonic-gate }
50670Sstevel@tonic-gate (void) zonecfg_endrctlent(handle);
50680Sstevel@tonic-gate /*
50690Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was
50700Sstevel@tonic-gate * nothing to output.
50710Sstevel@tonic-gate */
50720Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0)
50730Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"),
50740Sstevel@tonic-gate rt_to_str(RT_RCTL));
50750Sstevel@tonic-gate }
50760Sstevel@tonic-gate
50770Sstevel@tonic-gate static void
output_attr(FILE * fp,struct zone_attrtab * attrtab)50780Sstevel@tonic-gate output_attr(FILE *fp, struct zone_attrtab *attrtab)
50790Sstevel@tonic-gate {
50800Sstevel@tonic-gate (void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
50810Sstevel@tonic-gate output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
50820Sstevel@tonic-gate output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
50830Sstevel@tonic-gate output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
50840Sstevel@tonic-gate }
50850Sstevel@tonic-gate
50860Sstevel@tonic-gate static void
info_attr(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)50870Sstevel@tonic-gate info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
50880Sstevel@tonic-gate {
50890Sstevel@tonic-gate struct zone_attrtab lookup, user;
50906215Sgjelinek boolean_t output = B_FALSE;
50910Sstevel@tonic-gate
50920Sstevel@tonic-gate if (zonecfg_setattrent(handle) != Z_OK)
50930Sstevel@tonic-gate return;
50940Sstevel@tonic-gate while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
50950Sstevel@tonic-gate if (cmd->cmd_prop_nv_pairs == 0) {
50960Sstevel@tonic-gate output_attr(fp, &lookup);
50970Sstevel@tonic-gate continue;
50980Sstevel@tonic-gate }
50996215Sgjelinek if (fill_in_attrtab(cmd, &user, B_TRUE) != Z_OK)
51000Sstevel@tonic-gate continue;
51010Sstevel@tonic-gate if (strlen(user.zone_attr_name) > 0 &&
51020Sstevel@tonic-gate strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
51030Sstevel@tonic-gate continue; /* no match */
51040Sstevel@tonic-gate if (strlen(user.zone_attr_type) > 0 &&
51050Sstevel@tonic-gate strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
51060Sstevel@tonic-gate continue; /* no match */
51070Sstevel@tonic-gate if (strlen(user.zone_attr_value) > 0 &&
51080Sstevel@tonic-gate strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
51090Sstevel@tonic-gate continue; /* no match */
51100Sstevel@tonic-gate output_attr(fp, &lookup);
51116215Sgjelinek output = B_TRUE;
51120Sstevel@tonic-gate }
51130Sstevel@tonic-gate (void) zonecfg_endattrent(handle);
51140Sstevel@tonic-gate /*
51150Sstevel@tonic-gate * If a property n/v pair was specified, warn the user if there was
51160Sstevel@tonic-gate * nothing to output.
51170Sstevel@tonic-gate */
51180Sstevel@tonic-gate if (!output && cmd->cmd_prop_nv_pairs > 0)
51190Sstevel@tonic-gate (void) printf(gettext("No such %s resource.\n"),
51200Sstevel@tonic-gate rt_to_str(RT_ATTR));
51210Sstevel@tonic-gate }
51220Sstevel@tonic-gate
5123789Sahrens static void
output_ds(FILE * fp,struct zone_dstab * dstab)5124789Sahrens output_ds(FILE *fp, struct zone_dstab *dstab)
5125789Sahrens {
5126789Sahrens (void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
5127789Sahrens output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
5128789Sahrens }
5129789Sahrens
5130789Sahrens static void
info_ds(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)5131789Sahrens info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5132789Sahrens {
5133789Sahrens struct zone_dstab lookup, user;
51346215Sgjelinek boolean_t output = B_FALSE;
5135789Sahrens
51363247Sgjelinek if (zonecfg_setdsent(handle) != Z_OK)
5137789Sahrens return;
5138789Sahrens while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
5139789Sahrens if (cmd->cmd_prop_nv_pairs == 0) {
5140789Sahrens output_ds(fp, &lookup);
5141789Sahrens continue;
5142789Sahrens }
51436215Sgjelinek if (fill_in_dstab(cmd, &user, B_TRUE) != Z_OK)
5144789Sahrens continue;
5145789Sahrens if (strlen(user.zone_dataset_name) > 0 &&
5146789Sahrens strcmp(user.zone_dataset_name,
5147789Sahrens lookup.zone_dataset_name) != 0)
5148789Sahrens continue; /* no match */
5149789Sahrens output_ds(fp, &lookup);
51506215Sgjelinek output = B_TRUE;
5151789Sahrens }
5152789Sahrens (void) zonecfg_enddsent(handle);
5153789Sahrens /*
5154789Sahrens * If a property n/v pair was specified, warn the user if there was
5155789Sahrens * nothing to output.
5156789Sahrens */
5157789Sahrens if (!output && cmd->cmd_prop_nv_pairs > 0)
5158789Sahrens (void) printf(gettext("No such %s resource.\n"),
5159789Sahrens rt_to_str(RT_DATASET));
5160789Sahrens }
5161789Sahrens
51623247Sgjelinek static void
output_pset(FILE * fp,struct zone_psettab * psettab)51633247Sgjelinek output_pset(FILE *fp, struct zone_psettab *psettab)
51643247Sgjelinek {
51653247Sgjelinek (void) fprintf(fp, "%s:\n", rt_to_str(RT_DCPU));
51663247Sgjelinek if (strcmp(psettab->zone_ncpu_min, psettab->zone_ncpu_max) == 0)
51673247Sgjelinek (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_NCPUS),
51683247Sgjelinek psettab->zone_ncpu_max);
51693247Sgjelinek else
51703247Sgjelinek (void) fprintf(fp, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS),
51713247Sgjelinek psettab->zone_ncpu_min, psettab->zone_ncpu_max);
51723247Sgjelinek if (psettab->zone_importance[0] != '\0')
51733247Sgjelinek (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE),
51743247Sgjelinek psettab->zone_importance);
51753247Sgjelinek }
51763247Sgjelinek
51773247Sgjelinek static void
info_pset(zone_dochandle_t handle,FILE * fp)51783247Sgjelinek info_pset(zone_dochandle_t handle, FILE *fp)
51793247Sgjelinek {
51803247Sgjelinek struct zone_psettab lookup;
51813247Sgjelinek
51823247Sgjelinek if (zonecfg_getpsetent(handle, &lookup) == Z_OK)
51833247Sgjelinek output_pset(fp, &lookup);
51843247Sgjelinek }
51853247Sgjelinek
51863247Sgjelinek static void
output_pcap(FILE * fp)51873792Sakolb output_pcap(FILE *fp)
51883792Sakolb {
51893792Sakolb uint64_t cap;
51903792Sakolb
51913792Sakolb if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &cap) == Z_OK) {
51923792Sakolb float scaled = (float)cap / 100;
51933792Sakolb (void) fprintf(fp, "%s:\n", rt_to_str(RT_PCAP));
51943792Sakolb (void) fprintf(fp, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS),
51953792Sakolb scaled);
51963792Sakolb }
51973792Sakolb }
51983792Sakolb
51993792Sakolb static void
info_pcap(FILE * fp)52003792Sakolb info_pcap(FILE *fp)
52013792Sakolb {
52023792Sakolb output_pcap(fp);
52033792Sakolb }
52043792Sakolb
52053792Sakolb
52063792Sakolb static void
info_aliased_rctl(zone_dochandle_t handle,FILE * fp,char * alias)52073247Sgjelinek info_aliased_rctl(zone_dochandle_t handle, FILE *fp, char *alias)
52083247Sgjelinek {
52093247Sgjelinek uint64_t limit;
52103247Sgjelinek
52113247Sgjelinek if (zonecfg_get_aliased_rctl(handle, alias, &limit) == Z_OK) {
52123247Sgjelinek /* convert memory based properties */
52133247Sgjelinek if (strcmp(alias, ALIAS_MAXSHMMEM) == 0) {
52143247Sgjelinek char buf[128];
52153247Sgjelinek
52163247Sgjelinek (void) snprintf(buf, sizeof (buf), "%llu", limit);
52173247Sgjelinek bytes_to_units(buf, buf, sizeof (buf));
52183247Sgjelinek (void) fprintf(fp, "[%s: %s]\n", alias, buf);
52193247Sgjelinek return;
52203247Sgjelinek }
52213247Sgjelinek
52223247Sgjelinek (void) fprintf(fp, "[%s: %llu]\n", alias, limit);
52233247Sgjelinek }
52243247Sgjelinek }
52253247Sgjelinek
52263247Sgjelinek static void
bytes_to_units(char * str,char * buf,int bufsize)52273247Sgjelinek bytes_to_units(char *str, char *buf, int bufsize)
52283247Sgjelinek {
52293247Sgjelinek unsigned long long num;
52303247Sgjelinek unsigned long long save = 0;
52313247Sgjelinek char *units = "BKMGT";
52323247Sgjelinek char *up = units;
52333247Sgjelinek
52343247Sgjelinek num = strtoll(str, NULL, 10);
52353247Sgjelinek
52363247Sgjelinek if (num < 1024) {
52373247Sgjelinek (void) snprintf(buf, bufsize, "%llu", num);
52383247Sgjelinek return;
52393247Sgjelinek }
52403247Sgjelinek
52413247Sgjelinek while ((num >= 1024) && (*up != 'T')) {
52423247Sgjelinek up++; /* next unit of measurement */
52433247Sgjelinek save = num;
52443247Sgjelinek num = (num + 512) >> 10;
52453247Sgjelinek }
52463247Sgjelinek
52473247Sgjelinek /* check if we should output a fraction. snprintf will round for us */
52483247Sgjelinek if (save % 1024 != 0 && ((save >> 10) < 10))
52493247Sgjelinek (void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
52503247Sgjelinek *up);
52513247Sgjelinek else
52523247Sgjelinek (void) snprintf(buf, bufsize, "%llu%c", num, *up);
52533247Sgjelinek }
52543247Sgjelinek
52553247Sgjelinek static void
output_mcap(FILE * fp,struct zone_mcaptab * mcaptab,int showswap,uint64_t maxswap,int showlocked,uint64_t maxlocked)52563247Sgjelinek output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
52573247Sgjelinek uint64_t maxswap, int showlocked, uint64_t maxlocked)
52583247Sgjelinek {
52593247Sgjelinek char buf[128];
52603247Sgjelinek
52613247Sgjelinek (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
52623247Sgjelinek if (mcaptab->zone_physmem_cap[0] != '\0') {
52633247Sgjelinek bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
52643247Sgjelinek output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
52653247Sgjelinek }
52663247Sgjelinek
52673247Sgjelinek if (showswap == Z_OK) {
52683247Sgjelinek (void) snprintf(buf, sizeof (buf), "%llu", maxswap);
52693247Sgjelinek bytes_to_units(buf, buf, sizeof (buf));
52703247Sgjelinek output_prop(fp, PT_SWAP, buf, B_TRUE);
52713247Sgjelinek }
52723247Sgjelinek
52733247Sgjelinek if (showlocked == Z_OK) {
52743247Sgjelinek (void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
52753247Sgjelinek bytes_to_units(buf, buf, sizeof (buf));
52763247Sgjelinek output_prop(fp, PT_LOCKED, buf, B_TRUE);
52773247Sgjelinek }
52783247Sgjelinek }
52793247Sgjelinek
52803247Sgjelinek static void
info_mcap(zone_dochandle_t handle,FILE * fp)52813247Sgjelinek info_mcap(zone_dochandle_t handle, FILE *fp)
52823247Sgjelinek {
52833247Sgjelinek int res1, res2, res3;
52843247Sgjelinek uint64_t swap_limit;
52853247Sgjelinek uint64_t locked_limit;
52863247Sgjelinek struct zone_mcaptab lookup;
52873247Sgjelinek
52883247Sgjelinek bzero(&lookup, sizeof (lookup));
52893247Sgjelinek res1 = zonecfg_getmcapent(handle, &lookup);
52903247Sgjelinek res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
52913247Sgjelinek res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
52923247Sgjelinek &locked_limit);
52933247Sgjelinek
52943247Sgjelinek if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
52953247Sgjelinek output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
52963247Sgjelinek }
52973247Sgjelinek
529812578SGlenn.Faden@Sun.COM static void
output_auth(FILE * fp,struct zone_admintab * admintab)529912578SGlenn.Faden@Sun.COM output_auth(FILE *fp, struct zone_admintab *admintab)
530012578SGlenn.Faden@Sun.COM {
530112578SGlenn.Faden@Sun.COM (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
530212578SGlenn.Faden@Sun.COM output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
530312578SGlenn.Faden@Sun.COM output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
530412578SGlenn.Faden@Sun.COM }
530512578SGlenn.Faden@Sun.COM
530612578SGlenn.Faden@Sun.COM static void
info_auth(zone_dochandle_t handle,FILE * fp,cmd_t * cmd)530712578SGlenn.Faden@Sun.COM info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
530812578SGlenn.Faden@Sun.COM {
530912578SGlenn.Faden@Sun.COM struct zone_admintab lookup, user;
531012578SGlenn.Faden@Sun.COM boolean_t output = B_FALSE;
531112578SGlenn.Faden@Sun.COM int err;
531212578SGlenn.Faden@Sun.COM
531312578SGlenn.Faden@Sun.COM if ((err = zonecfg_setadminent(handle)) != Z_OK) {
531412578SGlenn.Faden@Sun.COM zone_perror(zone, err, B_TRUE);
531512578SGlenn.Faden@Sun.COM return;
531612578SGlenn.Faden@Sun.COM }
531712578SGlenn.Faden@Sun.COM while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
531812578SGlenn.Faden@Sun.COM if (cmd->cmd_prop_nv_pairs == 0) {
531912578SGlenn.Faden@Sun.COM output_auth(fp, &lookup);
532012578SGlenn.Faden@Sun.COM continue;
532112578SGlenn.Faden@Sun.COM }
532212578SGlenn.Faden@Sun.COM if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
532312578SGlenn.Faden@Sun.COM continue;
532412578SGlenn.Faden@Sun.COM if (strlen(user.zone_admin_user) > 0 &&
532512578SGlenn.Faden@Sun.COM strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
532612578SGlenn.Faden@Sun.COM continue; /* no match */
532712578SGlenn.Faden@Sun.COM output_auth(fp, &lookup);
532812578SGlenn.Faden@Sun.COM output = B_TRUE;
532912578SGlenn.Faden@Sun.COM }
533012578SGlenn.Faden@Sun.COM (void) zonecfg_endadminent(handle);
533112578SGlenn.Faden@Sun.COM /*
533212578SGlenn.Faden@Sun.COM * If a property n/v pair was specified, warn the user if there was
533312578SGlenn.Faden@Sun.COM * nothing to output.
533412578SGlenn.Faden@Sun.COM */
533512578SGlenn.Faden@Sun.COM if (!output && cmd->cmd_prop_nv_pairs > 0)
533612578SGlenn.Faden@Sun.COM (void) printf(gettext("No such %s resource.\n"),
533712578SGlenn.Faden@Sun.COM rt_to_str(RT_ADMIN));
533812578SGlenn.Faden@Sun.COM }
533912578SGlenn.Faden@Sun.COM
53400Sstevel@tonic-gate void
info_func(cmd_t * cmd)53410Sstevel@tonic-gate info_func(cmd_t *cmd)
53420Sstevel@tonic-gate {
53430Sstevel@tonic-gate FILE *fp = stdout;
53446215Sgjelinek boolean_t need_to_close = B_FALSE;
5345*12761SSusan.Kamm-Worrell@Sun.COM char *pager, *space;
53463247Sgjelinek int type;
53473247Sgjelinek int res1, res2;
53483247Sgjelinek uint64_t swap_limit;
53493247Sgjelinek uint64_t locked_limit;
535011882SFrank.Batschulat@Sun.COM struct stat statbuf;
53510Sstevel@tonic-gate
53520Sstevel@tonic-gate assert(cmd != NULL);
53530Sstevel@tonic-gate
53546215Sgjelinek if (initialize(B_TRUE) != Z_OK)
53550Sstevel@tonic-gate return;
53560Sstevel@tonic-gate
53570Sstevel@tonic-gate /* don't page error output */
53580Sstevel@tonic-gate if (interactive_mode) {
53590Sstevel@tonic-gate if ((pager = getenv("PAGER")) == NULL)
53600Sstevel@tonic-gate pager = PAGER;
5361*12761SSusan.Kamm-Worrell@Sun.COM space = strchr(pager, ' ');
5362*12761SSusan.Kamm-Worrell@Sun.COM if (space)
5363*12761SSusan.Kamm-Worrell@Sun.COM *space = '\0';
536411882SFrank.Batschulat@Sun.COM if (stat(pager, &statbuf) == 0) {
5365*12761SSusan.Kamm-Worrell@Sun.COM if (space)
5366*12761SSusan.Kamm-Worrell@Sun.COM *space = ' ';
536711882SFrank.Batschulat@Sun.COM if ((fp = popen(pager, "w")) != NULL)
536811882SFrank.Batschulat@Sun.COM need_to_close = B_TRUE;
536911882SFrank.Batschulat@Sun.COM else
537011882SFrank.Batschulat@Sun.COM fp = stdout;
537111882SFrank.Batschulat@Sun.COM } else {
537211882SFrank.Batschulat@Sun.COM zerr(gettext("PAGER %s does not exist (%s)."),
537311882SFrank.Batschulat@Sun.COM pager, strerror(errno));
537411882SFrank.Batschulat@Sun.COM }
537511882SFrank.Batschulat@Sun.COM
53760Sstevel@tonic-gate setbuf(fp, NULL);
53770Sstevel@tonic-gate }
53780Sstevel@tonic-gate
53790Sstevel@tonic-gate if (!global_scope) {
53800Sstevel@tonic-gate switch (resource_scope) {
53810Sstevel@tonic-gate case RT_FS:
53820Sstevel@tonic-gate output_fs(fp, &in_progress_fstab);
53830Sstevel@tonic-gate break;
53840Sstevel@tonic-gate case RT_NET:
53850Sstevel@tonic-gate output_net(fp, &in_progress_nwiftab);
53860Sstevel@tonic-gate break;
53870Sstevel@tonic-gate case RT_DEVICE:
53880Sstevel@tonic-gate output_dev(fp, &in_progress_devtab);
53890Sstevel@tonic-gate break;
53900Sstevel@tonic-gate case RT_RCTL:
53910Sstevel@tonic-gate output_rctl(fp, &in_progress_rctltab);
53920Sstevel@tonic-gate break;
53930Sstevel@tonic-gate case RT_ATTR:
53940Sstevel@tonic-gate output_attr(fp, &in_progress_attrtab);
53950Sstevel@tonic-gate break;
5396789Sahrens case RT_DATASET:
5397789Sahrens output_ds(fp, &in_progress_dstab);
5398789Sahrens break;
53993247Sgjelinek case RT_DCPU:
54003247Sgjelinek output_pset(fp, &in_progress_psettab);
54013247Sgjelinek break;
54023792Sakolb case RT_PCAP:
54033792Sakolb output_pcap(fp);
54043792Sakolb break;
54053247Sgjelinek case RT_MCAP:
54063247Sgjelinek res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
54073247Sgjelinek &swap_limit);
54083247Sgjelinek res2 = zonecfg_get_aliased_rctl(handle,
54093247Sgjelinek ALIAS_MAXLOCKEDMEM, &locked_limit);
54103247Sgjelinek output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
54113247Sgjelinek res2, locked_limit);
54123247Sgjelinek break;
541312578SGlenn.Faden@Sun.COM case RT_ADMIN:
541412578SGlenn.Faden@Sun.COM output_auth(fp, &in_progress_admintab);
541512578SGlenn.Faden@Sun.COM break;
54163247Sgjelinek }
54173247Sgjelinek goto cleanup;
54183247Sgjelinek }
54193247Sgjelinek
54203247Sgjelinek type = cmd->cmd_res_type;
54213247Sgjelinek
54223247Sgjelinek if (gz_invalid_rt_property(type)) {
54233247Sgjelinek zerr(gettext("%s is not a valid property for the global zone."),
54243247Sgjelinek rt_to_str(type));
54253247Sgjelinek goto cleanup;
54263247Sgjelinek }
54273247Sgjelinek
54283247Sgjelinek if (gz_invalid_resource(type)) {
54293247Sgjelinek zerr(gettext("%s is not a valid resource for the global zone."),
54303247Sgjelinek rt_to_str(type));
54310Sstevel@tonic-gate goto cleanup;
54320Sstevel@tonic-gate }
54330Sstevel@tonic-gate
54340Sstevel@tonic-gate switch (cmd->cmd_res_type) {
54350Sstevel@tonic-gate case RT_UNKNOWN:
5436565Sdp info_zonename(handle, fp);
54373247Sgjelinek if (!global_zone) {
54383247Sgjelinek info_zonepath(handle, fp);
54393247Sgjelinek info_brand(handle, fp);
54403247Sgjelinek info_autoboot(handle, fp);
54413247Sgjelinek info_bootargs(handle, fp);
54423247Sgjelinek }
54430Sstevel@tonic-gate info_pool(handle, fp);
54443247Sgjelinek if (!global_zone) {
54453247Sgjelinek info_limitpriv(handle, fp);
54463247Sgjelinek info_sched(handle, fp);
54473448Sdh155122 info_iptype(handle, fp);
54488662SJordan.Vaughan@Sun.com info_hostid(handle, fp);
544912633Sjohn.levon@sun.com info_fs_allowed(handle, fp);
54503247Sgjelinek }
54513247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
545212725SMenno.Lageman@Sun.COM info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
54533247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
54543247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
54553247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
54563247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
54573247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_SHARES);
54583247Sgjelinek if (!global_zone) {
54593247Sgjelinek info_fs(handle, fp, cmd);
54603247Sgjelinek info_net(handle, fp, cmd);
54613247Sgjelinek info_dev(handle, fp, cmd);
54623247Sgjelinek }
54633247Sgjelinek info_pset(handle, fp);
54643792Sakolb info_pcap(fp);
54653247Sgjelinek info_mcap(handle, fp);
54663247Sgjelinek if (!global_zone) {
54673247Sgjelinek info_attr(handle, fp, cmd);
54683247Sgjelinek info_ds(handle, fp, cmd);
546912578SGlenn.Faden@Sun.COM info_auth(handle, fp, cmd);
54703247Sgjelinek }
54710Sstevel@tonic-gate info_rctl(handle, fp, cmd);
54720Sstevel@tonic-gate break;
5473565Sdp case RT_ZONENAME:
5474565Sdp info_zonename(handle, fp);
5475565Sdp break;
54760Sstevel@tonic-gate case RT_ZONEPATH:
54770Sstevel@tonic-gate info_zonepath(handle, fp);
54780Sstevel@tonic-gate break;
54792712Snn35248 case RT_BRAND:
54802712Snn35248 info_brand(handle, fp);
54812712Snn35248 break;
54820Sstevel@tonic-gate case RT_AUTOBOOT:
54830Sstevel@tonic-gate info_autoboot(handle, fp);
54840Sstevel@tonic-gate break;
54850Sstevel@tonic-gate case RT_POOL:
54860Sstevel@tonic-gate info_pool(handle, fp);
54870Sstevel@tonic-gate break;
54881645Scomay case RT_LIMITPRIV:
54891645Scomay info_limitpriv(handle, fp);
54901645Scomay break;
54912267Sdp case RT_BOOTARGS:
54922267Sdp info_bootargs(handle, fp);
54932267Sdp break;
54943247Sgjelinek case RT_SCHED:
54953247Sgjelinek info_sched(handle, fp);
54963247Sgjelinek break;
54973448Sdh155122 case RT_IPTYPE:
54983448Sdh155122 info_iptype(handle, fp);
54993448Sdh155122 break;
55003247Sgjelinek case RT_MAXLWPS:
55013247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
55023247Sgjelinek break;
550312725SMenno.Lageman@Sun.COM case RT_MAXPROCS:
550412725SMenno.Lageman@Sun.COM info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
550512725SMenno.Lageman@Sun.COM break;
55063247Sgjelinek case RT_MAXSHMMEM:
55073247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
55083247Sgjelinek break;
55093247Sgjelinek case RT_MAXSHMIDS:
55103247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
55113247Sgjelinek break;
55123247Sgjelinek case RT_MAXMSGIDS:
55133247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
55143247Sgjelinek break;
55153247Sgjelinek case RT_MAXSEMIDS:
55163247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
55173247Sgjelinek break;
55183247Sgjelinek case RT_SHARES:
55193247Sgjelinek info_aliased_rctl(handle, fp, ALIAS_SHARES);
55203247Sgjelinek break;
55210Sstevel@tonic-gate case RT_FS:
55220Sstevel@tonic-gate info_fs(handle, fp, cmd);
55230Sstevel@tonic-gate break;
55240Sstevel@tonic-gate case RT_NET:
55250Sstevel@tonic-gate info_net(handle, fp, cmd);
55260Sstevel@tonic-gate break;
55270Sstevel@tonic-gate case RT_DEVICE:
55280Sstevel@tonic-gate info_dev(handle, fp, cmd);
55290Sstevel@tonic-gate break;
55300Sstevel@tonic-gate case RT_RCTL:
55310Sstevel@tonic-gate info_rctl(handle, fp, cmd);
55320Sstevel@tonic-gate break;
55330Sstevel@tonic-gate case RT_ATTR:
55340Sstevel@tonic-gate info_attr(handle, fp, cmd);
55350Sstevel@tonic-gate break;
5536789Sahrens case RT_DATASET:
5537789Sahrens info_ds(handle, fp, cmd);
5538789Sahrens break;
55393247Sgjelinek case RT_DCPU:
55403247Sgjelinek info_pset(handle, fp);
55413247Sgjelinek break;
55423792Sakolb case RT_PCAP:
55433792Sakolb info_pcap(fp);
55443792Sakolb break;
55453247Sgjelinek case RT_MCAP:
55463247Sgjelinek info_mcap(handle, fp);
55473247Sgjelinek break;
55488662SJordan.Vaughan@Sun.com case RT_HOSTID:
55498662SJordan.Vaughan@Sun.com info_hostid(handle, fp);
55508662SJordan.Vaughan@Sun.com break;
555112578SGlenn.Faden@Sun.COM case RT_ADMIN:
555212578SGlenn.Faden@Sun.COM info_auth(handle, fp, cmd);
555312578SGlenn.Faden@Sun.COM break;
555412633Sjohn.levon@sun.com case RT_FS_ALLOWED:
555512633Sjohn.levon@sun.com info_fs_allowed(handle, fp);
555612633Sjohn.levon@sun.com break;
55570Sstevel@tonic-gate default:
55580Sstevel@tonic-gate zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
55596215Sgjelinek B_TRUE);
55600Sstevel@tonic-gate }
55610Sstevel@tonic-gate
55620Sstevel@tonic-gate cleanup:
55630Sstevel@tonic-gate if (need_to_close)
55640Sstevel@tonic-gate (void) pclose(fp);
55650Sstevel@tonic-gate }
55660Sstevel@tonic-gate
5567565Sdp /*
5568565Sdp * Helper function for verify-- checks that a required string property
5569565Sdp * exists.
5570565Sdp */
5571565Sdp static void
check_reqd_prop(char * attr,int rt,int pt,int * ret_val)5572565Sdp check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
55730Sstevel@tonic-gate {
5574565Sdp if (strlen(attr) == 0) {
5575565Sdp zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5576565Sdp pt_to_str(pt));
55776215Sgjelinek saw_error = B_TRUE;
5578565Sdp if (*ret_val == Z_OK)
5579565Sdp *ret_val = Z_REQD_PROPERTY_MISSING;
55800Sstevel@tonic-gate }
55810Sstevel@tonic-gate }
55820Sstevel@tonic-gate
55832712Snn35248 static int
do_subproc(char * cmdbuf)55842712Snn35248 do_subproc(char *cmdbuf)
55852712Snn35248 {
55862712Snn35248 char inbuf[MAX_CMD_LEN];
55872712Snn35248 FILE *file;
55882712Snn35248 int status;
55892712Snn35248
55902712Snn35248 file = popen(cmdbuf, "r");
55912712Snn35248 if (file == NULL) {
55922712Snn35248 zerr(gettext("Could not launch: %s"), cmdbuf);
55932712Snn35248 return (-1);
55942712Snn35248 }
55952712Snn35248
55962712Snn35248 while (fgets(inbuf, sizeof (inbuf), file) != NULL)
55972712Snn35248 fprintf(stderr, "%s", inbuf);
55982712Snn35248 status = pclose(file);
55992712Snn35248
56002712Snn35248 if (WIFSIGNALED(status)) {
56012712Snn35248 zerr(gettext("%s unexpectedly terminated due to signal %d"),
56022712Snn35248 cmdbuf, WTERMSIG(status));
56032712Snn35248 return (-1);
56042712Snn35248 }
56052712Snn35248 assert(WIFEXITED(status));
56062712Snn35248 return (WEXITSTATUS(status));
56072712Snn35248 }
56082712Snn35248
56092712Snn35248 static int
brand_verify(zone_dochandle_t handle)56102712Snn35248 brand_verify(zone_dochandle_t handle)
56112712Snn35248 {
56122814Snn35248 char xml_file[32];
56132712Snn35248 char cmdbuf[MAX_CMD_LEN];
56142727Sedp brand_handle_t bh;
56152712Snn35248 char brand[MAXNAMELEN];
56162712Snn35248 int err;
56172712Snn35248
56182712Snn35248 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
56192712Snn35248 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
56202712Snn35248 return (Z_INVALID_DOCUMENT);
56212712Snn35248 }
56222727Sedp if ((bh = brand_open(brand)) == NULL) {
56232712Snn35248 zerr("%s: %s\n", zone, gettext("unknown brand."));
56242712Snn35248 return (Z_INVALID_DOCUMENT);
56252712Snn35248 }
56262712Snn35248
56272712Snn35248 /*
56282712Snn35248 * Fetch the verify command, if any, from the brand configuration
56292712Snn35248 * and build the command line to execute it.
56302712Snn35248 */
56312712Snn35248 strcpy(cmdbuf, EXEC_PREFIX);
56322727Sedp err = brand_get_verify_cfg(bh, cmdbuf + EXEC_LEN,
56332712Snn35248 sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
56342727Sedp brand_close(bh);
56352712Snn35248 if (err != Z_OK) {
56362712Snn35248 zerr("%s: %s\n", zone,
56372712Snn35248 gettext("could not get brand verification command"));
56382712Snn35248 return (Z_INVALID_DOCUMENT);
56392712Snn35248 }
56402712Snn35248
56412712Snn35248 /*
56422712Snn35248 * If the brand doesn't provide a verification routine, we just
56432712Snn35248 * return success.
56442712Snn35248 */
56452712Snn35248 if (strlen(cmdbuf) == EXEC_LEN)
56462712Snn35248 return (Z_OK);
56472712Snn35248
56482712Snn35248 /*
56492712Snn35248 * Dump the current config information for this zone to a file.
56502712Snn35248 */
56512814Snn35248 strcpy(xml_file, "/tmp/zonecfg_verify.XXXXXX");
56522712Snn35248 if (mkstemp(xml_file) == NULL)
56532712Snn35248 return (Z_TEMP_FILE);
56542712Snn35248 if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
56552712Snn35248 (void) unlink(xml_file);
56562712Snn35248 return (err);
56572712Snn35248 }
56582712Snn35248
56592712Snn35248 /*
56602712Snn35248 * Execute the verification command.
56612712Snn35248 */
56622712Snn35248 if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
56632712Snn35248 (strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
56642712Snn35248 err = Z_BRAND_ERROR;
56652712Snn35248 } else {
56662712Snn35248 err = do_subproc(cmdbuf);
56672712Snn35248 }
56682712Snn35248
56692712Snn35248 (void) unlink(xml_file);
56702712Snn35248 return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
56712712Snn35248 }
56722712Snn35248
56730Sstevel@tonic-gate /*
567412748SSowmini.Varadhan@oracle.COM * Track the network interfaces listed in zonecfg(1m) in a linked list
567512748SSowmini.Varadhan@oracle.COM * so that we can later check that defrouter is specified for an exclusive IP
567612748SSowmini.Varadhan@oracle.COM * zone if and only if at least one allowed-address has been specified.
567712748SSowmini.Varadhan@oracle.COM */
567812748SSowmini.Varadhan@oracle.COM static boolean_t
add_nwif(struct zone_nwiftab * nwif)567912748SSowmini.Varadhan@oracle.COM add_nwif(struct zone_nwiftab *nwif)
568012748SSowmini.Varadhan@oracle.COM {
568112748SSowmini.Varadhan@oracle.COM struct xif *tmp;
568212748SSowmini.Varadhan@oracle.COM
568312748SSowmini.Varadhan@oracle.COM for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
568412748SSowmini.Varadhan@oracle.COM if (strcmp(tmp->xif_name, nwif->zone_nwif_physical) == 0) {
568512748SSowmini.Varadhan@oracle.COM if (strlen(nwif->zone_nwif_allowed_address) > 0)
568612748SSowmini.Varadhan@oracle.COM tmp->xif_has_address = B_TRUE;
568712748SSowmini.Varadhan@oracle.COM if (strlen(nwif->zone_nwif_defrouter) > 0)
568812748SSowmini.Varadhan@oracle.COM tmp->xif_has_defrouter = B_TRUE;
568912748SSowmini.Varadhan@oracle.COM return (B_TRUE);
569012748SSowmini.Varadhan@oracle.COM }
569112748SSowmini.Varadhan@oracle.COM }
569212748SSowmini.Varadhan@oracle.COM
569312748SSowmini.Varadhan@oracle.COM tmp = malloc(sizeof (*tmp));
569412748SSowmini.Varadhan@oracle.COM if (tmp == NULL) {
569512748SSowmini.Varadhan@oracle.COM zerr(gettext("memory allocation failed for %s"),
569612748SSowmini.Varadhan@oracle.COM nwif->zone_nwif_physical);
569712748SSowmini.Varadhan@oracle.COM return (B_FALSE);
569812748SSowmini.Varadhan@oracle.COM }
569912748SSowmini.Varadhan@oracle.COM strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
570012748SSowmini.Varadhan@oracle.COM sizeof (tmp->xif_name));
570112748SSowmini.Varadhan@oracle.COM tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
570212748SSowmini.Varadhan@oracle.COM tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
570312748SSowmini.Varadhan@oracle.COM tmp->xif_next = xif;
570412748SSowmini.Varadhan@oracle.COM xif = tmp;
570512748SSowmini.Varadhan@oracle.COM return (B_TRUE);
570612748SSowmini.Varadhan@oracle.COM }
570712748SSowmini.Varadhan@oracle.COM
570812748SSowmini.Varadhan@oracle.COM /*
57090Sstevel@tonic-gate * See the DTD for which attributes are required for which resources.
57100Sstevel@tonic-gate *
57110Sstevel@tonic-gate * This function can be called by commit_func(), which needs to save things,
57120Sstevel@tonic-gate * in addition to the general call from parse_and_run(), which doesn't need
57130Sstevel@tonic-gate * things saved. Since the parameters are standardized, we distinguish by
57140Sstevel@tonic-gate * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
57150Sstevel@tonic-gate * that a save is needed.
57160Sstevel@tonic-gate */
57170Sstevel@tonic-gate void
verify_func(cmd_t * cmd)57180Sstevel@tonic-gate verify_func(cmd_t *cmd)
57190Sstevel@tonic-gate {
57200Sstevel@tonic-gate struct zone_nwiftab nwiftab;
57210Sstevel@tonic-gate struct zone_fstab fstab;
57220Sstevel@tonic-gate struct zone_attrtab attrtab;
57230Sstevel@tonic-gate struct zone_rctltab rctltab;
5724789Sahrens struct zone_dstab dstab;
57253247Sgjelinek struct zone_psettab psettab;
572612578SGlenn.Faden@Sun.COM struct zone_admintab admintab;
57270Sstevel@tonic-gate char zonepath[MAXPATHLEN];
57283247Sgjelinek char sched[MAXNAMELEN];
57292712Snn35248 char brand[MAXNAMELEN];
57308662SJordan.Vaughan@Sun.com char hostidp[HW_HOSTID_LEN];
573112633Sjohn.levon@sun.com char fsallowedp[ZONE_FS_ALLOWED_MAX];
57320Sstevel@tonic-gate int err, ret_val = Z_OK, arg;
57333792Sakolb int pset_res;
57346215Sgjelinek boolean_t save = B_FALSE;
57356215Sgjelinek boolean_t arg_err = B_FALSE;
57363448Sdh155122 zone_iptype_t iptype;
57373247Sgjelinek boolean_t has_cpu_shares = B_FALSE;
57383792Sakolb boolean_t has_cpu_cap = B_FALSE;
573912748SSowmini.Varadhan@oracle.COM struct xif *tmp;
57400Sstevel@tonic-gate
57410Sstevel@tonic-gate optind = 0;
57423691Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
57430Sstevel@tonic-gate switch (arg) {
57440Sstevel@tonic-gate case '?':
57450Sstevel@tonic-gate longer_usage(CMD_VERIFY);
57466215Sgjelinek arg_err = B_TRUE;
57473691Sgjelinek break;
57480Sstevel@tonic-gate default:
57490Sstevel@tonic-gate short_usage(CMD_VERIFY);
57506215Sgjelinek arg_err = B_TRUE;
57513691Sgjelinek break;
57523691Sgjelinek }
57533691Sgjelinek }
57543691Sgjelinek if (arg_err)
57553691Sgjelinek return;
57563691Sgjelinek
57570Sstevel@tonic-gate if (optind > cmd->cmd_argc) {
57580Sstevel@tonic-gate short_usage(CMD_VERIFY);
57590Sstevel@tonic-gate return;
57600Sstevel@tonic-gate }
57610Sstevel@tonic-gate
57620Sstevel@tonic-gate if (zone_is_read_only(CMD_VERIFY))
57630Sstevel@tonic-gate return;
57640Sstevel@tonic-gate
57650Sstevel@tonic-gate assert(cmd != NULL);
57660Sstevel@tonic-gate
57670Sstevel@tonic-gate if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
57686215Sgjelinek save = B_TRUE;
57696215Sgjelinek if (initialize(B_TRUE) != Z_OK)
57700Sstevel@tonic-gate return;
57710Sstevel@tonic-gate
57723247Sgjelinek if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK &&
57733247Sgjelinek !global_zone) {
5774565Sdp zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
57750Sstevel@tonic-gate ret_val = Z_REQD_RESOURCE_MISSING;
57766215Sgjelinek saw_error = B_TRUE;
57770Sstevel@tonic-gate }
57783247Sgjelinek if (strlen(zonepath) == 0 && !global_zone) {
5779565Sdp zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
57800Sstevel@tonic-gate ret_val = Z_REQD_RESOURCE_MISSING;
57816215Sgjelinek saw_error = B_TRUE;
57820Sstevel@tonic-gate }
57830Sstevel@tonic-gate
57842712Snn35248 if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
57856215Sgjelinek zone_perror(zone, err, B_TRUE);
57862712Snn35248 return;
57872712Snn35248 }
57889954SEdward.Pilatowicz@Sun.COM if ((err = brand_verify(handle)) != Z_OK) {
57899954SEdward.Pilatowicz@Sun.COM zone_perror(zone, err, B_TRUE);
57909954SEdward.Pilatowicz@Sun.COM return;
57912712Snn35248 }
57922712Snn35248
57933448Sdh155122 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
57943448Sdh155122 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
57953448Sdh155122 ret_val = Z_REQD_RESOURCE_MISSING;
57966215Sgjelinek saw_error = B_TRUE;
57973448Sdh155122 }
57980Sstevel@tonic-gate
579912633Sjohn.levon@sun.com if (zonecfg_get_hostid(handle, hostidp,
580012633Sjohn.levon@sun.com sizeof (hostidp)) == Z_INVALID_PROPERTY) {
580112633Sjohn.levon@sun.com zerr(gettext("%s: invalid hostid: %s"),
580212633Sjohn.levon@sun.com zone, hostidp);
580312633Sjohn.levon@sun.com return;
580412633Sjohn.levon@sun.com }
580512633Sjohn.levon@sun.com
580612633Sjohn.levon@sun.com if (zonecfg_get_fs_allowed(handle, fsallowedp,
580712633Sjohn.levon@sun.com sizeof (fsallowedp)) == Z_INVALID_PROPERTY) {
580812633Sjohn.levon@sun.com zerr(gettext("%s: invalid fs-allowed: %s"),
580912633Sjohn.levon@sun.com zone, fsallowedp);
58108662SJordan.Vaughan@Sun.com return;
58118662SJordan.Vaughan@Sun.com }
58128662SJordan.Vaughan@Sun.com
58130Sstevel@tonic-gate if ((err = zonecfg_setfsent(handle)) != Z_OK) {
58146215Sgjelinek zone_perror(zone, err, B_TRUE);
58150Sstevel@tonic-gate return;
58160Sstevel@tonic-gate }
58170Sstevel@tonic-gate while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
5818565Sdp check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
5819565Sdp check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
5820565Sdp &ret_val);
5821565Sdp check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
5822565Sdp
58230Sstevel@tonic-gate zonecfg_free_fs_option_list(fstab.zone_fs_options);
58240Sstevel@tonic-gate }
58250Sstevel@tonic-gate (void) zonecfg_endfsent(handle);
58260Sstevel@tonic-gate
58270Sstevel@tonic-gate if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
58286215Sgjelinek zone_perror(zone, err, B_TRUE);
58290Sstevel@tonic-gate return;
58300Sstevel@tonic-gate }
58310Sstevel@tonic-gate while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
58323448Sdh155122 /*
58333448Sdh155122 * physical is required in all cases.
58346076Sgfaden * A shared IP requires an address,
58356076Sgfaden * and may include a default router, while
58366076Sgfaden * an exclusive IP must have neither an address
58376076Sgfaden * nor a default router.
58388457SJordan.Vaughan@Sun.com * The physical interface name must be valid in all cases.
58393448Sdh155122 */
5840565Sdp check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
5841565Sdp PT_PHYSICAL, &ret_val);
58428457SJordan.Vaughan@Sun.com if (validate_net_physical_syntax(nwiftab.zone_nwif_physical) !=
58438457SJordan.Vaughan@Sun.com Z_OK) {
58448457SJordan.Vaughan@Sun.com saw_error = B_TRUE;
58458457SJordan.Vaughan@Sun.com if (ret_val == Z_OK)
58468457SJordan.Vaughan@Sun.com ret_val = Z_INVAL;
58478457SJordan.Vaughan@Sun.com }
58483448Sdh155122
58493448Sdh155122 switch (iptype) {
58503448Sdh155122 case ZS_SHARED:
58513448Sdh155122 check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
58523448Sdh155122 PT_ADDRESS, &ret_val);
585312748SSowmini.Varadhan@oracle.COM if (strlen(nwiftab.zone_nwif_allowed_address) > 0) {
585412748SSowmini.Varadhan@oracle.COM zerr(gettext("%s: %s cannot be specified "
585512748SSowmini.Varadhan@oracle.COM "for a shared IP type"),
585612748SSowmini.Varadhan@oracle.COM rt_to_str(RT_NET),
585712748SSowmini.Varadhan@oracle.COM pt_to_str(PT_ALLOWED_ADDRESS));
585812748SSowmini.Varadhan@oracle.COM saw_error = B_TRUE;
585912748SSowmini.Varadhan@oracle.COM if (ret_val == Z_OK)
586012748SSowmini.Varadhan@oracle.COM ret_val = Z_INVAL;
586112748SSowmini.Varadhan@oracle.COM }
58623448Sdh155122 break;
58633448Sdh155122 case ZS_EXCLUSIVE:
58643448Sdh155122 if (strlen(nwiftab.zone_nwif_address) > 0) {
58653448Sdh155122 zerr(gettext("%s: %s cannot be specified "
58663448Sdh155122 "for an exclusive IP type"),
58673448Sdh155122 rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
58686215Sgjelinek saw_error = B_TRUE;
58693448Sdh155122 if (ret_val == Z_OK)
58703448Sdh155122 ret_val = Z_INVAL;
587112748SSowmini.Varadhan@oracle.COM } else {
587212748SSowmini.Varadhan@oracle.COM if (!add_nwif(&nwiftab)) {
587312748SSowmini.Varadhan@oracle.COM saw_error = B_TRUE;
587412748SSowmini.Varadhan@oracle.COM if (ret_val == Z_OK)
587512748SSowmini.Varadhan@oracle.COM ret_val = Z_INVAL;
587612748SSowmini.Varadhan@oracle.COM }
58776076Sgfaden }
58783448Sdh155122 break;
58793448Sdh155122 }
58800Sstevel@tonic-gate }
588112748SSowmini.Varadhan@oracle.COM for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
588212748SSowmini.Varadhan@oracle.COM if (!tmp->xif_has_address && tmp->xif_has_defrouter) {
588312748SSowmini.Varadhan@oracle.COM zerr(gettext("%s: %s for %s cannot be specified "
588412748SSowmini.Varadhan@oracle.COM "without %s for an exclusive IP type"),
588512748SSowmini.Varadhan@oracle.COM rt_to_str(RT_NET), pt_to_str(PT_DEFROUTER),
588612748SSowmini.Varadhan@oracle.COM tmp->xif_name, pt_to_str(PT_ALLOWED_ADDRESS));
588712748SSowmini.Varadhan@oracle.COM saw_error = B_TRUE;
588812748SSowmini.Varadhan@oracle.COM ret_val = Z_INVAL;
588912748SSowmini.Varadhan@oracle.COM }
589012748SSowmini.Varadhan@oracle.COM }
589112748SSowmini.Varadhan@oracle.COM free(xif);
589212748SSowmini.Varadhan@oracle.COM xif = NULL;
58930Sstevel@tonic-gate (void) zonecfg_endnwifent(handle);
58940Sstevel@tonic-gate
58950Sstevel@tonic-gate if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
58966215Sgjelinek zone_perror(zone, err, B_TRUE);
58970Sstevel@tonic-gate return;
58980Sstevel@tonic-gate }
58990Sstevel@tonic-gate while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
5900565Sdp check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
5901565Sdp &ret_val);
5902565Sdp
59033247Sgjelinek if (strcmp(rctltab.zone_rctl_name, "zone.cpu-shares") == 0)
59043247Sgjelinek has_cpu_shares = B_TRUE;
59053247Sgjelinek
59063792Sakolb if (strcmp(rctltab.zone_rctl_name, "zone.cpu-cap") == 0)
59073792Sakolb has_cpu_cap = B_TRUE;
59083792Sakolb
59090Sstevel@tonic-gate if (rctltab.zone_rctl_valptr == NULL) {
59100Sstevel@tonic-gate zerr(gettext("%s: no %s specified"),
59110Sstevel@tonic-gate rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
59126215Sgjelinek saw_error = B_TRUE;
59130Sstevel@tonic-gate if (ret_val == Z_OK)
59140Sstevel@tonic-gate ret_val = Z_REQD_PROPERTY_MISSING;
59150Sstevel@tonic-gate } else {
59160Sstevel@tonic-gate zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
59170Sstevel@tonic-gate }
59180Sstevel@tonic-gate }
59190Sstevel@tonic-gate (void) zonecfg_endrctlent(handle);
59200Sstevel@tonic-gate
59213792Sakolb if ((pset_res = zonecfg_lookup_pset(handle, &psettab)) == Z_OK &&
59223792Sakolb has_cpu_shares) {
59233247Sgjelinek zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
59243247Sgjelinek rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
59256215Sgjelinek saw_error = B_TRUE;
59263247Sgjelinek if (ret_val == Z_OK)
59273247Sgjelinek ret_val = Z_INCOMPATIBLE;
59283247Sgjelinek }
59293247Sgjelinek
59303247Sgjelinek if (has_cpu_shares && zonecfg_get_sched_class(handle, sched,
59313247Sgjelinek sizeof (sched)) == Z_OK && strlen(sched) > 0 &&
59323247Sgjelinek strcmp(sched, "FSS") != 0) {
59333247Sgjelinek zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
59343247Sgjelinek "incompatible"),
59353247Sgjelinek rt_to_str(RT_RCTL), rt_to_str(RT_SCHED), sched);
59366215Sgjelinek saw_error = B_TRUE;
59373247Sgjelinek if (ret_val == Z_OK)
59383247Sgjelinek ret_val = Z_INCOMPATIBLE;
59393247Sgjelinek }
59403247Sgjelinek
59413792Sakolb if (pset_res == Z_OK && has_cpu_cap) {
59423792Sakolb zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
59433792Sakolb rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
59446215Sgjelinek saw_error = B_TRUE;
59453792Sakolb if (ret_val == Z_OK)
59463792Sakolb ret_val = Z_INCOMPATIBLE;
59473792Sakolb }
59483792Sakolb
59490Sstevel@tonic-gate if ((err = zonecfg_setattrent(handle)) != Z_OK) {
59506215Sgjelinek zone_perror(zone, err, B_TRUE);
59510Sstevel@tonic-gate return;
59520Sstevel@tonic-gate }
59530Sstevel@tonic-gate while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
5954565Sdp check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
5955565Sdp &ret_val);
5956565Sdp check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
5957565Sdp &ret_val);
5958565Sdp check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
5959565Sdp &ret_val);
59600Sstevel@tonic-gate }
59610Sstevel@tonic-gate (void) zonecfg_endattrent(handle);
59620Sstevel@tonic-gate
5963789Sahrens if ((err = zonecfg_setdsent(handle)) != Z_OK) {
59646215Sgjelinek zone_perror(zone, err, B_TRUE);
5965789Sahrens return;
5966789Sahrens }
5967789Sahrens while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
5968789Sahrens if (strlen(dstab.zone_dataset_name) == 0) {
5969789Sahrens zerr("%s: %s %s", rt_to_str(RT_DATASET),
5970789Sahrens pt_to_str(PT_NAME), gettext("not specified"));
59716215Sgjelinek saw_error = B_TRUE;
5972789Sahrens if (ret_val == Z_OK)
5973789Sahrens ret_val = Z_REQD_PROPERTY_MISSING;
5974789Sahrens } else if (!zfs_name_valid(dstab.zone_dataset_name,
5975789Sahrens ZFS_TYPE_FILESYSTEM)) {
5976789Sahrens zerr("%s: %s %s", rt_to_str(RT_DATASET),
5977789Sahrens pt_to_str(PT_NAME), gettext("invalid"));
59786215Sgjelinek saw_error = B_TRUE;
5979789Sahrens if (ret_val == Z_OK)
5980789Sahrens ret_val = Z_BAD_PROPERTY;
5981789Sahrens }
5982789Sahrens
5983789Sahrens }
5984789Sahrens (void) zonecfg_enddsent(handle);
5985789Sahrens
598612578SGlenn.Faden@Sun.COM if ((err = zonecfg_setadminent(handle)) != Z_OK) {
598712578SGlenn.Faden@Sun.COM zone_perror(zone, err, B_TRUE);
598812578SGlenn.Faden@Sun.COM return;
598912578SGlenn.Faden@Sun.COM }
599012578SGlenn.Faden@Sun.COM while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
599112578SGlenn.Faden@Sun.COM check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
599212578SGlenn.Faden@Sun.COM PT_USER, &ret_val);
599312578SGlenn.Faden@Sun.COM check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
599412578SGlenn.Faden@Sun.COM PT_AUTHS, &ret_val);
599512578SGlenn.Faden@Sun.COM if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
599612578SGlenn.Faden@Sun.COM == NULL)) {
599712578SGlenn.Faden@Sun.COM zerr(gettext("%s %s is not a valid username"),
599812578SGlenn.Faden@Sun.COM pt_to_str(PT_USER),
599912578SGlenn.Faden@Sun.COM admintab.zone_admin_user);
600012578SGlenn.Faden@Sun.COM ret_val = Z_BAD_PROPERTY;
600112578SGlenn.Faden@Sun.COM }
600212578SGlenn.Faden@Sun.COM if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
600312578SGlenn.Faden@Sun.COM admintab.zone_admin_auths, zone))) {
600412578SGlenn.Faden@Sun.COM ret_val = Z_BAD_PROPERTY;
600512578SGlenn.Faden@Sun.COM }
600612578SGlenn.Faden@Sun.COM }
600712578SGlenn.Faden@Sun.COM (void) zonecfg_endadminent(handle);
600812578SGlenn.Faden@Sun.COM
60090Sstevel@tonic-gate if (!global_scope) {
60100Sstevel@tonic-gate zerr(gettext("resource specification incomplete"));
60116215Sgjelinek saw_error = B_TRUE;
60120Sstevel@tonic-gate if (ret_val == Z_OK)
60130Sstevel@tonic-gate ret_val = Z_INSUFFICIENT_SPEC;
60140Sstevel@tonic-gate }
60150Sstevel@tonic-gate
60160Sstevel@tonic-gate if (save) {
6017565Sdp if (ret_val == Z_OK) {
6018565Sdp if ((ret_val = zonecfg_save(handle)) == Z_OK) {
60196215Sgjelinek need_to_commit = B_FALSE;
6020565Sdp (void) strlcpy(revert_zone, zone,
6021565Sdp sizeof (revert_zone));
6022565Sdp }
6023565Sdp } else {
6024565Sdp zerr(gettext("Zone %s failed to verify"), zone);
6025565Sdp }
60260Sstevel@tonic-gate }
60270Sstevel@tonic-gate if (ret_val != Z_OK)
60286215Sgjelinek zone_perror(zone, ret_val, B_TRUE);
60290Sstevel@tonic-gate }
60300Sstevel@tonic-gate
60310Sstevel@tonic-gate void
cancel_func(cmd_t * cmd)60320Sstevel@tonic-gate cancel_func(cmd_t *cmd)
60330Sstevel@tonic-gate {
60340Sstevel@tonic-gate int arg;
60356215Sgjelinek boolean_t arg_err = B_FALSE;
60360Sstevel@tonic-gate
60370Sstevel@tonic-gate assert(cmd != NULL);
60380Sstevel@tonic-gate
60390Sstevel@tonic-gate optind = 0;
60403691Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
60410Sstevel@tonic-gate switch (arg) {
60420Sstevel@tonic-gate case '?':
60430Sstevel@tonic-gate longer_usage(CMD_CANCEL);
60446215Sgjelinek arg_err = B_TRUE;
60453691Sgjelinek break;
60460Sstevel@tonic-gate default:
60470Sstevel@tonic-gate short_usage(CMD_CANCEL);
60486215Sgjelinek arg_err = B_TRUE;
60493691Sgjelinek break;
60503691Sgjelinek }
60513691Sgjelinek }
60523691Sgjelinek if (arg_err)
60533691Sgjelinek return;
60543691Sgjelinek
60550Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
60560Sstevel@tonic-gate short_usage(CMD_CANCEL);
60570Sstevel@tonic-gate return;
60580Sstevel@tonic-gate }
60590Sstevel@tonic-gate
60600Sstevel@tonic-gate if (global_scope)
60610Sstevel@tonic-gate scope_usage(CMD_CANCEL);
60626215Sgjelinek global_scope = B_TRUE;
60630Sstevel@tonic-gate zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
60640Sstevel@tonic-gate bzero(&in_progress_fstab, sizeof (in_progress_fstab));
60650Sstevel@tonic-gate bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
60660Sstevel@tonic-gate bzero(&in_progress_devtab, sizeof (in_progress_devtab));
60670Sstevel@tonic-gate zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
60680Sstevel@tonic-gate bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
60690Sstevel@tonic-gate bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
6070789Sahrens bzero(&in_progress_dstab, sizeof (in_progress_dstab));
60710Sstevel@tonic-gate }
60720Sstevel@tonic-gate
60730Sstevel@tonic-gate static int
validate_attr_name(char * name)60740Sstevel@tonic-gate validate_attr_name(char *name)
60750Sstevel@tonic-gate {
60760Sstevel@tonic-gate int i;
60770Sstevel@tonic-gate
60780Sstevel@tonic-gate if (!isalnum(name[0])) {
60790Sstevel@tonic-gate zerr(gettext("Invalid %s %s %s: must start with an alpha-"
60800Sstevel@tonic-gate "numeric character."), rt_to_str(RT_ATTR),
60810Sstevel@tonic-gate pt_to_str(PT_NAME), name);
60820Sstevel@tonic-gate return (Z_INVAL);
60830Sstevel@tonic-gate }
60840Sstevel@tonic-gate for (i = 1; name[i]; i++)
60850Sstevel@tonic-gate if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
60860Sstevel@tonic-gate zerr(gettext("Invalid %s %s %s: can only contain "
60870Sstevel@tonic-gate "alpha-numeric characters, plus '-' and '.'."),
60880Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
60890Sstevel@tonic-gate return (Z_INVAL);
60900Sstevel@tonic-gate }
60910Sstevel@tonic-gate return (Z_OK);
60920Sstevel@tonic-gate }
60930Sstevel@tonic-gate
60940Sstevel@tonic-gate static int
validate_attr_type_val(struct zone_attrtab * attrtab)60950Sstevel@tonic-gate validate_attr_type_val(struct zone_attrtab *attrtab)
60960Sstevel@tonic-gate {
60970Sstevel@tonic-gate boolean_t boolval;
60980Sstevel@tonic-gate int64_t intval;
60990Sstevel@tonic-gate char strval[MAXNAMELEN];
61000Sstevel@tonic-gate uint64_t uintval;
61010Sstevel@tonic-gate
61020Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
61030Sstevel@tonic-gate if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
61040Sstevel@tonic-gate return (Z_OK);
61050Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"),
61060Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
61070Sstevel@tonic-gate return (Z_ERR);
61080Sstevel@tonic-gate }
61090Sstevel@tonic-gate
61100Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "int") == 0) {
61110Sstevel@tonic-gate if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
61120Sstevel@tonic-gate return (Z_OK);
61130Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"),
61140Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
61150Sstevel@tonic-gate return (Z_ERR);
61160Sstevel@tonic-gate }
61170Sstevel@tonic-gate
61180Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "string") == 0) {
61190Sstevel@tonic-gate if (zonecfg_get_attr_string(attrtab, strval,
61200Sstevel@tonic-gate sizeof (strval)) == Z_OK)
61210Sstevel@tonic-gate return (Z_OK);
61220Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"),
61230Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
61240Sstevel@tonic-gate return (Z_ERR);
61250Sstevel@tonic-gate }
61260Sstevel@tonic-gate
61270Sstevel@tonic-gate if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
61280Sstevel@tonic-gate if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
61290Sstevel@tonic-gate return (Z_OK);
61300Sstevel@tonic-gate zerr(gettext("invalid %s value for %s=%s"),
61310Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
61320Sstevel@tonic-gate return (Z_ERR);
61330Sstevel@tonic-gate }
61340Sstevel@tonic-gate
61350Sstevel@tonic-gate zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
61360Sstevel@tonic-gate pt_to_str(PT_TYPE), attrtab->zone_attr_type);
61370Sstevel@tonic-gate return (Z_ERR);
61380Sstevel@tonic-gate }
61390Sstevel@tonic-gate
6140565Sdp /*
6141565Sdp * Helper function for end_func-- checks the existence of a given property
6142565Sdp * and emits a message if not specified.
6143565Sdp */
6144565Sdp static int
end_check_reqd(char * attr,int pt,boolean_t * validation_failed)61456215Sgjelinek end_check_reqd(char *attr, int pt, boolean_t *validation_failed)
6146565Sdp {
6147565Sdp if (strlen(attr) == 0) {
61486215Sgjelinek *validation_failed = B_TRUE;
6149565Sdp zerr(gettext("%s not specified"), pt_to_str(pt));
6150565Sdp return (Z_ERR);
6151565Sdp }
6152565Sdp return (Z_OK);
6153565Sdp }
6154565Sdp
615512748SSowmini.Varadhan@oracle.COM static void
net_exists_error(struct zone_nwiftab nwif)615612748SSowmini.Varadhan@oracle.COM net_exists_error(struct zone_nwiftab nwif)
615712748SSowmini.Varadhan@oracle.COM {
615812748SSowmini.Varadhan@oracle.COM if (strlen(nwif.zone_nwif_address) > 0) {
615912748SSowmini.Varadhan@oracle.COM zerr(gettext("A %s resource with the %s '%s', "
616012748SSowmini.Varadhan@oracle.COM "and %s '%s' already exists."),
616112748SSowmini.Varadhan@oracle.COM rt_to_str(RT_NET),
616212748SSowmini.Varadhan@oracle.COM pt_to_str(PT_PHYSICAL),
616312748SSowmini.Varadhan@oracle.COM nwif.zone_nwif_physical,
616412748SSowmini.Varadhan@oracle.COM pt_to_str(PT_ADDRESS),
616512748SSowmini.Varadhan@oracle.COM in_progress_nwiftab.zone_nwif_address);
616612748SSowmini.Varadhan@oracle.COM } else {
616712748SSowmini.Varadhan@oracle.COM zerr(gettext("A %s resource with the %s '%s', "
616812748SSowmini.Varadhan@oracle.COM "and %s '%s' already exists."),
616912748SSowmini.Varadhan@oracle.COM rt_to_str(RT_NET),
617012748SSowmini.Varadhan@oracle.COM pt_to_str(PT_PHYSICAL),
617112748SSowmini.Varadhan@oracle.COM nwif.zone_nwif_physical,
617212748SSowmini.Varadhan@oracle.COM pt_to_str(PT_ALLOWED_ADDRESS),
617312748SSowmini.Varadhan@oracle.COM nwif.zone_nwif_allowed_address);
617412748SSowmini.Varadhan@oracle.COM }
617512748SSowmini.Varadhan@oracle.COM }
617612748SSowmini.Varadhan@oracle.COM
61770Sstevel@tonic-gate void
end_func(cmd_t * cmd)61780Sstevel@tonic-gate end_func(cmd_t *cmd)
61790Sstevel@tonic-gate {
61806215Sgjelinek boolean_t validation_failed = B_FALSE;
61816215Sgjelinek boolean_t arg_err = B_FALSE;
61820Sstevel@tonic-gate struct zone_fstab tmp_fstab;
61830Sstevel@tonic-gate struct zone_nwiftab tmp_nwiftab;
61840Sstevel@tonic-gate struct zone_devtab tmp_devtab;
61850Sstevel@tonic-gate struct zone_rctltab tmp_rctltab;
61860Sstevel@tonic-gate struct zone_attrtab tmp_attrtab;
6187789Sahrens struct zone_dstab tmp_dstab;
618812578SGlenn.Faden@Sun.COM struct zone_admintab tmp_admintab;
61893247Sgjelinek int err, arg, res1, res2, res3;
61903247Sgjelinek uint64_t swap_limit;
61913247Sgjelinek uint64_t locked_limit;
61923792Sakolb uint64_t proc_cap;
61930Sstevel@tonic-gate
61940Sstevel@tonic-gate assert(cmd != NULL);
61950Sstevel@tonic-gate
61960Sstevel@tonic-gate optind = 0;
61973691Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
61980Sstevel@tonic-gate switch (arg) {
61990Sstevel@tonic-gate case '?':
62000Sstevel@tonic-gate longer_usage(CMD_END);
62016215Sgjelinek arg_err = B_TRUE;
62023691Sgjelinek break;
62030Sstevel@tonic-gate default:
62040Sstevel@tonic-gate short_usage(CMD_END);
62056215Sgjelinek arg_err = B_TRUE;
62063691Sgjelinek break;
62073691Sgjelinek }
62083691Sgjelinek }
62093691Sgjelinek if (arg_err)
62103691Sgjelinek return;
62113691Sgjelinek
62120Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
62130Sstevel@tonic-gate short_usage(CMD_END);
62140Sstevel@tonic-gate return;
62150Sstevel@tonic-gate }
62160Sstevel@tonic-gate
62170Sstevel@tonic-gate if (global_scope) {
62180Sstevel@tonic-gate scope_usage(CMD_END);
62190Sstevel@tonic-gate return;
62200Sstevel@tonic-gate }
62210Sstevel@tonic-gate
62220Sstevel@tonic-gate assert(end_op == CMD_ADD || end_op == CMD_SELECT);
62230Sstevel@tonic-gate
62240Sstevel@tonic-gate switch (resource_scope) {
62250Sstevel@tonic-gate case RT_FS:
62260Sstevel@tonic-gate /* First make sure everything was filled in. */
6227565Sdp if (end_check_reqd(in_progress_fstab.zone_fs_dir,
6228565Sdp PT_DIR, &validation_failed) == Z_OK) {
6229565Sdp if (in_progress_fstab.zone_fs_dir[0] != '/') {
6230565Sdp zerr(gettext("%s %s is not an absolute path."),
6231565Sdp pt_to_str(PT_DIR),
6232565Sdp in_progress_fstab.zone_fs_dir);
62336215Sgjelinek validation_failed = B_TRUE;
6234565Sdp }
62350Sstevel@tonic-gate }
6236565Sdp
6237565Sdp (void) end_check_reqd(in_progress_fstab.zone_fs_special,
6238565Sdp PT_SPECIAL, &validation_failed);
6239565Sdp
6240565Sdp if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
6241565Sdp in_progress_fstab.zone_fs_raw[0] != '/') {
6242565Sdp zerr(gettext("%s %s is not an absolute path."),
6243565Sdp pt_to_str(PT_RAW),
6244565Sdp in_progress_fstab.zone_fs_raw);
62456215Sgjelinek validation_failed = B_TRUE;
62460Sstevel@tonic-gate }
6247565Sdp
6248565Sdp (void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
6249565Sdp &validation_failed);
6250565Sdp
6251565Sdp if (validation_failed) {
62526215Sgjelinek saw_error = B_TRUE;
6253565Sdp return;
62540Sstevel@tonic-gate }
6255565Sdp
62560Sstevel@tonic-gate if (end_op == CMD_ADD) {
62570Sstevel@tonic-gate /* Make sure there isn't already one like this. */
62580Sstevel@tonic-gate bzero(&tmp_fstab, sizeof (tmp_fstab));
62590Sstevel@tonic-gate (void) strlcpy(tmp_fstab.zone_fs_dir,
62600Sstevel@tonic-gate in_progress_fstab.zone_fs_dir,
62610Sstevel@tonic-gate sizeof (tmp_fstab.zone_fs_dir));
62620Sstevel@tonic-gate err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
62630Sstevel@tonic-gate zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
62640Sstevel@tonic-gate if (err == Z_OK) {
62650Sstevel@tonic-gate zerr(gettext("A %s resource "
62660Sstevel@tonic-gate "with the %s '%s' already exists."),
62670Sstevel@tonic-gate rt_to_str(RT_FS), pt_to_str(PT_DIR),
62680Sstevel@tonic-gate in_progress_fstab.zone_fs_dir);
62696215Sgjelinek saw_error = B_TRUE;
62700Sstevel@tonic-gate return;
62710Sstevel@tonic-gate }
62720Sstevel@tonic-gate err = zonecfg_add_filesystem(handle,
62730Sstevel@tonic-gate &in_progress_fstab);
62740Sstevel@tonic-gate } else {
62750Sstevel@tonic-gate err = zonecfg_modify_filesystem(handle, &old_fstab,
62760Sstevel@tonic-gate &in_progress_fstab);
62770Sstevel@tonic-gate }
62780Sstevel@tonic-gate zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
62790Sstevel@tonic-gate in_progress_fstab.zone_fs_options = NULL;
62800Sstevel@tonic-gate break;
6281565Sdp
62820Sstevel@tonic-gate case RT_NET:
62833448Sdh155122 /*
62843448Sdh155122 * First make sure everything was filled in.
62853448Sdh155122 * Since we don't know whether IP will be shared
62863448Sdh155122 * or exclusive here, some checks are deferred until
62873448Sdh155122 * the verify command.
62883448Sdh155122 */
6289565Sdp (void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
6290565Sdp PT_PHYSICAL, &validation_failed);
6291565Sdp
6292565Sdp if (validation_failed) {
62936215Sgjelinek saw_error = B_TRUE;
6294565Sdp return;
62950Sstevel@tonic-gate }
62960Sstevel@tonic-gate if (end_op == CMD_ADD) {
62970Sstevel@tonic-gate /* Make sure there isn't already one like this. */
62980Sstevel@tonic-gate bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
62993448Sdh155122 (void) strlcpy(tmp_nwiftab.zone_nwif_physical,
63003448Sdh155122 in_progress_nwiftab.zone_nwif_physical,
63013448Sdh155122 sizeof (tmp_nwiftab.zone_nwif_physical));
63020Sstevel@tonic-gate (void) strlcpy(tmp_nwiftab.zone_nwif_address,
63030Sstevel@tonic-gate in_progress_nwiftab.zone_nwif_address,
63040Sstevel@tonic-gate sizeof (tmp_nwiftab.zone_nwif_address));
630512748SSowmini.Varadhan@oracle.COM (void) strlcpy(tmp_nwiftab.zone_nwif_allowed_address,
630612748SSowmini.Varadhan@oracle.COM in_progress_nwiftab.zone_nwif_allowed_address,
630712748SSowmini.Varadhan@oracle.COM sizeof (tmp_nwiftab.zone_nwif_allowed_address));
630812748SSowmini.Varadhan@oracle.COM (void) strlcpy(tmp_nwiftab.zone_nwif_defrouter,
630912748SSowmini.Varadhan@oracle.COM in_progress_nwiftab.zone_nwif_defrouter,
631012748SSowmini.Varadhan@oracle.COM sizeof (tmp_nwiftab.zone_nwif_defrouter));
63110Sstevel@tonic-gate if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
631212748SSowmini.Varadhan@oracle.COM net_exists_error(in_progress_nwiftab);
63136215Sgjelinek saw_error = B_TRUE;
63140Sstevel@tonic-gate return;
63150Sstevel@tonic-gate }
63160Sstevel@tonic-gate err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
63170Sstevel@tonic-gate } else {
63180Sstevel@tonic-gate err = zonecfg_modify_nwif(handle, &old_nwiftab,
63190Sstevel@tonic-gate &in_progress_nwiftab);
63200Sstevel@tonic-gate }
63210Sstevel@tonic-gate break;
6322565Sdp
63230Sstevel@tonic-gate case RT_DEVICE:
63240Sstevel@tonic-gate /* First make sure everything was filled in. */
6325565Sdp (void) end_check_reqd(in_progress_devtab.zone_dev_match,
6326565Sdp PT_MATCH, &validation_failed);
6327565Sdp
6328565Sdp if (validation_failed) {
63296215Sgjelinek saw_error = B_TRUE;
6330565Sdp return;
63310Sstevel@tonic-gate }
6332565Sdp
63330Sstevel@tonic-gate if (end_op == CMD_ADD) {
63340Sstevel@tonic-gate /* Make sure there isn't already one like this. */
63350Sstevel@tonic-gate (void) strlcpy(tmp_devtab.zone_dev_match,
63360Sstevel@tonic-gate in_progress_devtab.zone_dev_match,
63370Sstevel@tonic-gate sizeof (tmp_devtab.zone_dev_match));
63380Sstevel@tonic-gate if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
63390Sstevel@tonic-gate zerr(gettext("A %s resource with the %s '%s' "
63400Sstevel@tonic-gate "already exists."), rt_to_str(RT_DEVICE),
63410Sstevel@tonic-gate pt_to_str(PT_MATCH),
63420Sstevel@tonic-gate in_progress_devtab.zone_dev_match);
63436215Sgjelinek saw_error = B_TRUE;
63440Sstevel@tonic-gate return;
63450Sstevel@tonic-gate }
63460Sstevel@tonic-gate err = zonecfg_add_dev(handle, &in_progress_devtab);
63470Sstevel@tonic-gate } else {
63480Sstevel@tonic-gate err = zonecfg_modify_dev(handle, &old_devtab,
63490Sstevel@tonic-gate &in_progress_devtab);
63500Sstevel@tonic-gate }
63510Sstevel@tonic-gate break;
6352565Sdp
63530Sstevel@tonic-gate case RT_RCTL:
63540Sstevel@tonic-gate /* First make sure everything was filled in. */
6355565Sdp (void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
6356565Sdp PT_NAME, &validation_failed);
6357565Sdp
6358565Sdp if (in_progress_rctltab.zone_rctl_valptr == NULL) {
6359565Sdp zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
63606215Sgjelinek validation_failed = B_TRUE;
63610Sstevel@tonic-gate }
6362565Sdp
6363565Sdp if (validation_failed) {
63646215Sgjelinek saw_error = B_TRUE;
6365565Sdp return;
63660Sstevel@tonic-gate }
6367565Sdp
63680Sstevel@tonic-gate if (end_op == CMD_ADD) {
63690Sstevel@tonic-gate /* Make sure there isn't already one like this. */
63700Sstevel@tonic-gate (void) strlcpy(tmp_rctltab.zone_rctl_name,
63710Sstevel@tonic-gate in_progress_rctltab.zone_rctl_name,
63720Sstevel@tonic-gate sizeof (tmp_rctltab.zone_rctl_name));
63730Sstevel@tonic-gate tmp_rctltab.zone_rctl_valptr = NULL;
63740Sstevel@tonic-gate err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
63750Sstevel@tonic-gate zonecfg_free_rctl_value_list(
63760Sstevel@tonic-gate tmp_rctltab.zone_rctl_valptr);
63770Sstevel@tonic-gate if (err == Z_OK) {
63780Sstevel@tonic-gate zerr(gettext("A %s resource "
63790Sstevel@tonic-gate "with the %s '%s' already exists."),
63800Sstevel@tonic-gate rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
63810Sstevel@tonic-gate in_progress_rctltab.zone_rctl_name);
63826215Sgjelinek saw_error = B_TRUE;
63830Sstevel@tonic-gate return;
63840Sstevel@tonic-gate }
63850Sstevel@tonic-gate err = zonecfg_add_rctl(handle, &in_progress_rctltab);
63860Sstevel@tonic-gate } else {
63870Sstevel@tonic-gate err = zonecfg_modify_rctl(handle, &old_rctltab,
63880Sstevel@tonic-gate &in_progress_rctltab);
63890Sstevel@tonic-gate }
63900Sstevel@tonic-gate if (err == Z_OK) {
63910Sstevel@tonic-gate zonecfg_free_rctl_value_list(
63920Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr);
63930Sstevel@tonic-gate in_progress_rctltab.zone_rctl_valptr = NULL;
63940Sstevel@tonic-gate }
63950Sstevel@tonic-gate break;
6396565Sdp
63970Sstevel@tonic-gate case RT_ATTR:
63980Sstevel@tonic-gate /* First make sure everything was filled in. */
6399565Sdp (void) end_check_reqd(in_progress_attrtab.zone_attr_name,
6400565Sdp PT_NAME, &validation_failed);
6401565Sdp (void) end_check_reqd(in_progress_attrtab.zone_attr_type,
6402565Sdp PT_TYPE, &validation_failed);
6403565Sdp (void) end_check_reqd(in_progress_attrtab.zone_attr_value,
6404565Sdp PT_VALUE, &validation_failed);
6405565Sdp
6406565Sdp if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
6407565Sdp Z_OK)
64086215Sgjelinek validation_failed = B_TRUE;
6409565Sdp
6410565Sdp if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
64116215Sgjelinek validation_failed = B_TRUE;
6412565Sdp
6413565Sdp if (validation_failed) {
64146215Sgjelinek saw_error = B_TRUE;
6415565Sdp return;
64160Sstevel@tonic-gate }
64170Sstevel@tonic-gate if (end_op == CMD_ADD) {
64180Sstevel@tonic-gate /* Make sure there isn't already one like this. */
64190Sstevel@tonic-gate bzero(&tmp_attrtab, sizeof (tmp_attrtab));
64200Sstevel@tonic-gate (void) strlcpy(tmp_attrtab.zone_attr_name,
64210Sstevel@tonic-gate in_progress_attrtab.zone_attr_name,
64220Sstevel@tonic-gate sizeof (tmp_attrtab.zone_attr_name));
64230Sstevel@tonic-gate if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
64240Sstevel@tonic-gate zerr(gettext("An %s resource "
64250Sstevel@tonic-gate "with the %s '%s' already exists."),
64260Sstevel@tonic-gate rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
64270Sstevel@tonic-gate in_progress_attrtab.zone_attr_name);
64286215Sgjelinek saw_error = B_TRUE;
64290Sstevel@tonic-gate return;
64300Sstevel@tonic-gate }
64310Sstevel@tonic-gate err = zonecfg_add_attr(handle, &in_progress_attrtab);
64320Sstevel@tonic-gate } else {
64330Sstevel@tonic-gate err = zonecfg_modify_attr(handle, &old_attrtab,
64340Sstevel@tonic-gate &in_progress_attrtab);
64350Sstevel@tonic-gate }
64360Sstevel@tonic-gate break;
6437789Sahrens case RT_DATASET:
6438789Sahrens /* First make sure everything was filled in. */
6439789Sahrens if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
6440789Sahrens zerr("%s %s", pt_to_str(PT_NAME),
6441789Sahrens gettext("not specified"));
64426215Sgjelinek saw_error = B_TRUE;
64436215Sgjelinek validation_failed = B_TRUE;
6444789Sahrens }
6445789Sahrens if (validation_failed)
6446789Sahrens return;
6447789Sahrens if (end_op == CMD_ADD) {
6448789Sahrens /* Make sure there isn't already one like this. */
6449789Sahrens bzero(&tmp_dstab, sizeof (tmp_dstab));
6450789Sahrens (void) strlcpy(tmp_dstab.zone_dataset_name,
6451789Sahrens in_progress_dstab.zone_dataset_name,
6452789Sahrens sizeof (tmp_dstab.zone_dataset_name));
6453789Sahrens err = zonecfg_lookup_ds(handle, &tmp_dstab);
6454789Sahrens if (err == Z_OK) {
6455789Sahrens zerr(gettext("A %s resource "
6456789Sahrens "with the %s '%s' already exists."),
6457789Sahrens rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
6458789Sahrens in_progress_dstab.zone_dataset_name);
64596215Sgjelinek saw_error = B_TRUE;
6460789Sahrens return;
6461789Sahrens }
6462789Sahrens err = zonecfg_add_ds(handle, &in_progress_dstab);
6463789Sahrens } else {
6464789Sahrens err = zonecfg_modify_ds(handle, &old_dstab,
6465789Sahrens &in_progress_dstab);
6466789Sahrens }
6467789Sahrens break;
64683247Sgjelinek case RT_DCPU:
64693247Sgjelinek /* Make sure everything was filled in. */
64703247Sgjelinek if (end_check_reqd(in_progress_psettab.zone_ncpu_min,
64713247Sgjelinek PT_NCPUS, &validation_failed) != Z_OK) {
64726215Sgjelinek saw_error = B_TRUE;
64733247Sgjelinek return;
64743247Sgjelinek }
64753247Sgjelinek
64763247Sgjelinek if (end_op == CMD_ADD) {
64773247Sgjelinek err = zonecfg_add_pset(handle, &in_progress_psettab);
64783247Sgjelinek } else {
64793247Sgjelinek err = zonecfg_modify_pset(handle, &in_progress_psettab);
64803247Sgjelinek }
64813247Sgjelinek break;
64823792Sakolb case RT_PCAP:
64833792Sakolb /* Make sure everything was filled in. */
64843792Sakolb if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
64853792Sakolb != Z_OK) {
64863792Sakolb zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
64876215Sgjelinek saw_error = B_TRUE;
64886215Sgjelinek validation_failed = B_TRUE;
64893792Sakolb return;
64903792Sakolb }
64913792Sakolb err = Z_OK;
64923792Sakolb break;
64933247Sgjelinek case RT_MCAP:
64943247Sgjelinek /* Make sure everything was filled in. */
64953247Sgjelinek res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
64963247Sgjelinek Z_ERR : Z_OK;
64973247Sgjelinek res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
64983247Sgjelinek &swap_limit);
64993247Sgjelinek res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
65003247Sgjelinek &locked_limit);
65013247Sgjelinek
65023247Sgjelinek if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
65033247Sgjelinek zerr(gettext("No property was specified. One of %s, "
65043247Sgjelinek "%s or %s is required."), pt_to_str(PT_PHYSICAL),
65053247Sgjelinek pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
65066215Sgjelinek saw_error = B_TRUE;
65073247Sgjelinek return;
65083247Sgjelinek }
65093247Sgjelinek
65103247Sgjelinek /* if phys & locked are both set, verify locked <= phys */
65113247Sgjelinek if (res1 == Z_OK && res3 == Z_OK) {
65123247Sgjelinek uint64_t phys_limit;
65133247Sgjelinek char *endp;
65143247Sgjelinek
65153247Sgjelinek phys_limit = strtoull(
65163247Sgjelinek in_progress_mcaptab.zone_physmem_cap, &endp, 10);
65173247Sgjelinek if (phys_limit < locked_limit) {
65183247Sgjelinek zerr(gettext("The %s cap must be less than or "
65193247Sgjelinek "equal to the %s cap."),
65203247Sgjelinek pt_to_str(PT_LOCKED),
65213247Sgjelinek pt_to_str(PT_PHYSICAL));
65226215Sgjelinek saw_error = B_TRUE;
65233247Sgjelinek return;
65243247Sgjelinek }
65253247Sgjelinek }
65263247Sgjelinek
65273247Sgjelinek err = Z_OK;
65283247Sgjelinek if (res1 == Z_OK) {
65293247Sgjelinek /*
65303247Sgjelinek * We could be ending from either an add operation
65313247Sgjelinek * or a select operation. Since all of the properties
65323247Sgjelinek * within this resource are optional, we always use
65333247Sgjelinek * modify on the mcap entry. zonecfg_modify_mcap()
65343247Sgjelinek * will handle both adding and modifying a memory cap.
65353247Sgjelinek */
65363247Sgjelinek err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
65373247Sgjelinek } else if (end_op == CMD_SELECT) {
65383247Sgjelinek /*
65393247Sgjelinek * If we're ending from a select and the physical
65403247Sgjelinek * memory cap is empty then the user could have cleared
65413247Sgjelinek * the physical cap value, so try to delete the entry.
65423247Sgjelinek */
65433247Sgjelinek (void) zonecfg_delete_mcap(handle);
65443247Sgjelinek }
65453247Sgjelinek break;
654612578SGlenn.Faden@Sun.COM case RT_ADMIN:
654712578SGlenn.Faden@Sun.COM /* First make sure everything was filled in. */
654812578SGlenn.Faden@Sun.COM if (end_check_reqd(in_progress_admintab.zone_admin_user,
654912578SGlenn.Faden@Sun.COM PT_USER, &validation_failed) == Z_OK) {
655012578SGlenn.Faden@Sun.COM if (getpwnam(in_progress_admintab.zone_admin_user)
655112578SGlenn.Faden@Sun.COM == NULL) {
655212578SGlenn.Faden@Sun.COM zerr(gettext("%s %s is not a valid username"),
655312578SGlenn.Faden@Sun.COM pt_to_str(PT_USER),
655412578SGlenn.Faden@Sun.COM in_progress_admintab.zone_admin_user);
655512578SGlenn.Faden@Sun.COM validation_failed = B_TRUE;
655612578SGlenn.Faden@Sun.COM }
655712578SGlenn.Faden@Sun.COM }
655812578SGlenn.Faden@Sun.COM
655912578SGlenn.Faden@Sun.COM if (end_check_reqd(in_progress_admintab.zone_admin_auths,
656012578SGlenn.Faden@Sun.COM PT_AUTHS, &validation_failed) == Z_OK) {
656112578SGlenn.Faden@Sun.COM if (!zonecfg_valid_auths(
656212578SGlenn.Faden@Sun.COM in_progress_admintab.zone_admin_auths,
656312578SGlenn.Faden@Sun.COM zone)) {
656412578SGlenn.Faden@Sun.COM validation_failed = B_TRUE;
656512578SGlenn.Faden@Sun.COM }
656612578SGlenn.Faden@Sun.COM }
656712578SGlenn.Faden@Sun.COM
656812578SGlenn.Faden@Sun.COM if (validation_failed) {
656912578SGlenn.Faden@Sun.COM saw_error = B_TRUE;
657012578SGlenn.Faden@Sun.COM return;
657112578SGlenn.Faden@Sun.COM }
657212578SGlenn.Faden@Sun.COM
657312578SGlenn.Faden@Sun.COM if (end_op == CMD_ADD) {
657412578SGlenn.Faden@Sun.COM /* Make sure there isn't already one like this. */
657512578SGlenn.Faden@Sun.COM bzero(&tmp_admintab, sizeof (tmp_admintab));
657612578SGlenn.Faden@Sun.COM (void) strlcpy(tmp_admintab.zone_admin_user,
657712578SGlenn.Faden@Sun.COM in_progress_admintab.zone_admin_user,
657812578SGlenn.Faden@Sun.COM sizeof (tmp_admintab.zone_admin_user));
657912578SGlenn.Faden@Sun.COM err = zonecfg_lookup_admin(
658012578SGlenn.Faden@Sun.COM handle, &tmp_admintab);
658112578SGlenn.Faden@Sun.COM if (err == Z_OK) {
658212578SGlenn.Faden@Sun.COM zerr(gettext("A %s resource "
658312578SGlenn.Faden@Sun.COM "with the %s '%s' already exists."),
658412578SGlenn.Faden@Sun.COM rt_to_str(RT_ADMIN),
658512578SGlenn.Faden@Sun.COM pt_to_str(PT_USER),
658612578SGlenn.Faden@Sun.COM in_progress_admintab.zone_admin_user);
658712578SGlenn.Faden@Sun.COM saw_error = B_TRUE;
658812578SGlenn.Faden@Sun.COM return;
658912578SGlenn.Faden@Sun.COM }
659012578SGlenn.Faden@Sun.COM err = zonecfg_add_admin(handle,
659112578SGlenn.Faden@Sun.COM &in_progress_admintab, zone);
659212578SGlenn.Faden@Sun.COM } else {
659312578SGlenn.Faden@Sun.COM err = zonecfg_modify_admin(handle,
659412578SGlenn.Faden@Sun.COM &old_admintab, &in_progress_admintab,
659512578SGlenn.Faden@Sun.COM zone);
659612578SGlenn.Faden@Sun.COM }
659712578SGlenn.Faden@Sun.COM break;
65980Sstevel@tonic-gate default:
65990Sstevel@tonic-gate zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
66006215Sgjelinek B_TRUE);
66016215Sgjelinek saw_error = B_TRUE;
66020Sstevel@tonic-gate return;
66030Sstevel@tonic-gate }
66040Sstevel@tonic-gate
66050Sstevel@tonic-gate if (err != Z_OK) {
66066215Sgjelinek zone_perror(zone, err, B_TRUE);
66070Sstevel@tonic-gate } else {
66086215Sgjelinek need_to_commit = B_TRUE;
66096215Sgjelinek global_scope = B_TRUE;
66100Sstevel@tonic-gate end_op = -1;
66110Sstevel@tonic-gate }
66120Sstevel@tonic-gate }
66130Sstevel@tonic-gate
66140Sstevel@tonic-gate void
commit_func(cmd_t * cmd)66150Sstevel@tonic-gate commit_func(cmd_t *cmd)
66160Sstevel@tonic-gate {
66170Sstevel@tonic-gate int arg;
66186215Sgjelinek boolean_t arg_err = B_FALSE;
66190Sstevel@tonic-gate
66200Sstevel@tonic-gate optind = 0;
66213691Sgjelinek while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
66220Sstevel@tonic-gate switch (arg) {
66230Sstevel@tonic-gate case '?':
66240Sstevel@tonic-gate longer_usage(CMD_COMMIT);
66256215Sgjelinek arg_err = B_TRUE;
66263691Sgjelinek break;
66270Sstevel@tonic-gate default:
66280Sstevel@tonic-gate short_usage(CMD_COMMIT);
66296215Sgjelinek arg_err = B_TRUE;
66303691Sgjelinek break;
66313691Sgjelinek }
66323691Sgjelinek }
66333691Sgjelinek if (arg_err)
66343691Sgjelinek return;
66353691Sgjelinek
66360Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
66370Sstevel@tonic-gate short_usage(CMD_COMMIT);
66380Sstevel@tonic-gate return;
66390Sstevel@tonic-gate }
66400Sstevel@tonic-gate
66410Sstevel@tonic-gate if (zone_is_read_only(CMD_COMMIT))
66420Sstevel@tonic-gate return;
66430Sstevel@tonic-gate
66440Sstevel@tonic-gate assert(cmd != NULL);
66450Sstevel@tonic-gate
66460Sstevel@tonic-gate cmd->cmd_argc = 1;
66470Sstevel@tonic-gate /*
66480Sstevel@tonic-gate * cmd_arg normally comes from a strdup() in the lexer, and the
66490Sstevel@tonic-gate * whole cmd structure and its (char *) attributes are freed at
66500Sstevel@tonic-gate * the completion of each command, so the strdup() below is needed
66510Sstevel@tonic-gate * to match this and prevent a core dump from trying to free()
66520Sstevel@tonic-gate * something that can't be.
66530Sstevel@tonic-gate */
66540Sstevel@tonic-gate if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
66556215Sgjelinek zone_perror(zone, Z_NOMEM, B_TRUE);
66560Sstevel@tonic-gate exit(Z_ERR);
66570Sstevel@tonic-gate }
66580Sstevel@tonic-gate cmd->cmd_argv[1] = NULL;
66590Sstevel@tonic-gate verify_func(cmd);
66600Sstevel@tonic-gate }
66610Sstevel@tonic-gate
66620Sstevel@tonic-gate void
revert_func(cmd_t * cmd)66630Sstevel@tonic-gate revert_func(cmd_t *cmd)
66640Sstevel@tonic-gate {
66650Sstevel@tonic-gate char line[128]; /* enough to ask a question */
66666215Sgjelinek boolean_t force = B_FALSE;
66676215Sgjelinek boolean_t arg_err = B_FALSE;
66680Sstevel@tonic-gate int err, arg, answer;
66690Sstevel@tonic-gate
66700Sstevel@tonic-gate optind = 0;
66710Sstevel@tonic-gate while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
66720Sstevel@tonic-gate switch (arg) {
66730Sstevel@tonic-gate case '?':
66740Sstevel@tonic-gate longer_usage(CMD_REVERT);
66756215Sgjelinek arg_err = B_TRUE;
66763691Sgjelinek break;
66770Sstevel@tonic-gate case 'F':
66786215Sgjelinek force = B_TRUE;
66790Sstevel@tonic-gate break;
66800Sstevel@tonic-gate default:
66810Sstevel@tonic-gate short_usage(CMD_REVERT);
66826215Sgjelinek arg_err = B_TRUE;
66833691Sgjelinek break;
66843691Sgjelinek }
66853691Sgjelinek }
66863691Sgjelinek if (arg_err)
66873691Sgjelinek return;
66883691Sgjelinek
66890Sstevel@tonic-gate if (optind != cmd->cmd_argc) {
66900Sstevel@tonic-gate short_usage(CMD_REVERT);
66910Sstevel@tonic-gate return;
66920Sstevel@tonic-gate }
66930Sstevel@tonic-gate
66940Sstevel@tonic-gate if (zone_is_read_only(CMD_REVERT))
66950Sstevel@tonic-gate return;
66960Sstevel@tonic-gate
66978113SJordan.Vaughan@Sun.com if (!global_scope) {
66988113SJordan.Vaughan@Sun.com zerr(gettext("You can only use %s in the global scope.\nUse"
66998113SJordan.Vaughan@Sun.com " '%s' to cancel changes to a resource specification."),
67008113SJordan.Vaughan@Sun.com cmd_to_str(CMD_REVERT), cmd_to_str(CMD_CANCEL));
67018113SJordan.Vaughan@Sun.com saw_error = B_TRUE;
67028113SJordan.Vaughan@Sun.com return;
67038113SJordan.Vaughan@Sun.com }
67048113SJordan.Vaughan@Sun.com
67050Sstevel@tonic-gate if (zonecfg_check_handle(handle) != Z_OK) {
67060Sstevel@tonic-gate zerr(gettext("No changes to revert."));
67076215Sgjelinek saw_error = B_TRUE;
67080Sstevel@tonic-gate return;
67090Sstevel@tonic-gate }
67100Sstevel@tonic-gate
67110Sstevel@tonic-gate if (!force) {
67120Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
67130Sstevel@tonic-gate gettext("Are you sure you want to revert"));
67146215Sgjelinek if ((answer = ask_yesno(B_FALSE, line)) == -1) {
67150Sstevel@tonic-gate zerr(gettext("Input not from terminal and -F not "
67160Sstevel@tonic-gate "specified:\n%s command ignored, exiting."),
67170Sstevel@tonic-gate cmd_to_str(CMD_REVERT));
67180Sstevel@tonic-gate exit(Z_ERR);
67190Sstevel@tonic-gate }
67200Sstevel@tonic-gate if (answer != 1)
67210Sstevel@tonic-gate return;
67220Sstevel@tonic-gate }
67230Sstevel@tonic-gate
67240Sstevel@tonic-gate /*
672512578SGlenn.Faden@Sun.COM * Reset any pending admins that were
672612578SGlenn.Faden@Sun.COM * removed from the previous zone
672712578SGlenn.Faden@Sun.COM */
672812578SGlenn.Faden@Sun.COM zonecfg_remove_userauths(handle, "", zone, B_FALSE);
672912578SGlenn.Faden@Sun.COM
673012578SGlenn.Faden@Sun.COM /*
67310Sstevel@tonic-gate * Time for a new handle: finish the old one off first
67320Sstevel@tonic-gate * then get a new one properly to avoid leaks.
67330Sstevel@tonic-gate */
67340Sstevel@tonic-gate zonecfg_fini_handle(handle);
67350Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) {
67366215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
67370Sstevel@tonic-gate exit(Z_ERR);
67380Sstevel@tonic-gate }
673912578SGlenn.Faden@Sun.COM
6740565Sdp if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
67416215Sgjelinek saw_error = B_TRUE;
67426215Sgjelinek got_handle = B_FALSE;
67430Sstevel@tonic-gate if (err == Z_NO_ZONE)
67440Sstevel@tonic-gate zerr(gettext("%s: no such saved zone to revert to."),
6745565Sdp revert_zone);
67460Sstevel@tonic-gate else
67476215Sgjelinek zone_perror(zone, err, B_TRUE);
67480Sstevel@tonic-gate }
6749565Sdp (void) strlcpy(zone, revert_zone, sizeof (zone));
67500Sstevel@tonic-gate }
67510Sstevel@tonic-gate
67520Sstevel@tonic-gate void
help_func(cmd_t * cmd)67530Sstevel@tonic-gate help_func(cmd_t *cmd)
67540Sstevel@tonic-gate {
67550Sstevel@tonic-gate int i;
67560Sstevel@tonic-gate
67570Sstevel@tonic-gate assert(cmd != NULL);
67580Sstevel@tonic-gate
67590Sstevel@tonic-gate if (cmd->cmd_argc == 0) {
67606215Sgjelinek usage(B_TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
67610Sstevel@tonic-gate return;
67620Sstevel@tonic-gate }
67630Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
67646215Sgjelinek usage(B_TRUE, HELP_USAGE);
67650Sstevel@tonic-gate return;
67660Sstevel@tonic-gate }
67670Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
67686215Sgjelinek usage(B_TRUE, HELP_SUBCMDS);
67690Sstevel@tonic-gate return;
67700Sstevel@tonic-gate }
67710Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
67726215Sgjelinek usage(B_TRUE, HELP_SYNTAX | HELP_RES_PROPS);
67730Sstevel@tonic-gate return;
67740Sstevel@tonic-gate }
67750Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
67760Sstevel@tonic-gate longer_usage(CMD_HELP);
67770Sstevel@tonic-gate return;
67780Sstevel@tonic-gate }
67790Sstevel@tonic-gate
67800Sstevel@tonic-gate for (i = 0; i <= CMD_MAX; i++) {
67810Sstevel@tonic-gate if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
67820Sstevel@tonic-gate longer_usage(i);
67830Sstevel@tonic-gate return;
67840Sstevel@tonic-gate }
67850Sstevel@tonic-gate }
67860Sstevel@tonic-gate /* We do not use zerr() here because we do not want its extra \n. */
67870Sstevel@tonic-gate (void) fprintf(stderr, gettext("Unknown help subject %s. "),
67880Sstevel@tonic-gate cmd->cmd_argv[0]);
67896215Sgjelinek usage(B_FALSE, HELP_META);
67900Sstevel@tonic-gate }
67910Sstevel@tonic-gate
67920Sstevel@tonic-gate static int
string_to_yyin(char * string)67930Sstevel@tonic-gate string_to_yyin(char *string)
67940Sstevel@tonic-gate {
67950Sstevel@tonic-gate if ((yyin = tmpfile()) == NULL) {
67966215Sgjelinek zone_perror(execname, Z_TEMP_FILE, B_TRUE);
67970Sstevel@tonic-gate return (Z_ERR);
67980Sstevel@tonic-gate }
67990Sstevel@tonic-gate if (fwrite(string, strlen(string), 1, yyin) != 1) {
68006215Sgjelinek zone_perror(execname, Z_TEMP_FILE, B_TRUE);
68010Sstevel@tonic-gate return (Z_ERR);
68020Sstevel@tonic-gate }
68030Sstevel@tonic-gate if (fseek(yyin, 0, SEEK_SET) != 0) {
68046215Sgjelinek zone_perror(execname, Z_TEMP_FILE, B_TRUE);
68050Sstevel@tonic-gate return (Z_ERR);
68060Sstevel@tonic-gate }
68070Sstevel@tonic-gate return (Z_OK);
68080Sstevel@tonic-gate }
68090Sstevel@tonic-gate
68100Sstevel@tonic-gate /* This is the back-end helper function for read_input() below. */
68110Sstevel@tonic-gate
68120Sstevel@tonic-gate static int
cleanup()68130Sstevel@tonic-gate cleanup()
68140Sstevel@tonic-gate {
68150Sstevel@tonic-gate int answer;
68160Sstevel@tonic-gate cmd_t *cmd;
68170Sstevel@tonic-gate
68180Sstevel@tonic-gate if (!interactive_mode && !cmd_file_mode) {
68190Sstevel@tonic-gate /*
68200Sstevel@tonic-gate * If we're not in interactive mode, and we're not in command
68210Sstevel@tonic-gate * file mode, then we must be in commands-from-the-command-line
68220Sstevel@tonic-gate * mode. As such, we can't loop back and ask for more input.
68230Sstevel@tonic-gate * It was OK to prompt for such things as whether or not to
68240Sstevel@tonic-gate * really delete a zone in the command handler called from
68250Sstevel@tonic-gate * yyparse() above, but "really quit?" makes no sense in this
68260Sstevel@tonic-gate * context. So disable prompting.
68270Sstevel@tonic-gate */
68286215Sgjelinek ok_to_prompt = B_FALSE;
68290Sstevel@tonic-gate }
68300Sstevel@tonic-gate if (!global_scope) {
68310Sstevel@tonic-gate if (!time_to_exit) {
68320Sstevel@tonic-gate /*
68330Sstevel@tonic-gate * Just print a simple error message in the -1 case,
68340Sstevel@tonic-gate * since exit_func() already handles that case, and
68350Sstevel@tonic-gate * EOF means we are finished anyway.
68360Sstevel@tonic-gate */
68376215Sgjelinek answer = ask_yesno(B_FALSE,
68380Sstevel@tonic-gate gettext("Resource incomplete; really quit"));
68390Sstevel@tonic-gate if (answer == -1) {
68400Sstevel@tonic-gate zerr(gettext("Resource incomplete."));
68410Sstevel@tonic-gate return (Z_ERR);
68420Sstevel@tonic-gate }
68430Sstevel@tonic-gate if (answer != 1) {
68440Sstevel@tonic-gate yyin = stdin;
68450Sstevel@tonic-gate return (Z_REPEAT);
68460Sstevel@tonic-gate }
68470Sstevel@tonic-gate } else {
68486215Sgjelinek saw_error = B_TRUE;
68490Sstevel@tonic-gate }
68500Sstevel@tonic-gate }
68510Sstevel@tonic-gate /*
68520Sstevel@tonic-gate * Make sure we tried something and that the handle checks
68530Sstevel@tonic-gate * out, or we would get a false error trying to commit.
68540Sstevel@tonic-gate */
68550Sstevel@tonic-gate if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
68560Sstevel@tonic-gate if ((cmd = alloc_cmd()) == NULL) {
68576215Sgjelinek zone_perror(zone, Z_NOMEM, B_TRUE);
68580Sstevel@tonic-gate return (Z_ERR);
68590Sstevel@tonic-gate }
68600Sstevel@tonic-gate cmd->cmd_argc = 0;
68610Sstevel@tonic-gate cmd->cmd_argv[0] = NULL;
68620Sstevel@tonic-gate commit_func(cmd);
68630Sstevel@tonic-gate free_cmd(cmd);
68640Sstevel@tonic-gate /*
68650Sstevel@tonic-gate * need_to_commit will get set back to FALSE if the
68660Sstevel@tonic-gate * configuration is saved successfully.
68670Sstevel@tonic-gate */
68680Sstevel@tonic-gate if (need_to_commit) {
68690Sstevel@tonic-gate if (force_exit) {
68700Sstevel@tonic-gate zerr(gettext("Configuration not saved."));
68710Sstevel@tonic-gate return (Z_ERR);
68720Sstevel@tonic-gate }
68736215Sgjelinek answer = ask_yesno(B_FALSE,
68740Sstevel@tonic-gate gettext("Configuration not saved; really quit"));
68750Sstevel@tonic-gate if (answer == -1) {
68760Sstevel@tonic-gate zerr(gettext("Configuration not saved."));
68770Sstevel@tonic-gate return (Z_ERR);
68780Sstevel@tonic-gate }
68790Sstevel@tonic-gate if (answer != 1) {
68806215Sgjelinek time_to_exit = B_FALSE;
68810Sstevel@tonic-gate yyin = stdin;
68820Sstevel@tonic-gate return (Z_REPEAT);
68830Sstevel@tonic-gate }
68840Sstevel@tonic-gate }
68850Sstevel@tonic-gate }
68860Sstevel@tonic-gate return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
68870Sstevel@tonic-gate }
68880Sstevel@tonic-gate
68890Sstevel@tonic-gate /*
68900Sstevel@tonic-gate * read_input() is the driver of this program. It is a wrapper around
68910Sstevel@tonic-gate * yyparse(), printing appropriate prompts when needed, checking for
68920Sstevel@tonic-gate * exit conditions and reacting appropriately [the latter in its cleanup()
68930Sstevel@tonic-gate * helper function].
68940Sstevel@tonic-gate *
68950Sstevel@tonic-gate * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
68960Sstevel@tonic-gate * so do_interactive() knows that we are not really done (i.e, we asked
68970Sstevel@tonic-gate * the user if we should really quit and the user said no).
68980Sstevel@tonic-gate */
68990Sstevel@tonic-gate static int
read_input()69000Sstevel@tonic-gate read_input()
69010Sstevel@tonic-gate {
69026215Sgjelinek boolean_t yyin_is_a_tty = isatty(fileno(yyin));
69030Sstevel@tonic-gate /*
69040Sstevel@tonic-gate * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
69050Sstevel@tonic-gate * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
69060Sstevel@tonic-gate */
69070Sstevel@tonic-gate char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
69080Sstevel@tonic-gate
69090Sstevel@tonic-gate /* yyin should have been set to the appropriate (FILE *) if not stdin */
69106215Sgjelinek newline_terminated = B_TRUE;
69110Sstevel@tonic-gate for (;;) {
69120Sstevel@tonic-gate if (yyin_is_a_tty) {
69130Sstevel@tonic-gate if (newline_terminated) {
69140Sstevel@tonic-gate if (global_scope)
69150Sstevel@tonic-gate (void) snprintf(prompt, sizeof (prompt),
69160Sstevel@tonic-gate "%s:%s> ", execname, zone);
69170Sstevel@tonic-gate else
69180Sstevel@tonic-gate (void) snprintf(prompt, sizeof (prompt),
69190Sstevel@tonic-gate "%s:%s:%s> ", execname, zone,
69200Sstevel@tonic-gate rt_to_str(resource_scope));
69210Sstevel@tonic-gate }
69220Sstevel@tonic-gate /*
69230Sstevel@tonic-gate * If the user hits ^C then we want to catch it and
69240Sstevel@tonic-gate * start over. If the user hits EOF then we want to
69250Sstevel@tonic-gate * bail out.
69260Sstevel@tonic-gate */
69270Sstevel@tonic-gate line = gl_get_line(gl, prompt, NULL, -1);
69280Sstevel@tonic-gate if (gl_return_status(gl) == GLR_SIGNAL) {
69290Sstevel@tonic-gate gl_abandon_line(gl);
69300Sstevel@tonic-gate continue;
69310Sstevel@tonic-gate }
69320Sstevel@tonic-gate if (line == NULL)
69330Sstevel@tonic-gate break;
69340Sstevel@tonic-gate (void) string_to_yyin(line);
69350Sstevel@tonic-gate while (!feof(yyin))
69360Sstevel@tonic-gate yyparse();
69370Sstevel@tonic-gate } else {
69380Sstevel@tonic-gate yyparse();
69390Sstevel@tonic-gate }
69400Sstevel@tonic-gate /* Bail out on an error in command file mode. */
69410Sstevel@tonic-gate if (saw_error && cmd_file_mode && !interactive_mode)
69426215Sgjelinek time_to_exit = B_TRUE;
69430Sstevel@tonic-gate if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
69440Sstevel@tonic-gate break;
69450Sstevel@tonic-gate }
69460Sstevel@tonic-gate return (cleanup());
69470Sstevel@tonic-gate }
69480Sstevel@tonic-gate
69490Sstevel@tonic-gate /*
69500Sstevel@tonic-gate * This function is used in the zonecfg-interactive-mode scenario: it just
69510Sstevel@tonic-gate * calls read_input() until we are done.
69520Sstevel@tonic-gate */
69530Sstevel@tonic-gate
69540Sstevel@tonic-gate static int
do_interactive(void)69550Sstevel@tonic-gate do_interactive(void)
69560Sstevel@tonic-gate {
69570Sstevel@tonic-gate int err;
69580Sstevel@tonic-gate
69596215Sgjelinek interactive_mode = B_TRUE;
69600Sstevel@tonic-gate if (!read_only_mode) {
69610Sstevel@tonic-gate /*
69620Sstevel@tonic-gate * Try to set things up proactively in interactive mode, so
69630Sstevel@tonic-gate * that if the zone in question does not exist yet, we can
69640Sstevel@tonic-gate * provide the user with a clue.
69650Sstevel@tonic-gate */
69666215Sgjelinek (void) initialize(B_FALSE);
69670Sstevel@tonic-gate }
6968565Sdp do {
69690Sstevel@tonic-gate err = read_input();
6970565Sdp } while (err == Z_REPEAT);
69710Sstevel@tonic-gate return (err);
69720Sstevel@tonic-gate }
69730Sstevel@tonic-gate
69740Sstevel@tonic-gate /*
69750Sstevel@tonic-gate * cmd_file is slightly more complicated, as it has to open the command file
69760Sstevel@tonic-gate * and set yyin appropriately. Once that is done, though, it just calls
69770Sstevel@tonic-gate * read_input(), and only once, since prompting is not possible.
69780Sstevel@tonic-gate */
69790Sstevel@tonic-gate
69800Sstevel@tonic-gate static int
cmd_file(char * file)69810Sstevel@tonic-gate cmd_file(char *file)
69820Sstevel@tonic-gate {
69830Sstevel@tonic-gate FILE *infile;
69840Sstevel@tonic-gate int err;
69850Sstevel@tonic-gate struct stat statbuf;
69866215Sgjelinek boolean_t using_real_file = (strcmp(file, "-") != 0);
69870Sstevel@tonic-gate
69880Sstevel@tonic-gate if (using_real_file) {
69890Sstevel@tonic-gate /*
69900Sstevel@tonic-gate * zerr() prints a line number in cmd_file_mode, which we do
69910Sstevel@tonic-gate * not want here, so temporarily unset it.
69920Sstevel@tonic-gate */
69936215Sgjelinek cmd_file_mode = B_FALSE;
69940Sstevel@tonic-gate if ((infile = fopen(file, "r")) == NULL) {
69950Sstevel@tonic-gate zerr(gettext("could not open file %s: %s"),
69960Sstevel@tonic-gate file, strerror(errno));
69970Sstevel@tonic-gate return (Z_ERR);
69980Sstevel@tonic-gate }
69990Sstevel@tonic-gate if ((err = fstat(fileno(infile), &statbuf)) != 0) {
70000Sstevel@tonic-gate zerr(gettext("could not stat file %s: %s"),
70010Sstevel@tonic-gate file, strerror(errno));
70020Sstevel@tonic-gate err = Z_ERR;
70030Sstevel@tonic-gate goto done;
70040Sstevel@tonic-gate }
70050Sstevel@tonic-gate if (!S_ISREG(statbuf.st_mode)) {
70060Sstevel@tonic-gate zerr(gettext("%s is not a regular file."), file);
70070Sstevel@tonic-gate err = Z_ERR;
70080Sstevel@tonic-gate goto done;
70090Sstevel@tonic-gate }
70100Sstevel@tonic-gate yyin = infile;
70116215Sgjelinek cmd_file_mode = B_TRUE;
70126215Sgjelinek ok_to_prompt = B_FALSE;
70130Sstevel@tonic-gate } else {
70140Sstevel@tonic-gate /*
70150Sstevel@tonic-gate * "-f -" is essentially the same as interactive mode,
70160Sstevel@tonic-gate * so treat it that way.
70170Sstevel@tonic-gate */
70186215Sgjelinek interactive_mode = B_TRUE;
70190Sstevel@tonic-gate }
70200Sstevel@tonic-gate /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
70210Sstevel@tonic-gate if ((err = read_input()) == Z_REPEAT)
70220Sstevel@tonic-gate err = Z_ERR;
70230Sstevel@tonic-gate done:
70240Sstevel@tonic-gate if (using_real_file)
70250Sstevel@tonic-gate (void) fclose(infile);
70260Sstevel@tonic-gate return (err);
70270Sstevel@tonic-gate }
70280Sstevel@tonic-gate
70290Sstevel@tonic-gate /*
70300Sstevel@tonic-gate * Since yacc is based on reading from a (FILE *) whereas what we get from
70310Sstevel@tonic-gate * the command line is in argv format, we need to convert when the user
70320Sstevel@tonic-gate * gives us commands directly from the command line. That is done here by
70330Sstevel@tonic-gate * concatenating the argv list into a space-separated string, writing it
70340Sstevel@tonic-gate * to a temp file, and rewinding the file so yyin can be set to it. Then
70350Sstevel@tonic-gate * we call read_input(), and only once, since prompting about whether to
70360Sstevel@tonic-gate * continue or quit would make no sense in this context.
70370Sstevel@tonic-gate */
70380Sstevel@tonic-gate
70390Sstevel@tonic-gate static int
one_command_at_a_time(int argc,char * argv[])70400Sstevel@tonic-gate one_command_at_a_time(int argc, char *argv[])
70410Sstevel@tonic-gate {
70420Sstevel@tonic-gate char *command;
70430Sstevel@tonic-gate size_t len = 2; /* terminal \n\0 */
70440Sstevel@tonic-gate int i, err;
70450Sstevel@tonic-gate
70460Sstevel@tonic-gate for (i = 0; i < argc; i++)
70470Sstevel@tonic-gate len += strlen(argv[i]) + 1;
70480Sstevel@tonic-gate if ((command = malloc(len)) == NULL) {
70496215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
70500Sstevel@tonic-gate return (Z_ERR);
70510Sstevel@tonic-gate }
70520Sstevel@tonic-gate (void) strlcpy(command, argv[0], len);
70530Sstevel@tonic-gate for (i = 1; i < argc; i++) {
70540Sstevel@tonic-gate (void) strlcat(command, " ", len);
70550Sstevel@tonic-gate (void) strlcat(command, argv[i], len);
70560Sstevel@tonic-gate }
70570Sstevel@tonic-gate (void) strlcat(command, "\n", len);
70580Sstevel@tonic-gate err = string_to_yyin(command);
70590Sstevel@tonic-gate free(command);
70600Sstevel@tonic-gate if (err != Z_OK)
70610Sstevel@tonic-gate return (err);
70620Sstevel@tonic-gate while (!feof(yyin))
70630Sstevel@tonic-gate yyparse();
70640Sstevel@tonic-gate return (cleanup());
70650Sstevel@tonic-gate }
70660Sstevel@tonic-gate
70670Sstevel@tonic-gate static char *
get_execbasename(char * execfullname)70680Sstevel@tonic-gate get_execbasename(char *execfullname)
70690Sstevel@tonic-gate {
70700Sstevel@tonic-gate char *last_slash, *execbasename;
70710Sstevel@tonic-gate
70720Sstevel@tonic-gate /* guard against '/' at end of command invocation */
70730Sstevel@tonic-gate for (;;) {
70740Sstevel@tonic-gate last_slash = strrchr(execfullname, '/');
70750Sstevel@tonic-gate if (last_slash == NULL) {
70760Sstevel@tonic-gate execbasename = execfullname;
70770Sstevel@tonic-gate break;
70780Sstevel@tonic-gate } else {
70790Sstevel@tonic-gate execbasename = last_slash + 1;
70800Sstevel@tonic-gate if (*execbasename == '\0') {
70810Sstevel@tonic-gate *last_slash = '\0';
70820Sstevel@tonic-gate continue;
70830Sstevel@tonic-gate }
70840Sstevel@tonic-gate break;
70850Sstevel@tonic-gate }
70860Sstevel@tonic-gate }
70870Sstevel@tonic-gate return (execbasename);
70880Sstevel@tonic-gate }
70890Sstevel@tonic-gate
70900Sstevel@tonic-gate int
main(int argc,char * argv[])70910Sstevel@tonic-gate main(int argc, char *argv[])
70920Sstevel@tonic-gate {
70930Sstevel@tonic-gate int err, arg;
70942303Scarlsonj struct stat st;
70950Sstevel@tonic-gate
70960Sstevel@tonic-gate /* This must be before anything goes to stdout. */
70970Sstevel@tonic-gate setbuf(stdout, NULL);
70980Sstevel@tonic-gate
70996215Sgjelinek saw_error = B_FALSE;
71006215Sgjelinek cmd_file_mode = B_FALSE;
71010Sstevel@tonic-gate execname = get_execbasename(argv[0]);
71020Sstevel@tonic-gate
71030Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
71040Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
71050Sstevel@tonic-gate
71060Sstevel@tonic-gate if (getzoneid() != GLOBAL_ZONEID) {
71070Sstevel@tonic-gate zerr(gettext("%s can only be run from the global zone."),
71080Sstevel@tonic-gate execname);
71090Sstevel@tonic-gate exit(Z_ERR);
71100Sstevel@tonic-gate }
71110Sstevel@tonic-gate
71120Sstevel@tonic-gate if (argc < 2) {
71136215Sgjelinek usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
71140Sstevel@tonic-gate exit(Z_USAGE);
71150Sstevel@tonic-gate }
71160Sstevel@tonic-gate if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
71170Sstevel@tonic-gate (void) one_command_at_a_time(argc - 1, &(argv[1]));
71180Sstevel@tonic-gate exit(Z_OK);
71190Sstevel@tonic-gate }
71200Sstevel@tonic-gate
71212303Scarlsonj while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
71220Sstevel@tonic-gate switch (arg) {
71230Sstevel@tonic-gate case '?':
71240Sstevel@tonic-gate if (optopt == '?')
71256215Sgjelinek usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
71260Sstevel@tonic-gate else
71276215Sgjelinek usage(B_FALSE, HELP_USAGE);
71280Sstevel@tonic-gate exit(Z_USAGE);
71290Sstevel@tonic-gate /* NOTREACHED */
71300Sstevel@tonic-gate case 'f':
71310Sstevel@tonic-gate cmd_file_name = optarg;
71326215Sgjelinek cmd_file_mode = B_TRUE;
71330Sstevel@tonic-gate break;
71342303Scarlsonj case 'R':
71352303Scarlsonj if (*optarg != '/') {
71362303Scarlsonj zerr(gettext("root path must be absolute: %s"),
71372303Scarlsonj optarg);
71382303Scarlsonj exit(Z_USAGE);
71392303Scarlsonj }
71402303Scarlsonj if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
71412303Scarlsonj zerr(gettext(
71422303Scarlsonj "root path must be a directory: %s"),
71432303Scarlsonj optarg);
71442303Scarlsonj exit(Z_USAGE);
71452303Scarlsonj }
71462303Scarlsonj zonecfg_set_root(optarg);
71472303Scarlsonj break;
71480Sstevel@tonic-gate case 'z':
71493247Sgjelinek if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
71506215Sgjelinek global_zone = B_TRUE;
71513247Sgjelinek } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
71526215Sgjelinek zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
71536215Sgjelinek usage(B_FALSE, HELP_SYNTAX);
7154565Sdp exit(Z_USAGE);
7155565Sdp }
7156565Sdp (void) strlcpy(zone, optarg, sizeof (zone));
7157565Sdp (void) strlcpy(revert_zone, optarg, sizeof (zone));
71580Sstevel@tonic-gate break;
71590Sstevel@tonic-gate default:
71606215Sgjelinek usage(B_FALSE, HELP_USAGE);
71610Sstevel@tonic-gate exit(Z_USAGE);
71620Sstevel@tonic-gate }
71630Sstevel@tonic-gate }
71640Sstevel@tonic-gate
7165565Sdp if (optind > argc || strcmp(zone, "") == 0) {
71666215Sgjelinek usage(B_FALSE, HELP_USAGE);
71670Sstevel@tonic-gate exit(Z_USAGE);
71680Sstevel@tonic-gate }
71690Sstevel@tonic-gate
7170565Sdp if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
71716215Sgjelinek read_only_mode = B_FALSE;
7172565Sdp } else if (err == Z_ACCES) {
71736215Sgjelinek read_only_mode = B_TRUE;
71740Sstevel@tonic-gate /* skip this message in one-off from command line mode */
71750Sstevel@tonic-gate if (optind == argc)
71760Sstevel@tonic-gate (void) fprintf(stderr, gettext("WARNING: you do not "
71770Sstevel@tonic-gate "have write access to this zone's configuration "
71780Sstevel@tonic-gate "file;\ngoing into read-only mode.\n"));
7179565Sdp } else {
7180565Sdp fprintf(stderr, "%s: Could not access zone configuration "
7181565Sdp "store: %s\n", execname, zonecfg_strerror(err));
7182565Sdp exit(Z_ERR);
71830Sstevel@tonic-gate }
71840Sstevel@tonic-gate
71850Sstevel@tonic-gate if ((handle = zonecfg_init_handle()) == NULL) {
71866215Sgjelinek zone_perror(execname, Z_NOMEM, B_TRUE);
71870Sstevel@tonic-gate exit(Z_ERR);
71880Sstevel@tonic-gate }
71890Sstevel@tonic-gate
71900Sstevel@tonic-gate /*
71910Sstevel@tonic-gate * This may get set back to FALSE again in cmd_file() if cmd_file_name
71920Sstevel@tonic-gate * is a "real" file as opposed to "-" (i.e. meaning use stdin).
71930Sstevel@tonic-gate */
71940Sstevel@tonic-gate if (isatty(STDIN_FILENO))
71956215Sgjelinek ok_to_prompt = B_TRUE;
71960Sstevel@tonic-gate if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
71970Sstevel@tonic-gate exit(Z_ERR);
71980Sstevel@tonic-gate if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
71990Sstevel@tonic-gate exit(Z_ERR);
72000Sstevel@tonic-gate (void) sigset(SIGINT, SIG_IGN);
72010Sstevel@tonic-gate if (optind == argc) {
72020Sstevel@tonic-gate if (!cmd_file_mode)
72030Sstevel@tonic-gate err = do_interactive();
72040Sstevel@tonic-gate else
72050Sstevel@tonic-gate err = cmd_file(cmd_file_name);
72060Sstevel@tonic-gate } else {
72070Sstevel@tonic-gate err = one_command_at_a_time(argc - optind, &(argv[optind]));
72080Sstevel@tonic-gate }
72090Sstevel@tonic-gate zonecfg_fini_handle(handle);
72102712Snn35248 if (brand != NULL)
72112712Snn35248 brand_close(brand);
72120Sstevel@tonic-gate (void) del_GetLine(gl);
72130Sstevel@tonic-gate return (err);
72140Sstevel@tonic-gate }
7215