4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2014 Gary Mills
29 * zonecfg is a lex/yacc based command interpreter used to manage zone
30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
32 * which takes resources and/or properties as arguments. See the block
33 * comments near the end of zonecfg_grammar.y for how the data structures
34 * which keep track of these resources and properties are built up.
36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
46 * The rest of this module consists of the various function handlers and
47 * their helper functions. Some of these functions, particularly the
48 * X_to_str() functions, which maps command, resource and property numbers
49 * to strings, are used quite liberally, as doing so results in a better
50 * program w/rt I18N, reducing the need for translation notes.
53 #include <sys/mntent.h>
54 #include <sys/varargs.h>
55 #include <sys/sysmacros.h>
56 #include <sys/secflags.h>
67 #include <arpa/inet.h>
76 #include <sys/brand.h>
78 #include <sys/systeminfo.h>
80 #include <libinetutil.h>
84 #include <libzonecfg.h>
87 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
88 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
91 #define PAGER "/usr/bin/more"
92 #define EXEC_PREFIX "exec "
93 #define EXEC_LEN (strlen(EXEC_PREFIX))
102 extern int yyparse(void);
103 extern int lex_lineno
;
105 #define MAX_LINE_LEN 1024
106 #define MAX_CMD_HIST 1024
107 #define MAX_CMD_LEN 1024
109 #define ONE_MB 1048576
112 * Each SHELP_ should be a simple string.
115 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
116 "add <property-name> <property-value>\n\t(resource scope)"
117 #define SHELP_CANCEL "cancel"
118 #define SHELP_CLEAR "clear <property-name>"
119 #define SHELP_COMMIT "commit"
120 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
121 #define SHELP_DELETE "delete [-F]"
122 #define SHELP_END "end"
123 #define SHELP_EXIT "exit [-F]"
124 #define SHELP_EXPORT "export [-f output-file]"
125 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
126 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
127 #define SHELP_REMOVE "remove [-F] <resource-type> " \
128 "[ <property-name>=<property-value> ]*\n" \
129 "\t(global scope)\n" \
130 "remove <property-name> <property-value>\n" \
132 #define SHELP_REVERT "revert [-F]"
133 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
135 #define SHELP_SET "set <property-name>=<property-value>"
136 #define SHELP_VERIFY "verify"
138 static struct help helptab
[] = {
139 { CMD_ADD
, "add", HELP_RES_PROPS
, SHELP_ADD
, },
140 { CMD_CANCEL
, "cancel", 0, SHELP_CANCEL
, },
141 { CMD_CLEAR
, "clear", HELP_PROPS
, SHELP_CLEAR
, },
142 { CMD_COMMIT
, "commit", 0, SHELP_COMMIT
, },
143 { CMD_CREATE
, "create", 0, SHELP_CREATE
, },
144 { CMD_DELETE
, "delete", 0, SHELP_DELETE
, },
145 { CMD_END
, "end", 0, SHELP_END
, },
146 { CMD_EXIT
, "exit", 0, SHELP_EXIT
, },
147 { CMD_EXPORT
, "export", 0, SHELP_EXPORT
, },
148 { CMD_HELP
, "help", 0, SHELP_HELP
},
149 { CMD_INFO
, "info", HELP_RES_PROPS
, SHELP_INFO
, },
150 { CMD_REMOVE
, "remove", HELP_RES_PROPS
, SHELP_REMOVE
, },
151 { CMD_REVERT
, "revert", 0, SHELP_REVERT
, },
152 { CMD_SELECT
, "select", HELP_RES_PROPS
, SHELP_SELECT
, },
153 { CMD_SET
, "set", HELP_PROPS
, SHELP_SET
, },
154 { CMD_VERIFY
, "verify", 0, SHELP_VERIFY
, },
158 #define MAX_RT_STRLEN 16
160 /* These *must* match the order of the RT_ define's from zonecfg.h */
161 char *res_types
[] = {
195 /* These *must* match the order of the PT_ define's from zonecfg.h */
196 char *prop_types
[] = {
245 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
246 static char *prop_val_types
[] = {
253 * The various _cmds[] lists below are for command tab-completion.
257 * remove has a space afterwards because it has qualifiers; the other commands
258 * that have qualifiers (add, select, etc.) don't need a space here because
259 * they have their own _cmds[] lists below.
261 static const char *global_scope_cmds
[] = {
279 static const char *add_cmds
[] = {
290 "add security-flags",
294 static const char *clear_cmds
[] = {
299 "clear scheduling-class",
301 "clear " ALIAS_MAXLWPS
,
302 "clear " ALIAS_MAXSHMMEM
,
303 "clear " ALIAS_MAXSHMIDS
,
304 "clear " ALIAS_MAXMSGIDS
,
305 "clear " ALIAS_MAXSEMIDS
,
306 "clear " ALIAS_SHARES
,
307 "clear " ALIAS_MAXPROCS
,
311 static const char *remove_cmds
[] = {
318 "remove dedicated-cpu ",
319 "remove capped-cpu ",
320 "remove capped-memory ",
322 "remove security-flags",
326 static const char *select_cmds
[] = {
333 "select dedicated-cpu",
335 "select capped-memory",
337 "select security-flags",
341 static const char *set_cmds
[] = {
349 "set scheduling-class=",
351 "set " ALIAS_MAXLWPS
"=",
352 "set " ALIAS_MAXSHMMEM
"=",
353 "set " ALIAS_MAXSHMIDS
"=",
354 "set " ALIAS_MAXMSGIDS
"=",
355 "set " ALIAS_MAXSEMIDS
"=",
356 "set " ALIAS_SHARES
"=",
359 "set " ALIAS_MAXPROCS
"=",
363 static const char *info_cmds
[] = {
370 "info capped-memory",
371 "info dedicated-cpu",
373 "info security-flags",
381 "info scheduling-class",
384 "info max-shm-memory",
392 "info max-processes",
396 static const char *fs_res_scope_cmds
[] = {
412 static const char *net_res_scope_cmds
[] = {
419 "set allowed-address=",
425 static const char *device_res_scope_cmds
[] = {
435 static const char *attr_res_scope_cmds
[] = {
447 static const char *rctl_res_scope_cmds
[] = {
459 static const char *dataset_res_scope_cmds
[] = {
469 static const char *pset_res_scope_cmds
[] = {
481 static const char *pcap_res_scope_cmds
[] = {
491 static const char *mcap_res_scope_cmds
[] = {
506 static const char *admin_res_scope_cmds
[] = {
517 static const char *secflags_res_scope_cmds
[] = {
528 struct xif
*xif_next
;
529 char xif_name
[LIFNAMSIZ
];
530 boolean_t xif_has_address
;
531 boolean_t xif_has_defrouter
;
534 /* Global variables */
536 /* list of network interfaces specified for exclusive IP zone */
539 /* set early in main(), never modified thereafter, used all over the place */
540 static char *execname
;
542 /* set in main(), used all over the place */
543 static zone_dochandle_t handle
;
545 /* used all over the place */
546 static char zone
[ZONENAME_MAX
];
547 static char revert_zone
[ZONENAME_MAX
];
549 /* global brand operations */
550 static brand_handle_t brand
;
552 /* set in modifying functions, checked in read_input() */
553 static boolean_t need_to_commit
= B_FALSE
;
556 /* set in yacc parser, checked in read_input() */
557 boolean_t newline_terminated
;
559 /* set in main(), checked in lex error handler */
560 boolean_t cmd_file_mode
;
562 /* set in exit_func(), checked in read_input() */
563 static boolean_t time_to_exit
= B_FALSE
, force_exit
= B_FALSE
;
565 /* used in short_usage() and zerr() */
566 static char *cmd_file_name
= NULL
;
568 /* checked in read_input() and other places */
569 static boolean_t ok_to_prompt
= B_FALSE
;
571 /* set and checked in initialize() */
572 static boolean_t got_handle
= B_FALSE
;
574 /* initialized in do_interactive(), checked in initialize() */
575 static boolean_t interactive_mode
;
577 /* set if configuring the global zone */
578 static boolean_t global_zone
= B_FALSE
;
580 /* set in main(), checked in multiple places */
581 static boolean_t read_only_mode
;
583 /* scope is outer/global or inner/resource */
584 static boolean_t global_scope
= B_TRUE
;
585 static int resource_scope
; /* should be in the RT_ list from zonecfg.h */
586 static int end_op
= -1; /* operation on end is either add or modify */
588 int num_prop_vals
; /* for grammar */
591 * These are for keeping track of resources as they are specified as part of
592 * the multi-step process. They should be initialized by add_resource() or
593 * select_func() and filled in by add_property() or set_func().
595 static struct zone_fstab old_fstab
, in_progress_fstab
;
596 static struct zone_nwiftab old_nwiftab
, in_progress_nwiftab
;
597 static struct zone_devtab old_devtab
, in_progress_devtab
;
598 static struct zone_rctltab old_rctltab
, in_progress_rctltab
;
599 static struct zone_attrtab old_attrtab
, in_progress_attrtab
;
600 static struct zone_dstab old_dstab
, in_progress_dstab
;
601 static struct zone_psettab old_psettab
, in_progress_psettab
;
602 static struct zone_mcaptab old_mcaptab
, in_progress_mcaptab
;
603 static struct zone_admintab old_admintab
, in_progress_admintab
;
604 static struct zone_secflagstab old_secflagstab
, in_progress_secflagstab
;
606 static GetLine
*gl
; /* The gl_get_line() resource object */
608 static void bytes_to_units(char *str
, char *buf
, int bufsize
);
610 /* Functions begin here */
613 initial_match(const char *line1
, const char *line2
, int word_end
)
617 return (strncmp(line1
, line2
, word_end
) == 0);
621 add_stuff(WordCompletion
*cpl
, const char *line1
, const char **list
,
626 for (i
= 0; list
[i
] != NULL
; i
++) {
627 if (initial_match(line1
, list
[i
], word_end
)) {
628 err
= cpl_add_completion(cpl
, line1
, 0, word_end
,
629 list
[i
] + word_end
, "", "");
639 CPL_MATCH_FN(cmd_cpl_fn
)
643 * The MAX/MIN tests below are to make sure we have at least
644 * enough characters to distinguish from other prefixes (MAX)
645 * but only check MIN(what we have, what we're checking).
647 if (strncmp(line
, "add ", MAX(MIN(word_end
, 4), 1)) == 0)
648 return (add_stuff(cpl
, line
, add_cmds
, word_end
));
649 if (strncmp(line
, "clear ", MAX(MIN(word_end
, 6), 2)) == 0)
650 return (add_stuff(cpl
, line
, clear_cmds
, word_end
));
651 if (strncmp(line
, "select ", MAX(MIN(word_end
, 7), 3)) == 0)
652 return (add_stuff(cpl
, line
, select_cmds
, word_end
));
653 if (strncmp(line
, "set ", MAX(MIN(word_end
, 4), 3)) == 0)
654 return (add_stuff(cpl
, line
, set_cmds
, word_end
));
655 if (strncmp(line
, "remove ", MAX(MIN(word_end
, 7), 1)) == 0)
656 return (add_stuff(cpl
, line
, remove_cmds
, word_end
));
657 if (strncmp(line
, "info ", MAX(MIN(word_end
, 5), 1)) == 0)
658 return (add_stuff(cpl
, line
, info_cmds
, word_end
));
659 return (add_stuff(cpl
, line
, global_scope_cmds
, word_end
));
661 switch (resource_scope
) {
663 return (add_stuff(cpl
, line
, fs_res_scope_cmds
, word_end
));
665 return (add_stuff(cpl
, line
, net_res_scope_cmds
, word_end
));
667 return (add_stuff(cpl
, line
, device_res_scope_cmds
, word_end
));
669 return (add_stuff(cpl
, line
, rctl_res_scope_cmds
, word_end
));
671 return (add_stuff(cpl
, line
, attr_res_scope_cmds
, word_end
));
673 return (add_stuff(cpl
, line
, dataset_res_scope_cmds
, word_end
));
675 return (add_stuff(cpl
, line
, pset_res_scope_cmds
, word_end
));
677 return (add_stuff(cpl
, line
, pcap_res_scope_cmds
, word_end
));
679 return (add_stuff(cpl
, line
, mcap_res_scope_cmds
, word_end
));
681 return (add_stuff(cpl
, line
, admin_res_scope_cmds
, word_end
));
683 return (add_stuff(cpl
, line
, secflags_res_scope_cmds
,
691 * For the main CMD_func() functions below, several of them call getopt()
692 * then check optind against argc to make sure an extra parameter was not
693 * passed in. The reason this is not caught in the grammar is that the
694 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
695 * be "-F" (for example), but could be anything. So (for example) this
696 * check will prevent "create bogus".
702 return (calloc(1, sizeof (cmd_t
)));
710 for (i
= 0; i
< MAX_EQ_PROP_PAIRS
; i
++)
711 if (cmd
->cmd_property_ptr
[i
] != NULL
) {
712 property_value_ptr_t pp
= cmd
->cmd_property_ptr
[i
];
714 switch (pp
->pv_type
) {
715 case PROP_VAL_SIMPLE
:
718 case PROP_VAL_COMPLEX
:
719 free_complex(pp
->pv_complex
);
722 free_list(pp
->pv_list
);
726 for (i
= 0; i
< cmd
->cmd_argc
; i
++)
727 free(cmd
->cmd_argv
[i
]);
731 complex_property_ptr_t
734 return (calloc(1, sizeof (complex_property_t
)));
738 free_complex(complex_property_ptr_t
complex)
742 free_complex(complex->cp_next
);
743 free(complex->cp_value
);
750 return (calloc(1, sizeof (list_property_t
)));
754 free_list(list_property_ptr_t list
)
758 free(list
->lp_simple
);
759 free_complex(list
->lp_complex
);
760 free_list(list
->lp_next
);
765 free_outer_list(list_property_ptr_t list
)
769 free_outer_list(list
->lp_next
);
773 static struct zone_rctlvaltab
*
774 alloc_rctlvaltab(void)
776 return (calloc(1, sizeof (struct zone_rctlvaltab
)));
780 rt_to_str(int res_type
)
782 assert(res_type
>= RT_MIN
&& res_type
<= RT_MAX
);
783 return (res_types
[res_type
]);
787 pt_to_str(int prop_type
)
789 assert(prop_type
>= PT_MIN
&& prop_type
<= PT_MAX
);
790 return (prop_types
[prop_type
]);
794 pvt_to_str(int pv_type
)
796 assert(pv_type
>= PROP_VAL_MIN
&& pv_type
<= PROP_VAL_MAX
);
797 return (prop_val_types
[pv_type
]);
801 cmd_to_str(int cmd_num
)
803 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
804 return (helptab
[cmd_num
].cmd_name
);
809 zerr(const char *fmt
, ...)
812 static int last_lineno
;
814 /* lex_lineno has already been incremented in the lexer; compensate */
815 if (cmd_file_mode
&& lex_lineno
> last_lineno
) {
816 if (strcmp(cmd_file_name
, "-") == 0)
817 (void) fprintf(stderr
, gettext("On line %d:\n"),
820 (void) fprintf(stderr
, gettext("On line %d of %s:\n"),
821 lex_lineno
- 1, cmd_file_name
);
822 last_lineno
= lex_lineno
;
824 va_start(alist
, fmt
);
825 (void) vfprintf(stderr
, fmt
, alist
);
826 (void) fprintf(stderr
, "\n");
831 * This is a separate function rather than a set of define's because of the
832 * gettext() wrapping.
837 * Each string below should have \t follow \n whenever needed; the
838 * initial \t and the terminal \n will be provided by the calling function.
842 long_help(int cmd_num
)
844 static char line
[1024]; /* arbitrary large amount */
846 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
849 return (gettext("Prints help message."));
851 (void) snprintf(line
, sizeof (line
),
852 gettext("Creates a configuration for the "
853 "specified zone. %s should be\n\tused to "
854 "begin configuring a new zone. If overwriting an "
855 "existing\n\tconfiguration, the -F flag can be "
856 "used to force the action. If\n\t-t template is "
857 "given, creates a configuration identical to the\n"
858 "\tspecified template, except that the zone name "
859 "is changed from\n\ttemplate to zonename. '%s -a' "
860 "creates a configuration from a\n\tdetached "
861 "zonepath. '%s -b' results in a blank "
862 "configuration.\n\t'%s' with no arguments applies "
863 "the Sun default settings."),
864 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
),
865 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
));
868 return (gettext("Exits the program. The -F flag can "
869 "be used to force the action."));
871 return (gettext("Prints configuration to standard "
872 "output, or to output-file if\n\tspecified, in "
873 "a form suitable for use in a command-file."));
875 return (gettext("Add specified resource to "
878 return (gettext("Deletes the specified zone. The -F "
879 "flag can be used to force the\n\taction."));
881 return (gettext("Remove specified resource from "
882 "configuration. The -F flag can be used\n\tto "
883 "force the action."));
885 (void) snprintf(line
, sizeof (line
),
886 gettext("Selects a resource to modify. "
887 "Resource modification is completed\n\twith the "
888 "command \"%s\". The property name/value pairs "
889 "must uniquely\n\tidentify a resource. Note that "
890 "the curly braces ('{', '}') mean one\n\tor more "
891 "of whatever is between them."),
892 cmd_to_str(CMD_END
));
895 return (gettext("Sets property values."));
897 return (gettext("Clears property values."));
899 return (gettext("Displays information about the "
900 "current configuration. If resource\n\ttype is "
901 "specified, displays only information about "
902 "resources of\n\tthe relevant type. If resource "
903 "id is specified, displays only\n\tinformation "
904 "about that resource."));
906 return (gettext("Verifies current configuration "
907 "for correctness (some resource types\n\thave "
908 "required properties)."));
910 (void) snprintf(line
, sizeof (line
),
911 gettext("Commits current configuration. "
912 "Configuration must be committed to\n\tbe used by "
913 "%s. Until the configuration is committed, "
914 "changes \n\tcan be removed with the %s "
915 "command. This operation is\n\tattempted "
916 "automatically upon completion of a %s "
917 "session."), "zoneadm", cmd_to_str(CMD_REVERT
),
921 return (gettext("Reverts configuration back to the "
922 "last committed state. The -F flag\n\tcan be "
923 "used to force the action."));
925 return (gettext("Cancels resource/property "
928 return (gettext("Ends resource/property "
936 * Return the input filename appended to each component of the path
937 * or the filename itself if it is absolute.
938 * Parameters: path string, file name, output string.
941 exec_cat(const char *s1
, const char *s2
, char *si
)
944 /* Number of remaining characters in s */
945 int cnt
= PATH_MAX
+ 1;
948 while (*s1
&& *s1
!= ':') { /* Copy first component of path to si */
956 if (si
!= s
&& cnt
> 0) { /* Add slash if s2 is not absolute */
960 while (*s2
&& cnt
> 0) { /* Copy s2 to si */
964 *s
= '\0'; /* Terminate the output string */
965 return (*s1
? ++s1
: NULL
); /* Return next path component or NULL */
968 /* Determine that a name exists in PATH */
970 path_find(const char *name
)
973 char fname
[PATH_MAX
+ 2];
975 struct stat stat_buf
;
977 if ((pathstr
= getenv("PATH")) == NULL
) {
978 if (geteuid() == 0 || getuid() == 0)
979 pathstr
= "/usr/sbin:/usr/bin";
981 pathstr
= "/usr/bin:";
983 cp
= strchr(name
, '/') ? (const char *) "" : pathstr
;
986 cp
= exec_cat(cp
, name
, fname
);
987 if (stat(fname
, &stat_buf
) != -1) {
988 /* successful find of the file */
991 } while (cp
!= NULL
);
1000 char *pager
, *space
;
1002 pager
= getenv("PAGER");
1003 if (pager
== NULL
|| *pager
== '\0')
1006 space
= strchr(pager
, ' ');
1009 if (path_find(pager
) == 0) {
1012 if ((newfp
= popen(pager
, "w")) == NULL
)
1013 zerr(gettext("PAGER open failed (%s)."),
1017 zerr(gettext("PAGER %s does not exist (%s)."),
1018 pager
, strerror(errno
));
1024 pager_close(FILE *fp
)
1028 status
= pclose(fp
);
1030 zerr(gettext("PAGER close failed (%s)."),
1035 * Called with verbose TRUE when help is explicitly requested, FALSE for
1036 * unexpected errors.
1040 usage(boolean_t verbose
, uint_t flags
)
1042 FILE *fp
= verbose
? stdout
: stderr
;
1044 boolean_t need_to_close
= B_FALSE
;
1047 /* don't page error output */
1048 if (verbose
&& interactive_mode
) {
1049 if ((newfp
= pager_open()) != NULL
) {
1050 need_to_close
= B_TRUE
;
1055 if (flags
& HELP_META
) {
1056 (void) fprintf(fp
, gettext("More help is available for the "
1058 (void) fprintf(fp
, "\n\tcommands ('%s commands')\n",
1059 cmd_to_str(CMD_HELP
));
1060 (void) fprintf(fp
, "\tsyntax ('%s syntax')\n",
1061 cmd_to_str(CMD_HELP
));
1062 (void) fprintf(fp
, "\tusage ('%s usage')\n\n",
1063 cmd_to_str(CMD_HELP
));
1064 (void) fprintf(fp
, gettext("You may also obtain help on any "
1065 "command by typing '%s <command-name>.'\n"),
1066 cmd_to_str(CMD_HELP
));
1068 if (flags
& HELP_RES_SCOPE
) {
1069 switch (resource_scope
) {
1071 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1072 "used to configure a file-system.\n"),
1073 rt_to_str(resource_scope
));
1074 (void) fprintf(fp
, gettext("Valid commands:\n"));
1075 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1076 pt_to_str(PT_DIR
), gettext("<path>"));
1077 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1078 pt_to_str(PT_SPECIAL
), gettext("<path>"));
1079 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1080 pt_to_str(PT_RAW
), gettext("<raw-device>"));
1081 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1082 pt_to_str(PT_TYPE
), gettext("<file-system type>"));
1083 (void) fprintf(fp
, "\t%s %s %s\n", cmd_to_str(CMD_ADD
),
1084 pt_to_str(PT_OPTIONS
),
1085 gettext("<file-system options>"));
1086 (void) fprintf(fp
, "\t%s %s %s\n",
1087 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_OPTIONS
),
1088 gettext("<file-system options>"));
1089 (void) fprintf(fp
, gettext("Consult the file-system "
1090 "specific manual page, such as mount_ufs(8), "
1091 "for\ndetails about file-system options. Note "
1092 "that any file-system options with an\nembedded "
1093 "'=' character must be enclosed in double quotes, "
1095 "such as \"%s=5\".\n"), MNTOPT_RETRY
);
1098 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1099 "used to configure a network interface.\n"),
1100 rt_to_str(resource_scope
));
1101 (void) fprintf(fp
, gettext("Valid commands:\n"));
1102 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1103 pt_to_str(PT_ADDRESS
), gettext("<IP-address>"));
1104 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1105 pt_to_str(PT_ALLOWED_ADDRESS
),
1106 gettext("<IP-address>"));
1107 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1108 pt_to_str(PT_PHYSICAL
), gettext("<interface>"));
1109 (void) fprintf(fp
, gettext("See ifconfig(8) for "
1110 "details of the <interface> string.\n"));
1111 (void) fprintf(fp
, gettext("%s %s is valid "
1112 "if the %s property is set to %s, otherwise it "
1113 "must not be set.\n"),
1114 cmd_to_str(CMD_SET
), pt_to_str(PT_ADDRESS
),
1115 pt_to_str(PT_IPTYPE
), gettext("shared"));
1116 (void) fprintf(fp
, gettext("%s %s is valid "
1117 "if the %s property is set to %s, otherwise it "
1118 "must not be set.\n"),
1119 cmd_to_str(CMD_SET
), pt_to_str(PT_ALLOWED_ADDRESS
),
1120 pt_to_str(PT_IPTYPE
), gettext("exclusive"));
1121 (void) fprintf(fp
, gettext("\t%s %s=%s\n%s %s "
1122 "is valid if the %s or %s property is set, "
1123 "otherwise it must not be set\n"),
1124 cmd_to_str(CMD_SET
),
1125 pt_to_str(PT_DEFROUTER
), gettext("<IP-address>"),
1126 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFROUTER
),
1127 gettext(pt_to_str(PT_ADDRESS
)),
1128 gettext(pt_to_str(PT_ALLOWED_ADDRESS
)));
1131 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1132 "used to configure a device node.\n"),
1133 rt_to_str(resource_scope
));
1134 (void) fprintf(fp
, gettext("Valid commands:\n"));
1135 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1136 pt_to_str(PT_MATCH
), gettext("<device-path>"));
1139 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1140 "used to configure a resource control.\n"),
1141 rt_to_str(resource_scope
));
1142 (void) fprintf(fp
, gettext("Valid commands:\n"));
1143 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1144 pt_to_str(PT_NAME
), gettext("<string>"));
1145 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1146 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
1147 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1148 pt_to_str(PT_LIMIT
), gettext("<number>"),
1149 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1150 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1151 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_VALUE
),
1152 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1153 pt_to_str(PT_LIMIT
), gettext("<number>"),
1154 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1155 (void) fprintf(fp
, "%s\n\t%s := privileged\n"
1156 "\t%s := none | deny\n", gettext("Where"),
1157 gettext("<priv-value>"), gettext("<action-value>"));
1160 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1161 "used to configure a generic attribute.\n"),
1162 rt_to_str(resource_scope
));
1163 (void) fprintf(fp
, gettext("Valid commands:\n"));
1164 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1165 pt_to_str(PT_NAME
), gettext("<name>"));
1166 (void) fprintf(fp
, "\t%s %s=boolean\n",
1167 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1168 (void) fprintf(fp
, "\t%s %s=true | false\n",
1169 cmd_to_str(CMD_SET
), pt_to_str(PT_VALUE
));
1170 (void) fprintf(fp
, gettext("or\n"));
1171 (void) fprintf(fp
, "\t%s %s=int\n", cmd_to_str(CMD_SET
),
1172 pt_to_str(PT_TYPE
));
1173 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1174 pt_to_str(PT_VALUE
), gettext("<integer>"));
1175 (void) fprintf(fp
, gettext("or\n"));
1176 (void) fprintf(fp
, "\t%s %s=string\n",
1177 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1178 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1179 pt_to_str(PT_VALUE
), gettext("<string>"));
1180 (void) fprintf(fp
, gettext("or\n"));
1181 (void) fprintf(fp
, "\t%s %s=uint\n",
1182 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1183 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1184 pt_to_str(PT_VALUE
), gettext("<unsigned integer>"));
1187 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1188 "used to export ZFS datasets.\n"),
1189 rt_to_str(resource_scope
));
1190 (void) fprintf(fp
, gettext("Valid commands:\n"));
1191 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1192 pt_to_str(PT_NAME
), gettext("<name>"));
1195 (void) fprintf(fp
, gettext("The '%s' resource scope "
1196 "configures the 'pools' facility to dedicate\na "
1197 "subset of the system's processors to this zone "
1198 "while it is running.\n"),
1199 rt_to_str(resource_scope
));
1200 (void) fprintf(fp
, gettext("Valid commands:\n"));
1201 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1202 pt_to_str(PT_NCPUS
),
1203 gettext("<unsigned integer | range>"));
1204 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1205 pt_to_str(PT_IMPORTANCE
),
1206 gettext("<unsigned integer>"));
1209 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1210 "used to set an upper limit (a cap) on the\n"
1211 "percentage of CPU that can be used by this zone. "
1212 "A '%s' value of 1\ncorresponds to one cpu. The "
1213 "value can be set higher than 1, up to the total\n"
1214 "number of CPUs on the system. The value can "
1215 "also be less than 1,\nrepresenting a fraction of "
1217 rt_to_str(resource_scope
), pt_to_str(PT_NCPUS
));
1218 (void) fprintf(fp
, gettext("Valid commands:\n"));
1219 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1220 pt_to_str(PT_NCPUS
), gettext("<unsigned decimal>"));
1223 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1224 "used to set an upper limit (a cap) on the\n"
1225 "amount of physical memory, swap space and locked "
1226 "memory that can be used by\nthis zone.\n"),
1227 rt_to_str(resource_scope
));
1228 (void) fprintf(fp
, gettext("Valid commands:\n"));
1229 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1230 pt_to_str(PT_PHYSICAL
),
1231 gettext("<qualified unsigned decimal>"));
1232 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1234 gettext("<qualified unsigned decimal>"));
1235 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1236 pt_to_str(PT_LOCKED
),
1237 gettext("<qualified unsigned decimal>"));
1240 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1241 "used to delegate specific zone management\n"
1242 "rights to users and roles. These rights are "
1243 "only applicable to this zone.\n"),
1244 rt_to_str(resource_scope
));
1245 (void) fprintf(fp
, gettext("Valid commands:\n"));
1246 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1248 gettext("<single user or role name>"));
1249 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1250 pt_to_str(PT_AUTHS
),
1251 gettext("<comma separated list>"));
1254 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1255 "used to specify the default security-flags\n"
1256 "of this zone, and their upper and lower bound.\n"),
1257 rt_to_str(resource_scope
));
1258 (void) fprintf(fp
, "\t%s %s=%s\n",
1259 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFAULT
),
1260 gettext("<security flags>"));
1261 (void) fprintf(fp
, "\t%s %s=%s\n",
1262 cmd_to_str(CMD_SET
), pt_to_str(PT_LOWER
),
1263 gettext("<security flags>"));
1264 (void) fprintf(fp
, "\t%s %s=%s\n",
1265 cmd_to_str(CMD_SET
), pt_to_str(PT_UPPER
),
1266 gettext("<security flags>"));
1269 (void) fprintf(fp
, gettext("And from any resource scope, you "
1271 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_END
),
1272 gettext("(to conclude this operation)"));
1273 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL
),
1274 gettext("(to cancel this operation)"));
1275 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_EXIT
),
1276 gettext("(to exit the zonecfg utility)"));
1278 if (flags
& HELP_USAGE
) {
1279 (void) fprintf(fp
, "%s:\t%s %s\n", gettext("usage"),
1280 execname
, cmd_to_str(CMD_HELP
));
1281 (void) fprintf(fp
, "\t%s -z <zone>\t\t\t(%s)\n",
1282 execname
, gettext("interactive"));
1283 (void) fprintf(fp
, "\t%s -z <zone> <command>\n", execname
);
1284 (void) fprintf(fp
, "\t%s -z <zone> -f <command-file>\n",
1287 if (flags
& HELP_SUBCMDS
) {
1288 (void) fprintf(fp
, "%s:\n\n", gettext("Commands"));
1289 for (i
= 0; i
<= CMD_MAX
; i
++) {
1290 (void) fprintf(fp
, "%s\n", helptab
[i
].short_usage
);
1292 (void) fprintf(fp
, "\t%s\n\n", long_help(i
));
1295 if (flags
& HELP_SYNTAX
) {
1297 (void) fprintf(fp
, "\n");
1298 (void) fprintf(fp
, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1299 (void) fprintf(fp
, gettext("\t(except the reserved words "
1300 "'%s' and anything starting with '%s')\n"), "global",
1303 gettext("\tName must be less than %d characters.\n"),
1306 (void) fprintf(fp
, "\n");
1308 if (flags
& HELP_NETADDR
) {
1309 (void) fprintf(fp
, gettext("\n<net-addr> :="));
1311 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
1313 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1315 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1316 (void) fprintf(fp
, gettext("See inet(3SOCKET) for IPv4 and "
1317 "IPv6 address syntax.\n"));
1318 (void) fprintf(fp
, gettext("<IPv4-prefix-length> := [0-32]\n"));
1320 gettext("<IPv6-prefix-length> := [0-128]\n"));
1322 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1324 if (flags
& HELP_RESOURCES
) {
1325 (void) fprintf(fp
, "<%s> := %s | %s | %s | %s | %s |\n\t"
1326 "%s | %s | %s | %s | %s\n\n",
1327 gettext("resource type"), rt_to_str(RT_FS
),
1328 rt_to_str(RT_NET
), rt_to_str(RT_DEVICE
),
1329 rt_to_str(RT_RCTL
), rt_to_str(RT_ATTR
),
1330 rt_to_str(RT_DATASET
), rt_to_str(RT_DCPU
),
1331 rt_to_str(RT_PCAP
), rt_to_str(RT_MCAP
),
1332 rt_to_str(RT_ADMIN
), rt_to_str(RT_SECFLAGS
));
1334 if (flags
& HELP_PROPS
) {
1335 (void) fprintf(fp
, gettext("For resource type ... there are "
1336 "property types ...:\n"));
1337 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1338 pt_to_str(PT_ZONENAME
));
1339 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1340 pt_to_str(PT_ZONEPATH
));
1341 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1342 pt_to_str(PT_BRAND
));
1343 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1344 pt_to_str(PT_AUTOBOOT
));
1345 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1346 pt_to_str(PT_BOOTARGS
));
1347 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1348 pt_to_str(PT_POOL
));
1349 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1350 pt_to_str(PT_LIMITPRIV
));
1351 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1352 pt_to_str(PT_SCHED
));
1353 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1354 pt_to_str(PT_IPTYPE
));
1355 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1356 pt_to_str(PT_HOSTID
));
1357 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1358 pt_to_str(PT_FS_ALLOWED
));
1359 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1360 pt_to_str(PT_MAXLWPS
));
1361 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1362 pt_to_str(PT_MAXPROCS
));
1363 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1364 pt_to_str(PT_MAXSHMMEM
));
1365 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1366 pt_to_str(PT_MAXSHMIDS
));
1367 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1368 pt_to_str(PT_MAXMSGIDS
));
1369 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1370 pt_to_str(PT_MAXSEMIDS
));
1371 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1372 pt_to_str(PT_SHARES
));
1373 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s, %s, %s\n",
1374 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
1375 pt_to_str(PT_SPECIAL
), pt_to_str(PT_RAW
),
1376 pt_to_str(PT_TYPE
), pt_to_str(PT_OPTIONS
));
1377 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET
),
1378 pt_to_str(PT_ADDRESS
), pt_to_str(PT_ALLOWED_ADDRESS
),
1379 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_DEFROUTER
));
1380 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE
),
1381 pt_to_str(PT_MATCH
));
1382 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL
),
1383 pt_to_str(PT_NAME
), pt_to_str(PT_VALUE
));
1384 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR
),
1385 pt_to_str(PT_NAME
), pt_to_str(PT_TYPE
),
1386 pt_to_str(PT_VALUE
));
1387 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DATASET
),
1388 pt_to_str(PT_NAME
));
1389 (void) fprintf(fp
, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU
),
1390 pt_to_str(PT_NCPUS
), pt_to_str(PT_IMPORTANCE
));
1391 (void) fprintf(fp
, "\t%s\t%s\n", rt_to_str(RT_PCAP
),
1392 pt_to_str(PT_NCPUS
));
1393 (void) fprintf(fp
, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP
),
1394 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_SWAP
),
1395 pt_to_str(PT_LOCKED
));
1396 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN
),
1397 pt_to_str(PT_USER
), pt_to_str(PT_AUTHS
));
1398 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n",
1399 rt_to_str(RT_SECFLAGS
), pt_to_str(PT_DEFAULT
),
1400 pt_to_str(PT_LOWER
), pt_to_str(PT_UPPER
));
1403 (void) pager_close(fp
);
1407 zone_perror(char *prefix
, int err
, boolean_t set_saw
)
1409 zerr("%s: %s", prefix
, zonecfg_strerror(err
));
1415 * zone_perror() expects a single string, but for remove and select
1416 * we have both the command and the resource type, so this wrapper
1417 * function serves the same purpose in a slightly different way.
1421 z_cmd_rt_perror(int cmd_num
, int res_num
, int err
, boolean_t set_saw
)
1423 zerr("%s %s: %s", cmd_to_str(cmd_num
), rt_to_str(res_num
),
1424 zonecfg_strerror(err
));
1429 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1431 initialize(boolean_t handle_expected
)
1434 char brandname
[MAXNAMELEN
];
1436 if (zonecfg_check_handle(handle
) != Z_OK
) {
1437 if ((err
= zonecfg_get_handle(zone
, handle
)) == Z_OK
) {
1438 got_handle
= B_TRUE
;
1439 if (zonecfg_get_brand(handle
, brandname
,
1440 sizeof (brandname
)) != Z_OK
) {
1441 zerr("Zone %s is inconsistent: missing "
1442 "brand attribute", zone
);
1445 if ((brand
= brand_open(brandname
)) == NULL
) {
1446 zerr("Zone %s uses non-existent brand \"%s\"."
1447 " Unable to continue", zone
, brandname
);
1451 * If the user_attr file is newer than
1452 * the zone config file, the admins
1453 * may need to be updated since the
1454 * RBAC files are authoritative for
1455 * authorization checks.
1457 err
= zonecfg_update_userauths(handle
, zone
);
1459 zerr(gettext("The administrative rights "
1460 "were updated to match "
1461 "the current RBAC configuration.\n"
1462 "Use \"info admin\" and \"revert\" to "
1463 "compare with the previous settings."));
1464 need_to_commit
= B_TRUE
;
1465 } else if (err
!= Z_NO_ENTRY
) {
1466 zerr(gettext("failed to update "
1469 } else if (need_to_commit
) {
1470 zerr(gettext("admin rights were updated "
1471 "to match RBAC configuration."));
1474 } else if (global_zone
&& err
== Z_NO_ZONE
&& !got_handle
&&
1477 * We implicitly create the global zone config if it
1480 zone_dochandle_t tmphandle
;
1482 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1483 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1487 err
= zonecfg_get_template_handle("SUNWblank", zone
,
1491 zonecfg_fini_handle(tmphandle
);
1492 zone_perror("SUNWblank", err
, B_TRUE
);
1496 need_to_commit
= B_TRUE
;
1497 zonecfg_fini_handle(handle
);
1499 got_handle
= B_TRUE
;
1502 zone_perror(zone
, err
, handle_expected
|| got_handle
);
1503 if (err
== Z_NO_ZONE
&& !got_handle
&&
1504 interactive_mode
&& !read_only_mode
)
1505 (void) printf(gettext("Use '%s' to begin "
1506 "configuring a new zone.\n"),
1507 cmd_to_str(CMD_CREATE
));
1515 state_atleast(zone_state_t state
)
1517 zone_state_t state_num
;
1520 if ((err
= zone_get_state(zone
, &state_num
)) != Z_OK
) {
1521 /* all states are greater than "non-existent" */
1522 if (err
== Z_NO_ZONE
)
1524 zerr(gettext("Unexpectedly failed to determine state "
1525 "of zone %s: %s"), zone
, zonecfg_strerror(err
));
1528 return (state_num
>= state
);
1532 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
1536 short_usage(int command
)
1538 /* lex_lineno has already been incremented in the lexer; compensate */
1539 if (cmd_file_mode
) {
1540 if (strcmp(cmd_file_name
, "-") == 0)
1541 (void) fprintf(stderr
,
1542 gettext("syntax error on line %d\n"),
1545 (void) fprintf(stderr
,
1546 gettext("syntax error on line %d of %s\n"),
1547 lex_lineno
- 1, cmd_file_name
);
1549 (void) fprintf(stderr
, "%s:\n%s\n", gettext("usage"),
1550 helptab
[command
].short_usage
);
1555 * long_usage() is for bad semantics: e.g., wrong property type for a given
1556 * resource type. It is also used by longer_usage() below.
1560 long_usage(uint_t cmd_num
, boolean_t set_saw
)
1562 (void) fprintf(set_saw
? stderr
: stdout
, "%s:\n%s\n", gettext("usage"),
1563 helptab
[cmd_num
].short_usage
);
1564 (void) fprintf(set_saw
? stderr
: stdout
, "\t%s\n", long_help(cmd_num
));
1570 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
1571 * any extra usage() flags as appropriate for whatever command.
1575 longer_usage(uint_t cmd_num
)
1577 long_usage(cmd_num
, B_FALSE
);
1578 if (helptab
[cmd_num
].flags
!= 0) {
1579 (void) printf("\n");
1580 usage(B_TRUE
, helptab
[cmd_num
].flags
);
1585 * scope_usage() is simply used when a command is called from the wrong scope.
1589 scope_usage(uint_t cmd_num
)
1591 zerr(gettext("The %s command only makes sense in the %s scope."),
1592 cmd_to_str(cmd_num
),
1593 global_scope
? gettext("resource") : gettext("global"));
1598 * On input, B_TRUE => yes, B_FALSE => no.
1599 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
1603 ask_yesno(boolean_t default_answer
, const char *question
)
1605 char line
[64]; /* should be enough to answer yes or no */
1607 if (!ok_to_prompt
) {
1612 if (printf("%s (%s)? ", question
,
1613 default_answer
? "[y]/n" : "y/[n]") < 0)
1615 if (fgets(line
, sizeof (line
), stdin
) == NULL
)
1618 if (line
[0] == '\n')
1619 return (default_answer
? 1 : 0);
1620 if (tolower(line
[0]) == 'y')
1622 if (tolower(line
[0]) == 'n')
1628 * Prints warning if zone already exists.
1629 * In interactive mode, prompts if we should continue anyway and returns Z_OK
1630 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
1632 * Note that if a zone exists and its state is >= INSTALLED, an error message
1633 * will be printed and this function will return Z_ERR regardless of mode.
1637 check_if_zone_already_exists(boolean_t force
)
1639 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
1640 zone_dochandle_t tmphandle
;
1643 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1644 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1647 res
= zonecfg_get_handle(zone
, tmphandle
);
1648 zonecfg_fini_handle(tmphandle
);
1652 if (state_atleast(ZONE_STATE_INSTALLED
)) {
1653 zerr(gettext("Zone %s already installed; %s not allowed."),
1654 zone
, cmd_to_str(CMD_CREATE
));
1659 (void) printf(gettext("Zone %s already exists; overwriting.\n"),
1663 (void) snprintf(line
, sizeof (line
),
1664 gettext("Zone %s already exists; %s anyway"), zone
,
1665 cmd_to_str(CMD_CREATE
));
1666 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
1667 zerr(gettext("Zone exists, input not from terminal and -F not "
1668 "specified:\n%s command ignored, exiting."),
1669 cmd_to_str(CMD_CREATE
));
1672 return (answer
== 1 ? Z_OK
: Z_ERR
);
1676 zone_is_read_only(int cmd_num
)
1678 if (strncmp(zone
, "SUNW", 4) == 0) {
1679 zerr(gettext("%s: zones beginning with SUNW are read-only."),
1684 if (read_only_mode
) {
1685 zerr(gettext("%s: cannot %s in read-only mode."), zone
,
1686 cmd_to_str(cmd_num
));
1694 * Create a new configuration.
1697 create_func(cmd_t
*cmd
)
1700 char zone_template
[ZONENAME_MAX
];
1701 char attach_path
[MAXPATHLEN
];
1702 zone_dochandle_t tmphandle
;
1703 boolean_t force
= B_FALSE
;
1704 boolean_t attach
= B_FALSE
;
1705 boolean_t arg_err
= B_FALSE
;
1707 assert(cmd
!= NULL
);
1709 /* This is the default if no arguments are given. */
1710 (void) strlcpy(zone_template
, "SUNWdefault", sizeof (zone_template
));
1713 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?a:bFt:"))
1718 longer_usage(CMD_CREATE
);
1720 short_usage(CMD_CREATE
);
1724 (void) strlcpy(attach_path
, optarg
,
1725 sizeof (attach_path
));
1729 (void) strlcpy(zone_template
, "SUNWblank",
1730 sizeof (zone_template
));
1736 (void) strlcpy(zone_template
, optarg
,
1737 sizeof (zone_template
));
1740 short_usage(CMD_CREATE
);
1748 if (optind
!= cmd
->cmd_argc
) {
1749 short_usage(CMD_CREATE
);
1753 if (zone_is_read_only(CMD_CREATE
))
1756 if (check_if_zone_already_exists(force
) != Z_OK
)
1760 * Get a temporary handle first. If that fails, the old handle
1761 * will not be lost. Then finish whichever one we don't need,
1762 * to avoid leaks. Then get the handle for zone_template, and
1763 * set the name to zone: this "copy, rename" method is how
1764 * create -[b|t] works.
1766 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1767 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1772 err
= zonecfg_get_attach_handle(attach_path
, ZONE_DETACHED
,
1773 zone
, B_FALSE
, tmphandle
);
1775 err
= zonecfg_get_template_handle(zone_template
, zone
,
1779 zonecfg_fini_handle(tmphandle
);
1780 if (attach
&& err
== Z_NO_ZONE
)
1781 (void) fprintf(stderr
, gettext("invalid path to "
1782 "detached zone\n"));
1783 else if (attach
&& err
== Z_INVALID_DOCUMENT
)
1784 (void) fprintf(stderr
, gettext("Cannot attach to an "
1785 "earlier release of the operating system\n"));
1787 zone_perror(zone_template
, err
, B_TRUE
);
1791 need_to_commit
= B_TRUE
;
1792 zonecfg_fini_handle(handle
);
1794 got_handle
= B_TRUE
;
1798 * This malloc()'s memory, which must be freed by the caller.
1801 quoteit(char *instr
)
1804 size_t outstrsize
= strlen(instr
) + 3; /* 2 quotes + '\0' */
1806 if ((outstr
= malloc(outstrsize
)) == NULL
) {
1807 zone_perror(zone
, Z_NOMEM
, B_FALSE
);
1810 if (strchr(instr
, ' ') == NULL
) {
1811 (void) strlcpy(outstr
, instr
, outstrsize
);
1814 (void) snprintf(outstr
, outstrsize
, "\"%s\"", instr
);
1819 export_prop(FILE *of
, int prop_num
, char *prop_id
)
1823 if (strlen(prop_id
) == 0)
1825 quote_str
= quoteit(prop_id
);
1826 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1827 pt_to_str(prop_num
), quote_str
);
1832 export_func(cmd_t
*cmd
)
1834 struct zone_nwiftab nwiftab
;
1835 struct zone_fstab fstab
;
1836 struct zone_devtab devtab
;
1837 struct zone_attrtab attrtab
;
1838 struct zone_rctltab rctltab
;
1839 struct zone_dstab dstab
;
1840 struct zone_psettab psettab
;
1841 struct zone_mcaptab mcaptab
;
1842 struct zone_rctlvaltab
*valptr
;
1843 struct zone_admintab admintab
;
1844 struct zone_secflagstab secflagstab
;
1846 char zonepath
[MAXPATHLEN
], outfile
[MAXPATHLEN
], pool
[MAXNAMELEN
];
1847 char bootargs
[BOOTARGS_MAX
];
1848 char sched
[MAXNAMELEN
];
1849 char brand
[MAXNAMELEN
];
1850 char hostidp
[HW_HOSTID_LEN
];
1851 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
1855 zone_iptype_t iptype
;
1856 boolean_t need_to_close
= B_FALSE
;
1857 boolean_t arg_err
= B_FALSE
;
1859 assert(cmd
!= NULL
);
1863 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?f:")) != EOF
) {
1867 longer_usage(CMD_EXPORT
);
1869 short_usage(CMD_EXPORT
);
1873 (void) strlcpy(outfile
, optarg
, sizeof (outfile
));
1876 short_usage(CMD_EXPORT
);
1884 if (optind
!= cmd
->cmd_argc
) {
1885 short_usage(CMD_EXPORT
);
1888 if (strlen(outfile
) == 0) {
1891 if ((of
= fopen(outfile
, "w")) == NULL
) {
1892 zerr(gettext("opening file %s: %s"),
1893 outfile
, strerror(errno
));
1897 need_to_close
= B_TRUE
;
1900 if ((err
= initialize(B_TRUE
)) != Z_OK
)
1903 (void) fprintf(of
, "%s -b\n", cmd_to_str(CMD_CREATE
));
1905 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
&&
1906 strlen(zonepath
) > 0)
1907 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1908 pt_to_str(PT_ZONEPATH
), zonepath
);
1910 if ((zone_get_brand(zone
, brand
, sizeof (brand
)) == Z_OK
) &&
1911 (strcmp(brand
, NATIVE_BRAND_NAME
) != 0))
1912 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1913 pt_to_str(PT_BRAND
), brand
);
1915 if (zonecfg_get_autoboot(handle
, &autoboot
) == Z_OK
)
1916 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1917 pt_to_str(PT_AUTOBOOT
), autoboot
? "true" : "false");
1919 if (zonecfg_get_bootargs(handle
, bootargs
, sizeof (bootargs
)) == Z_OK
&&
1920 strlen(bootargs
) > 0) {
1921 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1922 pt_to_str(PT_BOOTARGS
), bootargs
);
1925 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
1927 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1928 pt_to_str(PT_POOL
), pool
);
1930 if (zonecfg_get_limitpriv(handle
, &limitpriv
) == Z_OK
&&
1931 strlen(limitpriv
) > 0) {
1932 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1933 pt_to_str(PT_LIMITPRIV
), limitpriv
);
1937 if (zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)) == Z_OK
&&
1939 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1940 pt_to_str(PT_SCHED
), sched
);
1942 if (zonecfg_get_iptype(handle
, &iptype
) == Z_OK
) {
1945 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1946 pt_to_str(PT_IPTYPE
), "shared");
1949 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1950 pt_to_str(PT_IPTYPE
), "exclusive");
1955 if (zonecfg_get_hostid(handle
, hostidp
, sizeof (hostidp
)) == Z_OK
) {
1956 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1957 pt_to_str(PT_HOSTID
), hostidp
);
1960 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
1961 sizeof (fsallowedp
)) == Z_OK
) {
1962 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1963 pt_to_str(PT_FS_ALLOWED
), fsallowedp
);
1966 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
1967 zone_perror(zone
, err
, B_FALSE
);
1970 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
1971 zone_fsopt_t
*optptr
;
1973 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
1975 export_prop(of
, PT_DIR
, fstab
.zone_fs_dir
);
1976 export_prop(of
, PT_SPECIAL
, fstab
.zone_fs_special
);
1977 export_prop(of
, PT_RAW
, fstab
.zone_fs_raw
);
1978 export_prop(of
, PT_TYPE
, fstab
.zone_fs_type
);
1979 for (optptr
= fstab
.zone_fs_options
; optptr
!= NULL
;
1980 optptr
= optptr
->zone_fsopt_next
) {
1982 * Simple property values with embedded equal signs
1983 * need to be quoted to prevent the lexer from
1984 * mis-parsing them as complex name=value pairs.
1986 if (strchr(optptr
->zone_fsopt_opt
, '='))
1987 (void) fprintf(of
, "%s %s \"%s\"\n",
1988 cmd_to_str(CMD_ADD
),
1989 pt_to_str(PT_OPTIONS
),
1990 optptr
->zone_fsopt_opt
);
1992 (void) fprintf(of
, "%s %s %s\n",
1993 cmd_to_str(CMD_ADD
),
1994 pt_to_str(PT_OPTIONS
),
1995 optptr
->zone_fsopt_opt
);
1997 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
1998 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
2000 (void) zonecfg_endfsent(handle
);
2002 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
2003 zone_perror(zone
, err
, B_FALSE
);
2006 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
2007 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2009 export_prop(of
, PT_ADDRESS
, nwiftab
.zone_nwif_address
);
2010 export_prop(of
, PT_ALLOWED_ADDRESS
,
2011 nwiftab
.zone_nwif_allowed_address
);
2012 export_prop(of
, PT_PHYSICAL
, nwiftab
.zone_nwif_physical
);
2013 export_prop(of
, PT_DEFROUTER
, nwiftab
.zone_nwif_defrouter
);
2014 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2016 (void) zonecfg_endnwifent(handle
);
2018 if ((err
= zonecfg_setdevent(handle
)) != Z_OK
) {
2019 zone_perror(zone
, err
, B_FALSE
);
2022 while (zonecfg_getdevent(handle
, &devtab
) == Z_OK
) {
2023 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2024 rt_to_str(RT_DEVICE
));
2025 export_prop(of
, PT_MATCH
, devtab
.zone_dev_match
);
2026 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2028 (void) zonecfg_enddevent(handle
);
2030 if (zonecfg_getmcapent(handle
, &mcaptab
) == Z_OK
) {
2033 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2034 rt_to_str(RT_MCAP
));
2035 bytes_to_units(mcaptab
.zone_physmem_cap
, buf
, sizeof (buf
));
2036 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2037 pt_to_str(PT_PHYSICAL
), buf
);
2038 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2041 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
2042 zone_perror(zone
, err
, B_FALSE
);
2045 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
2046 (void) fprintf(of
, "%s rctl\n", cmd_to_str(CMD_ADD
));
2047 export_prop(of
, PT_NAME
, rctltab
.zone_rctl_name
);
2048 for (valptr
= rctltab
.zone_rctl_valptr
; valptr
!= NULL
;
2049 valptr
= valptr
->zone_rctlval_next
) {
2050 fprintf(of
, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2051 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
2052 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
2053 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
2054 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
2056 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2057 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
2059 (void) zonecfg_endrctlent(handle
);
2061 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
2062 zone_perror(zone
, err
, B_FALSE
);
2065 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
2066 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2067 rt_to_str(RT_ATTR
));
2068 export_prop(of
, PT_NAME
, attrtab
.zone_attr_name
);
2069 export_prop(of
, PT_TYPE
, attrtab
.zone_attr_type
);
2070 export_prop(of
, PT_VALUE
, attrtab
.zone_attr_value
);
2071 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2073 (void) zonecfg_endattrent(handle
);
2075 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
2076 zone_perror(zone
, err
, B_FALSE
);
2079 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
2080 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2081 rt_to_str(RT_DATASET
));
2082 export_prop(of
, PT_NAME
, dstab
.zone_dataset_name
);
2083 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2085 (void) zonecfg_enddsent(handle
);
2087 if (zonecfg_getpsetent(handle
, &psettab
) == Z_OK
) {
2088 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2089 rt_to_str(RT_DCPU
));
2090 if (strcmp(psettab
.zone_ncpu_min
, psettab
.zone_ncpu_max
) == 0)
2091 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2092 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_max
);
2094 (void) fprintf(of
, "%s %s=%s-%s\n", cmd_to_str(CMD_SET
),
2095 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_min
,
2096 psettab
.zone_ncpu_max
);
2097 if (psettab
.zone_importance
[0] != '\0')
2098 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2099 pt_to_str(PT_IMPORTANCE
), psettab
.zone_importance
);
2100 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2103 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
2104 zone_perror(zone
, err
, B_FALSE
);
2107 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
2108 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2109 rt_to_str(RT_ADMIN
));
2110 export_prop(of
, PT_USER
, admintab
.zone_admin_user
);
2111 export_prop(of
, PT_AUTHS
, admintab
.zone_admin_auths
);
2112 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2115 (void) zonecfg_endadminent(handle
);
2117 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
2118 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2119 rt_to_str(RT_SECFLAGS
));
2120 export_prop(of
, PT_DEFAULT
, secflagstab
.zone_secflags_default
);
2121 export_prop(of
, PT_LOWER
, secflagstab
.zone_secflags_lower
);
2122 export_prop(of
, PT_UPPER
, secflagstab
.zone_secflags_upper
);
2123 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2127 * There is nothing to export for pcap since this resource is just
2128 * a container for an rctl alias.
2137 exit_func(cmd_t
*cmd
)
2140 boolean_t arg_err
= B_FALSE
;
2143 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2146 longer_usage(CMD_EXIT
);
2150 force_exit
= B_TRUE
;
2153 short_usage(CMD_EXIT
);
2161 if (optind
< cmd
->cmd_argc
) {
2162 short_usage(CMD_EXIT
);
2166 if (global_scope
|| force_exit
) {
2167 time_to_exit
= B_TRUE
;
2171 answer
= ask_yesno(B_FALSE
, "Resource incomplete; really quit");
2173 zerr(gettext("Resource incomplete, input "
2174 "not from terminal and -F not specified:\n%s command "
2175 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT
));
2177 } else if (answer
== 1) {
2178 time_to_exit
= B_TRUE
;
2180 /* (answer == 0) => just return */
2184 validate_zonepath_syntax(char *path
)
2186 if (path
[0] != '/') {
2187 zerr(gettext("%s is not an absolute path."), path
);
2190 /* If path is all slashes, then fail */
2191 if (strspn(path
, "/") == strlen(path
)) {
2192 zerr(gettext("/ is not allowed as a %s."),
2193 pt_to_str(PT_ZONEPATH
));
2200 add_resource(cmd_t
*cmd
)
2203 struct zone_psettab tmp_psettab
;
2204 struct zone_mcaptab tmp_mcaptab
;
2205 struct zone_secflagstab tmp_secflagstab
;
2208 char pool
[MAXNAMELEN
];
2210 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
2211 long_usage(CMD_ADD
, B_TRUE
);
2217 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
2220 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
2223 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
2227 zerr(gettext("WARNING: Setting a global zone resource "
2228 "control too low could deny\nservice "
2229 "to even the root user; "
2230 "this could render the system impossible\n"
2231 "to administer. Please use caution."));
2232 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
2235 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
2238 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
2241 /* Make sure there isn't already a cpu-set or cpu-cap entry. */
2242 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2243 zerr(gettext("The %s resource already exists."),
2244 rt_to_str(RT_DCPU
));
2247 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) !=
2249 zerr(gettext("The %s resource already exists."),
2250 rt_to_str(RT_PCAP
));
2254 /* Make sure the pool property isn't set. */
2255 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
2257 zerr(gettext("The %s property is already set. "
2258 "A persistent pool is incompatible with\nthe %s "
2260 pt_to_str(PT_POOL
), rt_to_str(RT_DCPU
));
2264 bzero(&in_progress_psettab
, sizeof (in_progress_psettab
));
2268 * Make sure there isn't already a cpu-set or incompatible
2271 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2272 zerr(gettext("The %s resource already exists."),
2273 rt_to_str(RT_DCPU
));
2277 switch (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
)) {
2278 case Z_ALIAS_DISALLOW
:
2279 zone_perror(rt_to_str(RT_PCAP
), Z_ALIAS_DISALLOW
,
2284 zerr(gettext("The %s resource already exists."),
2285 rt_to_str(RT_PCAP
));
2294 * Make sure there isn't already a mem-cap entry or max-swap
2295 * or max-locked rctl.
2297 if (zonecfg_lookup_mcap(handle
, &tmp_mcaptab
) == Z_OK
||
2298 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp_mcap
)
2300 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
2301 &tmp_mcap
) == Z_OK
) {
2302 zerr(gettext("The %s resource or a related resource "
2303 "control already exists."), rt_to_str(RT_MCAP
));
2307 zerr(gettext("WARNING: Setting a global zone memory "
2308 "cap too low could deny\nservice "
2309 "to even the root user; "
2310 "this could render the system impossible\n"
2311 "to administer. Please use caution."));
2312 bzero(&in_progress_mcaptab
, sizeof (in_progress_mcaptab
));
2315 bzero(&in_progress_admintab
, sizeof (in_progress_admintab
));
2318 /* Make sure we haven't already set this */
2319 if (zonecfg_lookup_secflags(handle
, &tmp_secflagstab
) == Z_OK
)
2320 zerr(gettext("The %s resource already exists."),
2321 rt_to_str(RT_SECFLAGS
));
2322 bzero(&in_progress_secflagstab
,
2323 sizeof (in_progress_secflagstab
));
2326 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2327 long_usage(CMD_ADD
, B_TRUE
);
2328 usage(B_FALSE
, HELP_RESOURCES
);
2331 global_scope
= B_TRUE
;
2336 do_complex_rctl_val(complex_property_ptr_t cp
)
2338 struct zone_rctlvaltab
*rctlvaltab
;
2339 complex_property_ptr_t cx
;
2340 boolean_t seen_priv
= B_FALSE
, seen_limit
= B_FALSE
,
2341 seen_action
= B_FALSE
;
2345 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
2346 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
2349 for (cx
= cp
; cx
!= NULL
; cx
= cx
->cp_next
) {
2350 switch (cx
->cp_type
) {
2353 zerr(gettext("%s already specified"),
2354 pt_to_str(PT_PRIV
));
2357 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
2359 sizeof (rctlvaltab
->zone_rctlval_priv
));
2364 zerr(gettext("%s already specified"),
2365 pt_to_str(PT_LIMIT
));
2368 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
2370 sizeof (rctlvaltab
->zone_rctlval_limit
));
2371 seen_limit
= B_TRUE
;
2375 zerr(gettext("%s already specified"),
2376 pt_to_str(PT_ACTION
));
2379 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
2381 sizeof (rctlvaltab
->zone_rctlval_action
));
2382 seen_action
= B_TRUE
;
2385 zone_perror(pt_to_str(PT_VALUE
),
2386 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2387 long_usage(CMD_ADD
, B_TRUE
);
2388 usage(B_FALSE
, HELP_PROPS
);
2389 zonecfg_free_rctl_value_list(rctlvaltab
);
2394 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV
));
2396 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT
));
2398 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION
));
2399 if (!seen_priv
|| !seen_limit
|| !seen_action
)
2401 rctlvaltab
->zone_rctlval_next
= NULL
;
2402 rctlblk
= alloca(rctlblk_size());
2404 * Make sure the rctl value looks roughly correct; we won't know if
2405 * it's truly OK until we verify the configuration on the target
2408 if (zonecfg_construct_rctlblk(rctlvaltab
, rctlblk
) != Z_OK
||
2409 !zonecfg_valid_rctlblk(rctlblk
)) {
2410 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL
),
2411 pt_to_str(PT_VALUE
));
2414 err
= zonecfg_add_rctl_value(&in_progress_rctltab
, rctlvaltab
);
2416 zone_perror(pt_to_str(PT_VALUE
), err
, B_TRUE
);
2420 zonecfg_free_rctl_value_list(rctlvaltab
);
2424 add_property(cmd_t
*cmd
)
2427 int err
, res_type
, prop_type
;
2428 property_value_ptr_t pp
;
2429 list_property_ptr_t l
;
2431 res_type
= resource_scope
;
2432 prop_type
= cmd
->cmd_prop_name
[0];
2433 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
2434 long_usage(CMD_ADD
, B_TRUE
);
2438 if (cmd
->cmd_prop_nv_pairs
!= 1) {
2439 long_usage(CMD_ADD
, B_TRUE
);
2443 if (initialize(B_TRUE
) != Z_OK
)
2448 if (prop_type
!= PT_OPTIONS
) {
2449 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2451 long_usage(CMD_ADD
, B_TRUE
);
2452 usage(B_FALSE
, HELP_PROPS
);
2455 pp
= cmd
->cmd_property_ptr
[0];
2456 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
2457 pp
->pv_type
!= PROP_VAL_LIST
) {
2458 zerr(gettext("A %s or %s value was expected here."),
2459 pvt_to_str(PROP_VAL_SIMPLE
),
2460 pvt_to_str(PROP_VAL_LIST
));
2464 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
2465 if (pp
->pv_simple
== NULL
) {
2466 long_usage(CMD_ADD
, B_TRUE
);
2469 prop_id
= pp
->pv_simple
;
2470 err
= zonecfg_add_fs_option(&in_progress_fstab
,
2473 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
2475 list_property_ptr_t list
;
2477 for (list
= pp
->pv_list
; list
!= NULL
;
2478 list
= list
->lp_next
) {
2479 prop_id
= list
->lp_simple
;
2480 if (prop_id
== NULL
)
2482 err
= zonecfg_add_fs_option(
2483 &in_progress_fstab
, prop_id
);
2485 zone_perror(pt_to_str(prop_type
), err
,
2491 if (prop_type
!= PT_VALUE
) {
2492 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2494 long_usage(CMD_ADD
, B_TRUE
);
2495 usage(B_FALSE
, HELP_PROPS
);
2498 pp
= cmd
->cmd_property_ptr
[0];
2499 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
2500 pp
->pv_type
!= PROP_VAL_LIST
) {
2501 zerr(gettext("A %s or %s value was expected here."),
2502 pvt_to_str(PROP_VAL_COMPLEX
),
2503 pvt_to_str(PROP_VAL_LIST
));
2507 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
2508 do_complex_rctl_val(pp
->pv_complex
);
2511 for (l
= pp
->pv_list
; l
!= NULL
; l
= l
->lp_next
)
2512 do_complex_rctl_val(l
->lp_complex
);
2515 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2516 long_usage(CMD_ADD
, B_TRUE
);
2517 usage(B_FALSE
, HELP_RESOURCES
);
2523 gz_invalid_resource(int type
)
2525 return (global_zone
&& (type
== RT_FS
||
2526 type
== RT_NET
|| type
== RT_DEVICE
|| type
== RT_ATTR
||
2527 type
== RT_DATASET
));
2531 gz_invalid_rt_property(int type
)
2533 return (global_zone
&& (type
== RT_ZONENAME
|| type
== RT_ZONEPATH
||
2534 type
== RT_AUTOBOOT
|| type
== RT_LIMITPRIV
||
2535 type
== RT_BOOTARGS
|| type
== RT_BRAND
|| type
== RT_SCHED
||
2536 type
== RT_IPTYPE
|| type
== RT_HOSTID
|| type
== RT_FS_ALLOWED
));
2540 gz_invalid_property(int type
)
2542 return (global_zone
&& (type
== PT_ZONENAME
|| type
== PT_ZONEPATH
||
2543 type
== PT_AUTOBOOT
|| type
== PT_LIMITPRIV
||
2544 type
== PT_BOOTARGS
|| type
== PT_BRAND
|| type
== PT_SCHED
||
2545 type
== PT_IPTYPE
|| type
== PT_HOSTID
|| type
== PT_FS_ALLOWED
));
2549 add_func(cmd_t
*cmd
)
2552 boolean_t arg_err
= B_FALSE
;
2554 assert(cmd
!= NULL
);
2557 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
2560 longer_usage(CMD_ADD
);
2564 short_usage(CMD_ADD
);
2572 if (optind
!= cmd
->cmd_argc
) {
2573 short_usage(CMD_ADD
);
2577 if (zone_is_read_only(CMD_ADD
))
2580 if (initialize(B_TRUE
) != Z_OK
)
2583 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
2584 zerr(gettext("Cannot add a %s resource to the "
2585 "global zone."), rt_to_str(cmd
->cmd_res_type
));
2590 global_scope
= B_FALSE
;
2591 resource_scope
= cmd
->cmd_res_type
;
2599 * This routine has an unusual implementation, because it tries very
2600 * hard to succeed in the face of a variety of failure modes.
2601 * The most common and most vexing occurs when the index file and
2602 * the /etc/zones/<zonename.xml> file are not both present. In
2603 * this case, delete must eradicate as much of the zone state as is left
2604 * so that the user can later create a new zone with the same name.
2607 delete_func(cmd_t
*cmd
)
2609 int err
, arg
, answer
;
2610 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
2611 boolean_t force
= B_FALSE
;
2612 boolean_t arg_err
= B_FALSE
;
2615 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2618 longer_usage(CMD_DELETE
);
2625 short_usage(CMD_DELETE
);
2633 if (optind
!= cmd
->cmd_argc
) {
2634 short_usage(CMD_DELETE
);
2638 if (zone_is_read_only(CMD_DELETE
))
2643 * Initialize sets up the global called "handle" and warns the
2644 * user if the zone is not configured. In force mode, we don't
2645 * trust that evaluation, and hence skip it. (We don't need the
2646 * handle to be loaded anyway, since zonecfg_destroy is done by
2647 * zonename). However, we also have to take care to emulate the
2648 * messages spit out by initialize; see below.
2650 if (initialize(B_TRUE
) != Z_OK
)
2653 (void) snprintf(line
, sizeof (line
),
2654 gettext("Are you sure you want to delete zone %s"), zone
);
2655 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
2656 zerr(gettext("Input not from terminal and -F not "
2657 "specified:\n%s command ignored, exiting."),
2658 cmd_to_str(CMD_DELETE
));
2666 * This function removes the authorizations from user_attr
2667 * that correspond to those specified in the configuration
2669 if (initialize(B_TRUE
) == Z_OK
) {
2670 (void) zonecfg_deauthorize_users(handle
, zone
);
2672 if ((err
= zonecfg_destroy(zone
, force
)) != Z_OK
) {
2673 if ((err
== Z_BAD_ZONE_STATE
) && !force
) {
2674 zerr(gettext("Zone %s not in %s state; %s not "
2675 "allowed. Use -F to force %s."),
2676 zone
, zone_state_str(ZONE_STATE_CONFIGURED
),
2677 cmd_to_str(CMD_DELETE
), cmd_to_str(CMD_DELETE
));
2679 zone_perror(zone
, err
, B_TRUE
);
2682 need_to_commit
= B_FALSE
;
2685 * Emulate initialize's messaging; if there wasn't a valid handle to
2686 * begin with, then user had typed delete (or delete -F) multiple
2687 * times. So we emit a message.
2689 * We only do this in the 'force' case because normally, initialize()
2690 * takes care of this for us.
2692 if (force
&& zonecfg_check_handle(handle
) != Z_OK
&& interactive_mode
)
2693 (void) printf(gettext("Use '%s' to begin "
2694 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE
));
2697 * Time for a new handle: finish the old one off first
2698 * then get a new one properly to avoid leaks.
2701 zonecfg_fini_handle(handle
);
2702 if ((handle
= zonecfg_init_handle()) == NULL
) {
2703 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
2706 if ((err
= zonecfg_get_handle(zone
, handle
)) != Z_OK
) {
2707 /* If there was no zone before, that's OK */
2708 if (err
!= Z_NO_ZONE
)
2709 zone_perror(zone
, err
, B_TRUE
);
2710 got_handle
= B_FALSE
;
2716 fill_in_fstab(cmd_t
*cmd
, struct zone_fstab
*fstab
, boolean_t fill_in_only
)
2719 property_value_ptr_t pp
;
2721 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2724 bzero(fstab
, sizeof (*fstab
));
2725 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2726 pp
= cmd
->cmd_property_ptr
[i
];
2727 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2728 zerr(gettext("A simple value was expected here."));
2730 return (Z_INSUFFICIENT_SPEC
);
2732 switch (cmd
->cmd_prop_name
[i
]) {
2734 (void) strlcpy(fstab
->zone_fs_dir
, pp
->pv_simple
,
2735 sizeof (fstab
->zone_fs_dir
));
2738 (void) strlcpy(fstab
->zone_fs_special
, pp
->pv_simple
,
2739 sizeof (fstab
->zone_fs_special
));
2742 (void) strlcpy(fstab
->zone_fs_raw
, pp
->pv_simple
,
2743 sizeof (fstab
->zone_fs_raw
));
2746 (void) strlcpy(fstab
->zone_fs_type
, pp
->pv_simple
,
2747 sizeof (fstab
->zone_fs_type
));
2750 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2751 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2752 return (Z_INSUFFICIENT_SPEC
);
2757 return (zonecfg_lookup_filesystem(handle
, fstab
));
2761 fill_in_nwiftab(cmd_t
*cmd
, struct zone_nwiftab
*nwiftab
,
2762 boolean_t fill_in_only
)
2765 property_value_ptr_t pp
;
2767 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2770 bzero(nwiftab
, sizeof (*nwiftab
));
2771 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2772 pp
= cmd
->cmd_property_ptr
[i
];
2773 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2774 zerr(gettext("A simple value was expected here."));
2776 return (Z_INSUFFICIENT_SPEC
);
2778 switch (cmd
->cmd_prop_name
[i
]) {
2780 (void) strlcpy(nwiftab
->zone_nwif_address
,
2781 pp
->pv_simple
, sizeof (nwiftab
->zone_nwif_address
));
2783 case PT_ALLOWED_ADDRESS
:
2784 (void) strlcpy(nwiftab
->zone_nwif_allowed_address
,
2786 sizeof (nwiftab
->zone_nwif_allowed_address
));
2789 (void) strlcpy(nwiftab
->zone_nwif_physical
,
2791 sizeof (nwiftab
->zone_nwif_physical
));
2794 (void) strlcpy(nwiftab
->zone_nwif_defrouter
,
2796 sizeof (nwiftab
->zone_nwif_defrouter
));
2799 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2800 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2801 return (Z_INSUFFICIENT_SPEC
);
2806 err
= zonecfg_lookup_nwif(handle
, nwiftab
);
2811 fill_in_devtab(cmd_t
*cmd
, struct zone_devtab
*devtab
, boolean_t fill_in_only
)
2814 property_value_ptr_t pp
;
2816 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2819 bzero(devtab
, sizeof (*devtab
));
2820 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2821 pp
= cmd
->cmd_property_ptr
[i
];
2822 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2823 zerr(gettext("A simple value was expected here."));
2825 return (Z_INSUFFICIENT_SPEC
);
2827 switch (cmd
->cmd_prop_name
[i
]) {
2829 (void) strlcpy(devtab
->zone_dev_match
, pp
->pv_simple
,
2830 sizeof (devtab
->zone_dev_match
));
2833 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2834 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2835 return (Z_INSUFFICIENT_SPEC
);
2840 err
= zonecfg_lookup_dev(handle
, devtab
);
2845 fill_in_rctltab(cmd_t
*cmd
, struct zone_rctltab
*rctltab
,
2846 boolean_t fill_in_only
)
2849 property_value_ptr_t pp
;
2851 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2854 bzero(rctltab
, sizeof (*rctltab
));
2855 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2856 pp
= cmd
->cmd_property_ptr
[i
];
2857 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2858 zerr(gettext("A simple value was expected here."));
2860 return (Z_INSUFFICIENT_SPEC
);
2862 switch (cmd
->cmd_prop_name
[i
]) {
2864 (void) strlcpy(rctltab
->zone_rctl_name
, pp
->pv_simple
,
2865 sizeof (rctltab
->zone_rctl_name
));
2868 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2869 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2870 return (Z_INSUFFICIENT_SPEC
);
2875 err
= zonecfg_lookup_rctl(handle
, rctltab
);
2880 fill_in_attrtab(cmd_t
*cmd
, struct zone_attrtab
*attrtab
,
2881 boolean_t fill_in_only
)
2884 property_value_ptr_t pp
;
2886 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2889 bzero(attrtab
, sizeof (*attrtab
));
2890 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2891 pp
= cmd
->cmd_property_ptr
[i
];
2892 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2893 zerr(gettext("A simple value was expected here."));
2895 return (Z_INSUFFICIENT_SPEC
);
2897 switch (cmd
->cmd_prop_name
[i
]) {
2899 (void) strlcpy(attrtab
->zone_attr_name
, pp
->pv_simple
,
2900 sizeof (attrtab
->zone_attr_name
));
2903 (void) strlcpy(attrtab
->zone_attr_type
, pp
->pv_simple
,
2904 sizeof (attrtab
->zone_attr_type
));
2907 (void) strlcpy(attrtab
->zone_attr_value
, pp
->pv_simple
,
2908 sizeof (attrtab
->zone_attr_value
));
2911 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2912 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2913 return (Z_INSUFFICIENT_SPEC
);
2918 err
= zonecfg_lookup_attr(handle
, attrtab
);
2923 fill_in_dstab(cmd_t
*cmd
, struct zone_dstab
*dstab
, boolean_t fill_in_only
)
2926 property_value_ptr_t pp
;
2928 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2931 dstab
->zone_dataset_name
[0] = '\0';
2932 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2933 pp
= cmd
->cmd_property_ptr
[i
];
2934 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2935 zerr(gettext("A simple value was expected here."));
2937 return (Z_INSUFFICIENT_SPEC
);
2939 switch (cmd
->cmd_prop_name
[i
]) {
2941 (void) strlcpy(dstab
->zone_dataset_name
, pp
->pv_simple
,
2942 sizeof (dstab
->zone_dataset_name
));
2945 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2946 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2947 return (Z_INSUFFICIENT_SPEC
);
2952 return (zonecfg_lookup_ds(handle
, dstab
));
2956 fill_in_admintab(cmd_t
*cmd
, struct zone_admintab
*admintab
,
2957 boolean_t fill_in_only
)
2960 property_value_ptr_t pp
;
2962 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2965 bzero(admintab
, sizeof (*admintab
));
2966 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2967 pp
= cmd
->cmd_property_ptr
[i
];
2968 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2969 zerr(gettext("A simple value was expected here."));
2971 return (Z_INSUFFICIENT_SPEC
);
2973 switch (cmd
->cmd_prop_name
[i
]) {
2975 (void) strlcpy(admintab
->zone_admin_user
, pp
->pv_simple
,
2976 sizeof (admintab
->zone_admin_user
));
2979 (void) strlcpy(admintab
->zone_admin_auths
,
2980 pp
->pv_simple
, sizeof (admintab
->zone_admin_auths
));
2983 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2984 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2985 return (Z_INSUFFICIENT_SPEC
);
2990 err
= zonecfg_lookup_admin(handle
, admintab
);
2995 fill_in_secflagstab(cmd_t
*cmd
, struct zone_secflagstab
*secflagstab
,
2996 boolean_t fill_in_only
)
2999 property_value_ptr_t pp
;
3001 if ((err
= initialize(B_TRUE
)) != Z_OK
)
3004 bzero(secflagstab
, sizeof (*secflagstab
));
3005 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
3006 pp
= cmd
->cmd_property_ptr
[i
];
3007 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
3008 zerr(gettext("A simple value was expected here."));
3010 return (Z_INSUFFICIENT_SPEC
);
3012 switch (cmd
->cmd_prop_name
[i
]) {
3014 (void) strlcpy(secflagstab
->zone_secflags_default
,
3016 sizeof (secflagstab
->zone_secflags_default
));
3019 (void) strlcpy(secflagstab
->zone_secflags_lower
,
3021 sizeof (secflagstab
->zone_secflags_lower
));
3024 (void) strlcpy(secflagstab
->zone_secflags_upper
,
3026 sizeof (secflagstab
->zone_secflags_upper
));
3029 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
3030 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3031 return (Z_INSUFFICIENT_SPEC
);
3037 err
= zonecfg_lookup_secflags(handle
, secflagstab
);
3043 remove_aliased_rctl(int type
, char *name
)
3048 if ((err
= zonecfg_get_aliased_rctl(handle
, name
, &tmp
)) != Z_OK
) {
3049 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3050 zonecfg_strerror(err
));
3054 if ((err
= zonecfg_rm_aliased_rctl(handle
, name
)) != Z_OK
) {
3055 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3056 zonecfg_strerror(err
));
3059 need_to_commit
= B_TRUE
;
3064 prompt_remove_resource(cmd_t
*cmd
, char *rsrc
)
3069 boolean_t force
= B_FALSE
;
3071 boolean_t arg_err
= B_FALSE
;
3074 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
3088 num
= zonecfg_num_resources(handle
, rsrc
);
3091 z_cmd_rt_perror(CMD_REMOVE
, cmd
->cmd_res_type
, Z_NO_ENTRY
,
3095 if (num
> 1 && !force
) {
3096 if (!interactive_mode
) {
3097 zerr(gettext("There are multiple instances of this "
3098 "resource. Either qualify the resource to\n"
3099 "remove a single instance or use the -F option to "
3100 "remove all instances."));
3104 (void) snprintf(prompt
, sizeof (prompt
), gettext(
3105 "Are you sure you want to remove ALL '%s' resources"),
3107 answer
= ask_yesno(B_FALSE
, prompt
);
3109 zerr(gettext("Resource incomplete."));
3119 remove_fs(cmd_t
*cmd
)
3123 /* traditional, qualified fs removal */
3124 if (cmd
->cmd_prop_nv_pairs
> 0) {
3125 struct zone_fstab fstab
;
3127 if ((err
= fill_in_fstab(cmd
, &fstab
, B_FALSE
)) != Z_OK
) {
3128 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3131 if ((err
= zonecfg_delete_filesystem(handle
, &fstab
)) != Z_OK
)
3132 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3134 need_to_commit
= B_TRUE
;
3135 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
3140 * unqualified fs removal. remove all fs's but prompt if more
3143 if (!prompt_remove_resource(cmd
, "fs"))
3146 if ((err
= zonecfg_del_all_resources(handle
, "fs")) != Z_OK
)
3147 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3149 need_to_commit
= B_TRUE
;
3153 remove_net(cmd_t
*cmd
)
3157 /* traditional, qualified net removal */
3158 if (cmd
->cmd_prop_nv_pairs
> 0) {
3159 struct zone_nwiftab nwiftab
;
3161 if ((err
= fill_in_nwiftab(cmd
, &nwiftab
, B_FALSE
)) != Z_OK
) {
3162 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3165 if ((err
= zonecfg_delete_nwif(handle
, &nwiftab
)) != Z_OK
)
3166 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3168 need_to_commit
= B_TRUE
;
3173 * unqualified net removal. remove all nets but prompt if more
3176 if (!prompt_remove_resource(cmd
, "net"))
3179 if ((err
= zonecfg_del_all_resources(handle
, "net")) != Z_OK
)
3180 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3182 need_to_commit
= B_TRUE
;
3186 remove_device(cmd_t
*cmd
)
3190 /* traditional, qualified device removal */
3191 if (cmd
->cmd_prop_nv_pairs
> 0) {
3192 struct zone_devtab devtab
;
3194 if ((err
= fill_in_devtab(cmd
, &devtab
, B_FALSE
)) != Z_OK
) {
3195 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3198 if ((err
= zonecfg_delete_dev(handle
, &devtab
)) != Z_OK
)
3199 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3201 need_to_commit
= B_TRUE
;
3206 * unqualified device removal. remove all devices but prompt if more
3209 if (!prompt_remove_resource(cmd
, "device"))
3212 if ((err
= zonecfg_del_all_resources(handle
, "device")) != Z_OK
)
3213 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3215 need_to_commit
= B_TRUE
;
3219 remove_attr(cmd_t
*cmd
)
3223 /* traditional, qualified attr removal */
3224 if (cmd
->cmd_prop_nv_pairs
> 0) {
3225 struct zone_attrtab attrtab
;
3227 if ((err
= fill_in_attrtab(cmd
, &attrtab
, B_FALSE
)) != Z_OK
) {
3228 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3231 if ((err
= zonecfg_delete_attr(handle
, &attrtab
)) != Z_OK
)
3232 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3234 need_to_commit
= B_TRUE
;
3239 * unqualified attr removal. remove all attrs but prompt if more
3242 if (!prompt_remove_resource(cmd
, "attr"))
3245 if ((err
= zonecfg_del_all_resources(handle
, "attr")) != Z_OK
)
3246 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3248 need_to_commit
= B_TRUE
;
3252 remove_dataset(cmd_t
*cmd
)
3256 /* traditional, qualified dataset removal */
3257 if (cmd
->cmd_prop_nv_pairs
> 0) {
3258 struct zone_dstab dstab
;
3260 if ((err
= fill_in_dstab(cmd
, &dstab
, B_FALSE
)) != Z_OK
) {
3261 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3264 if ((err
= zonecfg_delete_ds(handle
, &dstab
)) != Z_OK
)
3265 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3267 need_to_commit
= B_TRUE
;
3272 * unqualified dataset removal. remove all datasets but prompt if more
3275 if (!prompt_remove_resource(cmd
, "dataset"))
3278 if ((err
= zonecfg_del_all_resources(handle
, "dataset")) != Z_OK
)
3279 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3281 need_to_commit
= B_TRUE
;
3285 remove_rctl(cmd_t
*cmd
)
3289 /* traditional, qualified rctl removal */
3290 if (cmd
->cmd_prop_nv_pairs
> 0) {
3291 struct zone_rctltab rctltab
;
3293 if ((err
= fill_in_rctltab(cmd
, &rctltab
, B_FALSE
)) != Z_OK
) {
3294 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3297 if ((err
= zonecfg_delete_rctl(handle
, &rctltab
)) != Z_OK
)
3298 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3300 need_to_commit
= B_TRUE
;
3301 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
3306 * unqualified rctl removal. remove all rctls but prompt if more
3309 if (!prompt_remove_resource(cmd
, "rctl"))
3312 if ((err
= zonecfg_del_all_resources(handle
, "rctl")) != Z_OK
)
3313 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3315 need_to_commit
= B_TRUE
;
3322 struct zone_psettab psettab
;
3324 if ((err
= zonecfg_lookup_pset(handle
, &psettab
)) != Z_OK
) {
3325 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3328 if ((err
= zonecfg_delete_pset(handle
)) != Z_OK
)
3329 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3331 need_to_commit
= B_TRUE
;
3340 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) != Z_OK
) {
3341 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_PCAP
),
3342 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3347 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_CPUCAP
)) != Z_OK
)
3348 z_cmd_rt_perror(CMD_REMOVE
, RT_PCAP
, err
, B_TRUE
);
3350 need_to_commit
= B_TRUE
;
3356 int err
, res1
, res2
, res3
;
3358 struct zone_mcaptab mcaptab
;
3359 boolean_t revert
= B_FALSE
;
3361 res1
= zonecfg_lookup_mcap(handle
, &mcaptab
);
3362 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp
);
3363 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &tmp
);
3365 /* if none of these exist, there is no resource to remove */
3366 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
3367 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_MCAP
),
3368 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3373 if ((err
= zonecfg_delete_mcap(handle
)) != Z_OK
) {
3374 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3377 need_to_commit
= B_TRUE
;
3381 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXSWAP
))
3383 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3386 need_to_commit
= B_TRUE
;
3390 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
))
3392 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3395 need_to_commit
= B_TRUE
;
3400 need_to_commit
= B_FALSE
;
3404 remove_admin(cmd_t
*cmd
)
3408 /* traditional, qualified attr removal */
3409 if (cmd
->cmd_prop_nv_pairs
> 0) {
3410 struct zone_admintab admintab
;
3412 if ((err
= fill_in_admintab(cmd
, &admintab
, B_FALSE
)) != Z_OK
) {
3413 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3417 if ((err
= zonecfg_delete_admin(handle
, &admintab
,
3420 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3423 need_to_commit
= B_TRUE
;
3427 * unqualified admin removal.
3428 * remove all admins but prompt if more
3431 if (!prompt_remove_resource(cmd
, "admin"))
3434 if ((err
= zonecfg_delete_admins(handle
, zone
))
3436 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3439 need_to_commit
= B_TRUE
;
3447 struct zone_secflagstab sectab
= { 0 };
3449 if (zonecfg_lookup_secflags(handle
, §ab
) != Z_OK
) {
3450 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
),
3451 rt_to_str(RT_SECFLAGS
),
3452 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3456 if ((err
= zonecfg_delete_secflags(handle
, §ab
)) != Z_OK
) {
3457 z_cmd_rt_perror(CMD_REMOVE
, RT_SECFLAGS
, err
, B_TRUE
);
3461 need_to_commit
= B_TRUE
;
3465 remove_resource(cmd_t
*cmd
)
3469 boolean_t arg_err
= B_FALSE
;
3471 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3472 long_usage(CMD_REMOVE
, B_TRUE
);
3477 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
3480 longer_usage(CMD_REMOVE
);
3486 short_usage(CMD_REMOVE
);
3494 if (initialize(B_TRUE
) != Z_OK
)
3514 remove_dataset(cmd
);
3532 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3533 long_usage(CMD_REMOVE
, B_TRUE
);
3534 usage(B_FALSE
, HELP_RESOURCES
);
3540 remove_property(cmd_t
*cmd
)
3543 int err
, res_type
, prop_type
;
3544 property_value_ptr_t pp
;
3545 struct zone_rctlvaltab
*rctlvaltab
;
3546 complex_property_ptr_t cx
;
3548 res_type
= resource_scope
;
3549 prop_type
= cmd
->cmd_prop_name
[0];
3550 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3551 long_usage(CMD_REMOVE
, B_TRUE
);
3555 if (cmd
->cmd_prop_nv_pairs
!= 1) {
3556 long_usage(CMD_ADD
, B_TRUE
);
3560 if (initialize(B_TRUE
) != Z_OK
)
3565 if (prop_type
!= PT_OPTIONS
) {
3566 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3568 long_usage(CMD_REMOVE
, B_TRUE
);
3569 usage(B_FALSE
, HELP_PROPS
);
3572 pp
= cmd
->cmd_property_ptr
[0];
3573 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
3574 zerr(gettext("A %s or %s value was expected here."),
3575 pvt_to_str(PROP_VAL_SIMPLE
),
3576 pvt_to_str(PROP_VAL_LIST
));
3580 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
3581 if (pp
->pv_simple
== NULL
) {
3582 long_usage(CMD_ADD
, B_TRUE
);
3585 prop_id
= pp
->pv_simple
;
3586 err
= zonecfg_remove_fs_option(&in_progress_fstab
,
3589 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3591 list_property_ptr_t list
;
3593 for (list
= pp
->pv_list
; list
!= NULL
;
3594 list
= list
->lp_next
) {
3595 prop_id
= list
->lp_simple
;
3596 if (prop_id
== NULL
)
3598 err
= zonecfg_remove_fs_option(
3599 &in_progress_fstab
, prop_id
);
3601 zone_perror(pt_to_str(prop_type
), err
,
3607 if (prop_type
!= PT_VALUE
) {
3608 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3610 long_usage(CMD_REMOVE
, B_TRUE
);
3611 usage(B_FALSE
, HELP_PROPS
);
3614 pp
= cmd
->cmd_property_ptr
[0];
3615 if (pp
->pv_type
!= PROP_VAL_COMPLEX
) {
3616 zerr(gettext("A %s value was expected here."),
3617 pvt_to_str(PROP_VAL_COMPLEX
));
3621 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
3622 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
3625 for (cx
= pp
->pv_complex
; cx
!= NULL
; cx
= cx
->cp_next
) {
3626 switch (cx
->cp_type
) {
3628 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
3630 sizeof (rctlvaltab
->zone_rctlval_priv
));
3633 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
3635 sizeof (rctlvaltab
->zone_rctlval_limit
));
3638 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
3640 sizeof (rctlvaltab
->zone_rctlval_action
));
3643 zone_perror(pt_to_str(prop_type
),
3644 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3645 long_usage(CMD_ADD
, B_TRUE
);
3646 usage(B_FALSE
, HELP_PROPS
);
3647 zonecfg_free_rctl_value_list(rctlvaltab
);
3651 rctlvaltab
->zone_rctlval_next
= NULL
;
3652 err
= zonecfg_remove_rctl_value(&in_progress_rctltab
,
3655 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3656 zonecfg_free_rctl_value_list(rctlvaltab
);
3659 if (prop_type
!= PT_DEFROUTER
) {
3660 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3662 long_usage(CMD_REMOVE
, B_TRUE
);
3663 usage(B_FALSE
, HELP_PROPS
);
3666 bzero(&in_progress_nwiftab
.zone_nwif_defrouter
,
3667 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
3671 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3672 long_usage(CMD_REMOVE
, B_TRUE
);
3673 usage(B_FALSE
, HELP_RESOURCES
);
3679 remove_func(cmd_t
*cmd
)
3681 if (zone_is_read_only(CMD_REMOVE
))
3684 assert(cmd
!= NULL
);
3687 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
3688 zerr(gettext("%s is not a valid resource for the "
3689 "global zone."), rt_to_str(cmd
->cmd_res_type
));
3693 remove_resource(cmd
);
3695 remove_property(cmd
);
3700 clear_property(cmd_t
*cmd
)
3702 int res_type
, prop_type
;
3704 res_type
= resource_scope
;
3705 prop_type
= cmd
->cmd_res_type
;
3706 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3707 long_usage(CMD_CLEAR
, B_TRUE
);
3711 if (initialize(B_TRUE
) != Z_OK
)
3716 if (prop_type
== PT_RAW
) {
3717 in_progress_fstab
.zone_fs_raw
[0] = '\0';
3718 need_to_commit
= B_TRUE
;
3723 if (prop_type
== PT_IMPORTANCE
) {
3724 in_progress_psettab
.zone_importance
[0] = '\0';
3725 need_to_commit
= B_TRUE
;
3730 switch (prop_type
) {
3732 in_progress_mcaptab
.zone_physmem_cap
[0] = '\0';
3733 need_to_commit
= B_TRUE
;
3736 remove_aliased_rctl(PT_SWAP
, ALIAS_MAXSWAP
);
3739 remove_aliased_rctl(PT_LOCKED
, ALIAS_MAXLOCKEDMEM
);
3744 switch (prop_type
) {
3746 in_progress_secflagstab
.zone_secflags_lower
[0] = '\0';
3747 need_to_commit
= B_TRUE
;
3750 in_progress_secflagstab
.zone_secflags_default
[0] = '\0';
3751 need_to_commit
= B_TRUE
;
3754 in_progress_secflagstab
.zone_secflags_upper
[0] = '\0';
3755 need_to_commit
= B_TRUE
;
3763 zone_perror(pt_to_str(prop_type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3767 clear_global(cmd_t
*cmd
)
3771 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3772 long_usage(CMD_CLEAR
, B_TRUE
);
3776 if (initialize(B_TRUE
) != Z_OK
)
3785 zone_perror(pt_to_str(type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3788 /* false is default; we'll treat as equivalent to clearing */
3789 if ((err
= zonecfg_set_autoboot(handle
, B_FALSE
)) != Z_OK
)
3790 z_cmd_rt_perror(CMD_CLEAR
, RT_AUTOBOOT
, err
, B_TRUE
);
3792 need_to_commit
= B_TRUE
;
3795 if ((err
= zonecfg_set_pool(handle
, NULL
)) != Z_OK
)
3796 z_cmd_rt_perror(CMD_CLEAR
, RT_POOL
, err
, B_TRUE
);
3798 need_to_commit
= B_TRUE
;
3801 if ((err
= zonecfg_set_limitpriv(handle
, NULL
)) != Z_OK
)
3802 z_cmd_rt_perror(CMD_CLEAR
, RT_LIMITPRIV
, err
, B_TRUE
);
3804 need_to_commit
= B_TRUE
;
3807 if ((err
= zonecfg_set_bootargs(handle
, NULL
)) != Z_OK
)
3808 z_cmd_rt_perror(CMD_CLEAR
, RT_BOOTARGS
, err
, B_TRUE
);
3810 need_to_commit
= B_TRUE
;
3813 if ((err
= zonecfg_set_sched(handle
, NULL
)) != Z_OK
)
3814 z_cmd_rt_perror(CMD_CLEAR
, RT_SCHED
, err
, B_TRUE
);
3816 need_to_commit
= B_TRUE
;
3819 /* shared is default; we'll treat as equivalent to clearing */
3820 if ((err
= zonecfg_set_iptype(handle
, ZS_SHARED
)) != Z_OK
)
3821 z_cmd_rt_perror(CMD_CLEAR
, RT_IPTYPE
, err
, B_TRUE
);
3823 need_to_commit
= B_TRUE
;
3826 remove_aliased_rctl(PT_MAXLWPS
, ALIAS_MAXLWPS
);
3829 remove_aliased_rctl(PT_MAXPROCS
, ALIAS_MAXPROCS
);
3832 remove_aliased_rctl(PT_MAXSHMMEM
, ALIAS_MAXSHMMEM
);
3835 remove_aliased_rctl(PT_MAXSHMIDS
, ALIAS_MAXSHMIDS
);
3838 remove_aliased_rctl(PT_MAXMSGIDS
, ALIAS_MAXMSGIDS
);
3841 remove_aliased_rctl(PT_MAXSEMIDS
, ALIAS_MAXSEMIDS
);
3844 remove_aliased_rctl(PT_SHARES
, ALIAS_SHARES
);
3847 if ((err
= zonecfg_set_hostid(handle
, NULL
)) != Z_OK
)
3848 z_cmd_rt_perror(CMD_CLEAR
, RT_HOSTID
, err
, B_TRUE
);
3850 need_to_commit
= B_TRUE
;
3853 if ((err
= zonecfg_set_fs_allowed(handle
, NULL
)) != Z_OK
)
3854 z_cmd_rt_perror(CMD_CLEAR
, RT_FS_ALLOWED
, err
, B_TRUE
);
3856 need_to_commit
= B_TRUE
;
3859 zone_perror(pt_to_str(type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
3860 long_usage(CMD_CLEAR
, B_TRUE
);
3861 usage(B_FALSE
, HELP_PROPS
);
3867 clear_func(cmd_t
*cmd
)
3869 if (zone_is_read_only(CMD_CLEAR
))
3872 assert(cmd
!= NULL
);
3875 if (gz_invalid_property(cmd
->cmd_res_type
)) {
3876 zerr(gettext("%s is not a valid property for the "
3877 "global zone."), pt_to_str(cmd
->cmd_res_type
));
3884 clear_property(cmd
);
3889 select_func(cmd_t
*cmd
)
3895 if (zone_is_read_only(CMD_SELECT
))
3898 assert(cmd
!= NULL
);
3901 global_scope
= B_FALSE
;
3902 resource_scope
= cmd
->cmd_res_type
;
3903 end_op
= CMD_SELECT
;
3905 scope_usage(CMD_SELECT
);
3909 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3910 long_usage(CMD_SELECT
, B_TRUE
);
3914 if (initialize(B_TRUE
) != Z_OK
)
3919 if ((err
= fill_in_fstab(cmd
, &old_fstab
, B_FALSE
)) != Z_OK
) {
3920 z_cmd_rt_perror(CMD_SELECT
, RT_FS
, err
, B_TRUE
);
3921 global_scope
= B_TRUE
;
3923 bcopy(&old_fstab
, &in_progress_fstab
,
3924 sizeof (struct zone_fstab
));
3927 if ((err
= fill_in_nwiftab(cmd
, &old_nwiftab
, B_FALSE
))
3929 z_cmd_rt_perror(CMD_SELECT
, RT_NET
, err
, B_TRUE
);
3930 global_scope
= B_TRUE
;
3932 bcopy(&old_nwiftab
, &in_progress_nwiftab
,
3933 sizeof (struct zone_nwiftab
));
3936 if ((err
= fill_in_devtab(cmd
, &old_devtab
, B_FALSE
)) != Z_OK
) {
3937 z_cmd_rt_perror(CMD_SELECT
, RT_DEVICE
, err
, B_TRUE
);
3938 global_scope
= B_TRUE
;
3940 bcopy(&old_devtab
, &in_progress_devtab
,
3941 sizeof (struct zone_devtab
));
3944 if ((err
= fill_in_rctltab(cmd
, &old_rctltab
, B_FALSE
))
3946 z_cmd_rt_perror(CMD_SELECT
, RT_RCTL
, err
, B_TRUE
);
3947 global_scope
= B_TRUE
;
3949 bcopy(&old_rctltab
, &in_progress_rctltab
,
3950 sizeof (struct zone_rctltab
));
3953 if ((err
= fill_in_attrtab(cmd
, &old_attrtab
, B_FALSE
))
3955 z_cmd_rt_perror(CMD_SELECT
, RT_ATTR
, err
, B_TRUE
);
3956 global_scope
= B_TRUE
;
3958 bcopy(&old_attrtab
, &in_progress_attrtab
,
3959 sizeof (struct zone_attrtab
));
3962 if ((err
= fill_in_dstab(cmd
, &old_dstab
, B_FALSE
)) != Z_OK
) {
3963 z_cmd_rt_perror(CMD_SELECT
, RT_DATASET
, err
, B_TRUE
);
3964 global_scope
= B_TRUE
;
3966 bcopy(&old_dstab
, &in_progress_dstab
,
3967 sizeof (struct zone_dstab
));
3970 if ((err
= zonecfg_lookup_pset(handle
, &old_psettab
)) != Z_OK
) {
3971 z_cmd_rt_perror(CMD_SELECT
, RT_DCPU
, err
, B_TRUE
);
3972 global_scope
= B_TRUE
;
3974 bcopy(&old_psettab
, &in_progress_psettab
,
3975 sizeof (struct zone_psettab
));
3978 if ((err
= zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
))
3980 z_cmd_rt_perror(CMD_SELECT
, RT_PCAP
, err
, B_TRUE
);
3981 global_scope
= B_TRUE
;
3985 /* if none of these exist, there is no resource to select */
3986 if ((res
= zonecfg_lookup_mcap(handle
, &old_mcaptab
)) != Z_OK
&&
3987 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &limit
)
3989 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &limit
)
3991 z_cmd_rt_perror(CMD_SELECT
, RT_MCAP
, Z_NO_RESOURCE_TYPE
,
3993 global_scope
= B_TRUE
;
3996 bcopy(&old_mcaptab
, &in_progress_mcaptab
,
3997 sizeof (struct zone_mcaptab
));
3999 bzero(&in_progress_mcaptab
,
4000 sizeof (in_progress_mcaptab
));
4003 if ((err
= fill_in_admintab(cmd
, &old_admintab
, B_FALSE
))
4005 z_cmd_rt_perror(CMD_SELECT
, RT_ADMIN
, err
,
4007 global_scope
= B_TRUE
;
4009 bcopy(&old_admintab
, &in_progress_admintab
,
4010 sizeof (struct zone_admintab
));
4013 if ((err
= fill_in_secflagstab(cmd
, &old_secflagstab
, B_FALSE
))
4015 z_cmd_rt_perror(CMD_SELECT
, RT_SECFLAGS
, err
,
4017 global_scope
= B_TRUE
;
4019 bcopy(&old_secflagstab
, &in_progress_secflagstab
,
4020 sizeof (struct zone_secflagstab
));
4023 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4024 long_usage(CMD_SELECT
, B_TRUE
);
4025 usage(B_FALSE
, HELP_RESOURCES
);
4031 * Network "addresses" can be one of the following forms:
4033 * <IPv4 address>/<prefix length>
4034 * <IPv6 address>/<prefix length>
4036 * <host name>/<prefix length>
4037 * In other words, the "/" followed by a prefix length is allowed but not
4038 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4039 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4040 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4041 * Host names must start with an alpha-numeric character, and all subsequent
4042 * characters must be either alpha-numeric or "-".
4044 * In some cases, e.g., the nexthop for the defrouter, the context indicates
4045 * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
4046 * require the /<prefix length> (and should ignore it if provided).
4050 validate_net_address_syntax(char *address
, boolean_t ishost
)
4052 char *slashp
, part1
[MAXHOSTNAMELEN
];
4053 struct in6_addr in6
;
4058 * Copy the part before any '/' into part1 or copy the whole
4059 * thing if there is no '/'.
4061 if ((slashp
= strchr(address
, '/')) != NULL
) {
4063 (void) strlcpy(part1
, address
, sizeof (part1
));
4065 prefixlen
= atoi(++slashp
);
4067 (void) strlcpy(part1
, address
, sizeof (part1
));
4070 if (ishost
&& slashp
!= NULL
) {
4071 zerr(gettext("Warning: prefix length in %s is not required and "
4072 "will be ignored. The default host-prefix length "
4073 "will be used"), address
);
4077 if (inet_pton(AF_INET6
, part1
, &in6
) == 1) {
4079 prefixlen
= IPV6_ABITS
;
4080 } else if (slashp
== NULL
) {
4081 zerr(gettext("%s: IPv6 addresses "
4082 "require /prefix-length suffix."), address
);
4085 if (prefixlen
< 0 || prefixlen
> 128) {
4086 zerr(gettext("%s: IPv6 address "
4087 "prefix lengths must be 0 - 128."), address
);
4093 /* At this point, any /prefix must be for IPv4. */
4095 prefixlen
= IPV4_ABITS
;
4096 else if (slashp
!= NULL
) {
4097 if (prefixlen
< 0 || prefixlen
> 32) {
4098 zerr(gettext("%s: IPv4 address "
4099 "prefix lengths must be 0 - 32."), address
);
4104 if (inet_pton(AF_INET
, part1
, &in4
) == 1)
4107 /* address may also be a host name */
4108 if (!isalnum(part1
[0])) {
4109 zerr(gettext("%s: bogus host name or network address syntax"),
4112 usage(B_FALSE
, HELP_NETADDR
);
4115 for (i
= 1; part1
[i
]; i
++)
4116 if (!isalnum(part1
[i
]) && part1
[i
] != '-' && part1
[i
] != '.') {
4117 zerr(gettext("%s: bogus host name or "
4118 "network address syntax"), part1
);
4120 usage(B_FALSE
, HELP_NETADDR
);
4127 validate_net_physical_syntax(const char *ifname
)
4129 ifspec_t ifnameprop
;
4130 zone_iptype_t iptype
;
4132 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
4133 zerr(gettext("zone configuration has an invalid or nonexistent "
4134 "ip-type property"));
4139 if (ifparse_ifspec(ifname
, &ifnameprop
) == B_FALSE
) {
4140 zerr(gettext("%s: invalid physical interface name"),
4144 if (ifnameprop
.ifsp_lunvalid
) {
4145 zerr(gettext("%s: LUNs not allowed in physical "
4146 "interface names"), ifname
);
4151 if (dladm_valid_linkname(ifname
) == B_FALSE
) {
4152 if (strchr(ifname
, ':') != NULL
)
4153 zerr(gettext("%s: physical interface name "
4154 "required; logical interface name not "
4155 "allowed"), ifname
);
4157 zerr(gettext("%s: invalid physical interface "
4167 valid_fs_type(const char *type
)
4170 * Is this a valid path component?
4172 if (strlen(type
) + 1 > MAXNAMELEN
)
4175 * Make sure a bad value for "type" doesn't make
4176 * /usr/lib/fs/<type>/mount turn into something else.
4178 if (strchr(type
, '/') != NULL
|| type
[0] == '\0' ||
4179 strcmp(type
, ".") == 0 || strcmp(type
, "..") == 0)
4182 * More detailed verification happens later by zoneadm(1m).
4191 char brand
[MAXNAMELEN
];
4194 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
4195 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
4198 if ((bh
= brand_open(brand
)) == NULL
) {
4199 zerr("%s: %s\n", zone
, gettext("unknown brand."));
4202 ret
= brand_allow_exclusive_ip(bh
);
4205 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
4206 pt_to_str(PT_IPTYPE
), "exclusive",
4207 pt_to_str(PT_BRAND
), brand
);
4212 set_aliased_rctl(char *alias
, int prop_type
, char *s
)
4218 if (global_zone
&& strcmp(alias
, ALIAS_SHARES
) != 0)
4219 zerr(gettext("WARNING: Setting a global zone resource "
4220 "control too low could deny\nservice "
4221 "to even the root user; "
4222 "this could render the system impossible\n"
4223 "to administer. Please use caution."));
4225 /* convert memory based properties */
4226 if (prop_type
== PT_MAXSHMMEM
) {
4227 if (!zonecfg_valid_memlimit(s
, &limit
)) {
4228 zerr(gettext("A non-negative number with a required "
4229 "scale suffix (K, M, G or T) was expected\nhere."));
4234 (void) snprintf(tmp
, sizeof (tmp
), "%llu", limit
);
4238 if (!zonecfg_aliased_rctl_ok(handle
, alias
)) {
4239 zone_perror(pt_to_str(prop_type
), Z_ALIAS_DISALLOW
, B_FALSE
);
4241 } else if (!zonecfg_valid_alias_limit(alias
, s
, &limit
)) {
4242 zerr(gettext("%s property is out of range."),
4243 pt_to_str(prop_type
));
4245 } else if ((err
= zonecfg_set_aliased_rctl(handle
, alias
, limit
))
4247 zone_perror(zone
, err
, B_TRUE
);
4250 need_to_commit
= B_TRUE
;
4255 set_in_progress_nwiftab_address(char *prop_id
, int prop_type
)
4257 if (prop_type
== PT_ADDRESS
) {
4258 (void) strlcpy(in_progress_nwiftab
.zone_nwif_address
, prop_id
,
4259 sizeof (in_progress_nwiftab
.zone_nwif_address
));
4261 assert(prop_type
== PT_ALLOWED_ADDRESS
);
4262 (void) strlcpy(in_progress_nwiftab
.zone_nwif_allowed_address
,
4264 sizeof (in_progress_nwiftab
.zone_nwif_allowed_address
));
4269 set_func(cmd_t
*cmd
)
4272 int arg
, err
, res_type
, prop_type
;
4273 property_value_ptr_t pp
;
4275 zone_iptype_t iptype
;
4276 boolean_t force_set
= B_FALSE
;
4277 size_t physmem_size
= sizeof (in_progress_mcaptab
.zone_physmem_cap
);
4278 uint64_t mem_cap
, mem_limit
;
4281 struct zone_psettab tmp_psettab
;
4282 boolean_t arg_err
= B_FALSE
;
4284 if (zone_is_read_only(CMD_SET
))
4287 assert(cmd
!= NULL
);
4289 optind
= opterr
= 0;
4290 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
4297 longer_usage(CMD_SET
);
4299 short_usage(CMD_SET
);
4307 prop_type
= cmd
->cmd_prop_name
[0];
4309 if (gz_invalid_property(prop_type
)) {
4310 zerr(gettext("%s is not a valid property for the "
4311 "global zone."), pt_to_str(prop_type
));
4316 if (prop_type
== PT_ZONENAME
) {
4317 res_type
= RT_ZONENAME
;
4318 } else if (prop_type
== PT_ZONEPATH
) {
4319 res_type
= RT_ZONEPATH
;
4320 } else if (prop_type
== PT_AUTOBOOT
) {
4321 res_type
= RT_AUTOBOOT
;
4322 } else if (prop_type
== PT_BRAND
) {
4323 res_type
= RT_BRAND
;
4324 } else if (prop_type
== PT_POOL
) {
4326 } else if (prop_type
== PT_LIMITPRIV
) {
4327 res_type
= RT_LIMITPRIV
;
4328 } else if (prop_type
== PT_BOOTARGS
) {
4329 res_type
= RT_BOOTARGS
;
4330 } else if (prop_type
== PT_SCHED
) {
4331 res_type
= RT_SCHED
;
4332 } else if (prop_type
== PT_IPTYPE
) {
4333 res_type
= RT_IPTYPE
;
4334 } else if (prop_type
== PT_MAXLWPS
) {
4335 res_type
= RT_MAXLWPS
;
4336 } else if (prop_type
== PT_MAXPROCS
) {
4337 res_type
= RT_MAXPROCS
;
4338 } else if (prop_type
== PT_MAXSHMMEM
) {
4339 res_type
= RT_MAXSHMMEM
;
4340 } else if (prop_type
== PT_MAXSHMIDS
) {
4341 res_type
= RT_MAXSHMIDS
;
4342 } else if (prop_type
== PT_MAXMSGIDS
) {
4343 res_type
= RT_MAXMSGIDS
;
4344 } else if (prop_type
== PT_MAXSEMIDS
) {
4345 res_type
= RT_MAXSEMIDS
;
4346 } else if (prop_type
== PT_SHARES
) {
4347 res_type
= RT_SHARES
;
4348 } else if (prop_type
== PT_HOSTID
) {
4349 res_type
= RT_HOSTID
;
4350 } else if (prop_type
== PT_FS_ALLOWED
) {
4351 res_type
= RT_FS_ALLOWED
;
4353 zerr(gettext("Cannot set a resource-specific property "
4354 "from the global scope."));
4359 res_type
= resource_scope
;
4363 if (res_type
!= RT_ZONEPATH
) {
4364 zerr(gettext("Only zonepath setting can be forced."));
4368 if (!zonecfg_in_alt_root()) {
4369 zerr(gettext("Zonepath is changeable only in an "
4370 "alternate root."));
4376 pp
= cmd
->cmd_property_ptr
[0];
4378 * A nasty expression but not that complicated:
4379 * 1. fs options are simple or list (tested below)
4380 * 2. rctl value's are complex or list (tested below)
4381 * Anything else should be simple.
4383 if (!(res_type
== RT_FS
&& prop_type
== PT_OPTIONS
) &&
4384 !(res_type
== RT_RCTL
&& prop_type
== PT_VALUE
) &&
4385 (pp
->pv_type
!= PROP_VAL_SIMPLE
||
4386 (prop_id
= pp
->pv_simple
) == NULL
)) {
4387 zerr(gettext("A %s value was expected here."),
4388 pvt_to_str(PROP_VAL_SIMPLE
));
4392 if (prop_type
== PT_UNKNOWN
) {
4393 long_usage(CMD_SET
, B_TRUE
);
4398 * Special case: the user can change the zone name prior to 'create';
4399 * if the zone already exists, we fall through letting initialize()
4400 * and the rest of the logic run.
4402 if (res_type
== RT_ZONENAME
&& got_handle
== B_FALSE
&&
4403 !state_atleast(ZONE_STATE_CONFIGURED
)) {
4404 if ((err
= zonecfg_validate_zonename(prop_id
)) != Z_OK
) {
4405 zone_perror(prop_id
, err
, B_TRUE
);
4406 usage(B_FALSE
, HELP_SYNTAX
);
4409 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4413 if (initialize(B_TRUE
) != Z_OK
)
4418 if ((err
= zonecfg_set_name(handle
, prop_id
)) != Z_OK
) {
4420 * Use prop_id instead of 'zone' here, since we're
4421 * reporting a problem about the *new* zonename.
4423 zone_perror(prop_id
, err
, B_TRUE
);
4424 usage(B_FALSE
, HELP_SYNTAX
);
4426 need_to_commit
= B_TRUE
;
4427 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4431 if (!force_set
&& state_atleast(ZONE_STATE_INSTALLED
)) {
4432 zerr(gettext("Zone %s already installed; %s %s not "
4433 "allowed."), zone
, cmd_to_str(CMD_SET
),
4434 rt_to_str(RT_ZONEPATH
));
4437 if (validate_zonepath_syntax(prop_id
) != Z_OK
) {
4441 if ((err
= zonecfg_set_zonepath(handle
, prop_id
)) != Z_OK
)
4442 zone_perror(zone
, err
, B_TRUE
);
4444 need_to_commit
= B_TRUE
;
4447 if (state_atleast(ZONE_STATE_INSTALLED
)) {
4448 zerr(gettext("Zone %s already installed; %s %s not "
4449 "allowed."), zone
, cmd_to_str(CMD_SET
),
4450 rt_to_str(RT_BRAND
));
4453 if ((err
= zonecfg_set_brand(handle
, prop_id
)) != Z_OK
)
4454 zone_perror(zone
, err
, B_TRUE
);
4456 need_to_commit
= B_TRUE
;
4459 if (strcmp(prop_id
, "true") == 0) {
4461 } else if (strcmp(prop_id
, "false") == 0) {
4464 zerr(gettext("%s value must be '%s' or '%s'."),
4465 pt_to_str(PT_AUTOBOOT
), "true", "false");
4469 if ((err
= zonecfg_set_autoboot(handle
, autoboot
)) != Z_OK
)
4470 zone_perror(zone
, err
, B_TRUE
);
4472 need_to_commit
= B_TRUE
;
4475 /* don't allow use of the reserved temporary pool names */
4476 if (strncmp("SUNW", prop_id
, 4) == 0) {
4477 zerr(gettext("pool names starting with SUNW are "
4483 /* can't set pool if dedicated-cpu exists */
4484 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
4485 zerr(gettext("The %s resource already exists. "
4486 "A persistent pool is incompatible\nwith the %s "
4487 "resource."), rt_to_str(RT_DCPU
),
4488 rt_to_str(RT_DCPU
));
4493 if ((err
= zonecfg_set_pool(handle
, prop_id
)) != Z_OK
)
4494 zone_perror(zone
, err
, B_TRUE
);
4496 need_to_commit
= B_TRUE
;
4499 if ((err
= zonecfg_set_limitpriv(handle
, prop_id
)) != Z_OK
)
4500 zone_perror(zone
, err
, B_TRUE
);
4502 need_to_commit
= B_TRUE
;
4505 if ((err
= zonecfg_set_bootargs(handle
, prop_id
)) != Z_OK
)
4506 zone_perror(zone
, err
, B_TRUE
);
4508 need_to_commit
= B_TRUE
;
4511 if ((err
= zonecfg_set_sched(handle
, prop_id
)) != Z_OK
)
4512 zone_perror(zone
, err
, B_TRUE
);
4514 need_to_commit
= B_TRUE
;
4517 if (strcmp(prop_id
, "shared") == 0) {
4519 } else if (strcmp(prop_id
, "exclusive") == 0) {
4520 iptype
= ZS_EXCLUSIVE
;
4522 zerr(gettext("%s value must be '%s' or '%s'."),
4523 pt_to_str(PT_IPTYPE
), "shared", "exclusive");
4527 if (iptype
== ZS_EXCLUSIVE
&& !allow_exclusive()) {
4531 if ((err
= zonecfg_set_iptype(handle
, iptype
)) != Z_OK
)
4532 zone_perror(zone
, err
, B_TRUE
);
4534 need_to_commit
= B_TRUE
;
4537 set_aliased_rctl(ALIAS_MAXLWPS
, prop_type
, prop_id
);
4540 set_aliased_rctl(ALIAS_MAXPROCS
, prop_type
, prop_id
);
4543 set_aliased_rctl(ALIAS_MAXSHMMEM
, prop_type
, prop_id
);
4546 set_aliased_rctl(ALIAS_MAXSHMIDS
, prop_type
, prop_id
);
4549 set_aliased_rctl(ALIAS_MAXMSGIDS
, prop_type
, prop_id
);
4552 set_aliased_rctl(ALIAS_MAXSEMIDS
, prop_type
, prop_id
);
4555 set_aliased_rctl(ALIAS_SHARES
, prop_type
, prop_id
);
4558 if ((err
= zonecfg_set_hostid(handle
, prop_id
)) != Z_OK
) {
4559 if (err
== Z_TOO_BIG
) {
4560 zerr(gettext("hostid string is too large: %s"),
4564 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
4568 need_to_commit
= B_TRUE
;
4571 if ((err
= zonecfg_set_fs_allowed(handle
, prop_id
)) != Z_OK
)
4572 zone_perror(zone
, err
, B_TRUE
);
4574 need_to_commit
= B_TRUE
;
4577 switch (prop_type
) {
4579 (void) strlcpy(in_progress_fstab
.zone_fs_dir
, prop_id
,
4580 sizeof (in_progress_fstab
.zone_fs_dir
));
4583 (void) strlcpy(in_progress_fstab
.zone_fs_special
,
4585 sizeof (in_progress_fstab
.zone_fs_special
));
4588 (void) strlcpy(in_progress_fstab
.zone_fs_raw
,
4589 prop_id
, sizeof (in_progress_fstab
.zone_fs_raw
));
4592 if (!valid_fs_type(prop_id
)) {
4593 zerr(gettext("\"%s\" is not a valid %s."),
4594 prop_id
, pt_to_str(PT_TYPE
));
4598 (void) strlcpy(in_progress_fstab
.zone_fs_type
, prop_id
,
4599 sizeof (in_progress_fstab
.zone_fs_type
));
4602 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
4603 pp
->pv_type
!= PROP_VAL_LIST
) {
4604 zerr(gettext("A %s or %s value was expected "
4605 "here."), pvt_to_str(PROP_VAL_SIMPLE
),
4606 pvt_to_str(PROP_VAL_LIST
));
4610 zonecfg_free_fs_option_list(
4611 in_progress_fstab
.zone_fs_options
);
4612 in_progress_fstab
.zone_fs_options
= NULL
;
4613 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4614 pp
->pv_list
== NULL
))
4620 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4621 long_usage(CMD_SET
, B_TRUE
);
4622 usage(B_FALSE
, HELP_PROPS
);
4625 switch (prop_type
) {
4627 case PT_ALLOWED_ADDRESS
:
4628 if (validate_net_address_syntax(prop_id
, B_FALSE
)
4633 set_in_progress_nwiftab_address(prop_id
, prop_type
);
4636 if (validate_net_physical_syntax(prop_id
) != Z_OK
) {
4640 (void) strlcpy(in_progress_nwiftab
.zone_nwif_physical
,
4642 sizeof (in_progress_nwiftab
.zone_nwif_physical
));
4645 if (validate_net_address_syntax(prop_id
, B_TRUE
)
4650 (void) strlcpy(in_progress_nwiftab
.zone_nwif_defrouter
,
4652 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
4655 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4657 long_usage(CMD_SET
, B_TRUE
);
4658 usage(B_FALSE
, HELP_PROPS
);
4663 switch (prop_type
) {
4665 (void) strlcpy(in_progress_devtab
.zone_dev_match
,
4667 sizeof (in_progress_devtab
.zone_dev_match
));
4670 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4672 long_usage(CMD_SET
, B_TRUE
);
4673 usage(B_FALSE
, HELP_PROPS
);
4678 switch (prop_type
) {
4680 if (!zonecfg_valid_rctlname(prop_id
)) {
4681 zerr(gettext("'%s' is not a valid zone %s "
4682 "name."), prop_id
, rt_to_str(RT_RCTL
));
4685 (void) strlcpy(in_progress_rctltab
.zone_rctl_name
,
4687 sizeof (in_progress_rctltab
.zone_rctl_name
));
4690 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
4691 pp
->pv_type
!= PROP_VAL_LIST
) {
4692 zerr(gettext("A %s or %s value was expected "
4693 "here."), pvt_to_str(PROP_VAL_COMPLEX
),
4694 pvt_to_str(PROP_VAL_LIST
));
4698 zonecfg_free_rctl_value_list(
4699 in_progress_rctltab
.zone_rctl_valptr
);
4700 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
4701 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4702 pp
->pv_list
== NULL
))
4706 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4708 long_usage(CMD_SET
, B_TRUE
);
4709 usage(B_FALSE
, HELP_PROPS
);
4714 switch (prop_type
) {
4716 (void) strlcpy(in_progress_attrtab
.zone_attr_name
,
4718 sizeof (in_progress_attrtab
.zone_attr_name
));
4721 (void) strlcpy(in_progress_attrtab
.zone_attr_type
,
4723 sizeof (in_progress_attrtab
.zone_attr_type
));
4726 (void) strlcpy(in_progress_attrtab
.zone_attr_value
,
4728 sizeof (in_progress_attrtab
.zone_attr_value
));
4731 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4733 long_usage(CMD_SET
, B_TRUE
);
4734 usage(B_FALSE
, HELP_PROPS
);
4739 switch (prop_type
) {
4741 (void) strlcpy(in_progress_dstab
.zone_dataset_name
,
4743 sizeof (in_progress_dstab
.zone_dataset_name
));
4748 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4749 long_usage(CMD_SET
, B_TRUE
);
4750 usage(B_FALSE
, HELP_PROPS
);
4753 switch (prop_type
) {
4758 if ((highp
= strchr(prop_id
, '-')) != NULL
)
4763 /* Make sure the input makes sense. */
4764 if (!zonecfg_valid_ncpus(lowp
, highp
)) {
4765 zerr(gettext("%s property is out of range."),
4766 pt_to_str(PT_NCPUS
));
4772 in_progress_psettab
.zone_ncpu_min
, lowp
,
4773 sizeof (in_progress_psettab
.zone_ncpu_min
));
4775 in_progress_psettab
.zone_ncpu_max
, highp
,
4776 sizeof (in_progress_psettab
.zone_ncpu_max
));
4779 /* Make sure the value makes sense. */
4780 if (!zonecfg_valid_importance(prop_id
)) {
4781 zerr(gettext("%s property is out of range."),
4782 pt_to_str(PT_IMPORTANCE
));
4787 (void) strlcpy(in_progress_psettab
.zone_importance
,
4789 sizeof (in_progress_psettab
.zone_importance
));
4794 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4795 long_usage(CMD_SET
, B_TRUE
);
4796 usage(B_FALSE
, HELP_PROPS
);
4799 if (prop_type
!= PT_NCPUS
) {
4800 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4802 long_usage(CMD_SET
, B_TRUE
);
4803 usage(B_FALSE
, HELP_PROPS
);
4808 * We already checked that an rctl alias is allowed in
4809 * the add_resource() function.
4812 if ((cap
= strtof(prop_id
, &unitp
)) <= 0 || *unitp
!= '\0' ||
4813 (int)(cap
* 100) < 1) {
4814 zerr(gettext("%s property is out of range."),
4815 pt_to_str(PT_NCPUS
));
4820 if ((err
= zonecfg_set_aliased_rctl(handle
, ALIAS_CPUCAP
,
4821 (int)(cap
* 100))) != Z_OK
)
4822 zone_perror(zone
, err
, B_TRUE
);
4824 need_to_commit
= B_TRUE
;
4827 switch (prop_type
) {
4829 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4830 zerr(gettext("A positive number with a "
4831 "required scale suffix (K, M, G or T) was "
4834 } else if (mem_cap
< ONE_MB
) {
4835 zerr(gettext("%s value is too small. It must "
4836 "be at least 1M."), pt_to_str(PT_PHYSICAL
));
4839 snprintf(in_progress_mcaptab
.zone_physmem_cap
,
4840 physmem_size
, "%llu", mem_cap
);
4845 * We have to check if an rctl is allowed here since
4846 * there might already be a rctl defined that blocks
4849 if (!zonecfg_aliased_rctl_ok(handle
, ALIAS_MAXSWAP
)) {
4850 zone_perror(pt_to_str(PT_MAXSWAP
),
4851 Z_ALIAS_DISALLOW
, B_FALSE
);
4857 mem_limit
= ONE_MB
* 100;
4859 mem_limit
= ONE_MB
* 50;
4861 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4862 zerr(gettext("A positive number with a "
4863 "required scale suffix (K, M, G or T) was "
4866 } else if (mem_cap
< mem_limit
) {
4869 (void) snprintf(buf
, sizeof (buf
), "%llu",
4871 bytes_to_units(buf
, buf
, sizeof (buf
));
4872 zerr(gettext("%s value is too small. It must "
4873 "be at least %s."), pt_to_str(PT_SWAP
),
4877 if ((err
= zonecfg_set_aliased_rctl(handle
,
4878 ALIAS_MAXSWAP
, mem_cap
)) != Z_OK
)
4879 zone_perror(zone
, err
, B_TRUE
);
4881 need_to_commit
= B_TRUE
;
4886 * We have to check if an rctl is allowed here since
4887 * there might already be a rctl defined that blocks
4890 if (!zonecfg_aliased_rctl_ok(handle
,
4891 ALIAS_MAXLOCKEDMEM
)) {
4892 zone_perror(pt_to_str(PT_LOCKED
),
4893 Z_ALIAS_DISALLOW
, B_FALSE
);
4898 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4899 zerr(gettext("A non-negative number with a "
4900 "required scale suffix (K, M, G or T) was "
4901 "expected\nhere."));
4904 if ((err
= zonecfg_set_aliased_rctl(handle
,
4905 ALIAS_MAXLOCKEDMEM
, mem_cap
)) != Z_OK
)
4906 zone_perror(zone
, err
, B_TRUE
);
4908 need_to_commit
= B_TRUE
;
4912 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4914 long_usage(CMD_SET
, B_TRUE
);
4915 usage(B_FALSE
, HELP_PROPS
);
4920 switch (prop_type
) {
4922 (void) strlcpy(in_progress_admintab
.zone_admin_user
,
4924 sizeof (in_progress_admintab
.zone_admin_user
));
4927 (void) strlcpy(in_progress_admintab
.zone_admin_auths
,
4929 sizeof (in_progress_admintab
.zone_admin_auths
));
4932 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4934 long_usage(CMD_SET
, B_TRUE
);
4935 usage(B_FALSE
, HELP_PROPS
);
4941 switch (prop_type
) {
4943 propstr
= in_progress_secflagstab
.zone_secflags_default
;
4946 propstr
= in_progress_secflagstab
.zone_secflags_upper
;
4949 propstr
= in_progress_secflagstab
.zone_secflags_lower
;
4952 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4954 long_usage(CMD_SET
, B_TRUE
);
4955 usage(B_FALSE
, HELP_PROPS
);
4958 (void) strlcpy(propstr
, prop_id
, ZONECFG_SECFLAGS_MAX
);
4962 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4963 long_usage(CMD_SET
, B_TRUE
);
4964 usage(B_FALSE
, HELP_RESOURCES
);
4970 output_prop(FILE *fp
, int pnum
, char *pval
, boolean_t print_notspec
)
4974 if (*pval
!= '\0') {
4975 qstr
= quoteit(pval
);
4976 if (pnum
== PT_SWAP
|| pnum
== PT_LOCKED
)
4977 (void) fprintf(fp
, "\t[%s: %s]\n", pt_to_str(pnum
),
4980 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(pnum
), qstr
);
4982 } else if (print_notspec
)
4983 (void) fprintf(fp
, gettext("\t%s not specified\n"),
4988 info_zonename(zone_dochandle_t handle
, FILE *fp
)
4990 char zonename
[ZONENAME_MAX
];
4992 if (zonecfg_get_name(handle
, zonename
, sizeof (zonename
)) == Z_OK
)
4993 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONENAME
),
4996 (void) fprintf(fp
, gettext("%s not specified\n"),
4997 pt_to_str(PT_ZONENAME
));
5001 info_zonepath(zone_dochandle_t handle
, FILE *fp
)
5003 char zonepath
[MAXPATHLEN
];
5005 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
)
5006 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONEPATH
),
5009 (void) fprintf(fp
, gettext("%s not specified\n"),
5010 pt_to_str(PT_ZONEPATH
));
5015 info_brand(zone_dochandle_t handle
, FILE *fp
)
5017 char brand
[MAXNAMELEN
];
5019 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) == Z_OK
)
5020 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BRAND
),
5023 (void) fprintf(fp
, "%s %s\n", pt_to_str(PT_BRAND
),
5024 gettext("not specified"));
5028 info_autoboot(zone_dochandle_t handle
, FILE *fp
)
5033 if ((err
= zonecfg_get_autoboot(handle
, &autoboot
)) == Z_OK
)
5034 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_AUTOBOOT
),
5035 autoboot
? "true" : "false");
5037 zone_perror(zone
, err
, B_TRUE
);
5041 info_pool(zone_dochandle_t handle
, FILE *fp
)
5043 char pool
[MAXNAMELEN
];
5046 if ((err
= zonecfg_get_pool(handle
, pool
, sizeof (pool
))) == Z_OK
)
5047 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_POOL
), pool
);
5049 zone_perror(zone
, err
, B_TRUE
);
5053 info_limitpriv(zone_dochandle_t handle
, FILE *fp
)
5058 if ((err
= zonecfg_get_limitpriv(handle
, &limitpriv
)) == Z_OK
) {
5059 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_LIMITPRIV
),
5063 zone_perror(zone
, err
, B_TRUE
);
5068 info_bootargs(zone_dochandle_t handle
, FILE *fp
)
5070 char bootargs
[BOOTARGS_MAX
];
5073 if ((err
= zonecfg_get_bootargs(handle
, bootargs
,
5074 sizeof (bootargs
))) == Z_OK
) {
5075 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BOOTARGS
),
5078 zone_perror(zone
, err
, B_TRUE
);
5083 info_sched(zone_dochandle_t handle
, FILE *fp
)
5085 char sched
[MAXNAMELEN
];
5088 if ((err
= zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)))
5090 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_SCHED
), sched
);
5092 zone_perror(zone
, err
, B_TRUE
);
5097 info_iptype(zone_dochandle_t handle
, FILE *fp
)
5099 zone_iptype_t iptype
;
5102 if ((err
= zonecfg_get_iptype(handle
, &iptype
)) == Z_OK
) {
5105 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5109 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5114 zone_perror(zone
, err
, B_TRUE
);
5119 info_hostid(zone_dochandle_t handle
, FILE *fp
)
5121 char hostidp
[HW_HOSTID_LEN
];
5124 if ((err
= zonecfg_get_hostid(handle
, hostidp
,
5125 sizeof (hostidp
))) == Z_OK
) {
5126 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_HOSTID
), hostidp
);
5127 } else if (err
== Z_BAD_PROPERTY
) {
5128 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_HOSTID
));
5130 zone_perror(zone
, err
, B_TRUE
);
5135 info_fs_allowed(zone_dochandle_t handle
, FILE *fp
)
5137 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
5140 if ((err
= zonecfg_get_fs_allowed(handle
, fsallowedp
,
5141 sizeof (fsallowedp
))) == Z_OK
) {
5142 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_FS_ALLOWED
),
5144 } else if (err
== Z_BAD_PROPERTY
) {
5145 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_FS_ALLOWED
));
5147 zone_perror(zone
, err
, B_TRUE
);
5152 output_fs(FILE *fp
, struct zone_fstab
*fstab
)
5156 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_FS
));
5157 output_prop(fp
, PT_DIR
, fstab
->zone_fs_dir
, B_TRUE
);
5158 output_prop(fp
, PT_SPECIAL
, fstab
->zone_fs_special
, B_TRUE
);
5159 output_prop(fp
, PT_RAW
, fstab
->zone_fs_raw
, B_TRUE
);
5160 output_prop(fp
, PT_TYPE
, fstab
->zone_fs_type
, B_TRUE
);
5161 (void) fprintf(fp
, "\t%s: [", pt_to_str(PT_OPTIONS
));
5162 for (this = fstab
->zone_fs_options
; this != NULL
;
5163 this = this->zone_fsopt_next
) {
5164 if (strchr(this->zone_fsopt_opt
, '='))
5165 (void) fprintf(fp
, "\"%s\"", this->zone_fsopt_opt
);
5167 (void) fprintf(fp
, "%s", this->zone_fsopt_opt
);
5168 if (this->zone_fsopt_next
!= NULL
)
5169 (void) fprintf(fp
, ",");
5171 (void) fprintf(fp
, "]\n");
5175 info_fs(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5177 struct zone_fstab lookup
, user
;
5178 boolean_t output
= B_FALSE
;
5180 if (zonecfg_setfsent(handle
) != Z_OK
)
5182 while (zonecfg_getfsent(handle
, &lookup
) == Z_OK
) {
5183 if (cmd
->cmd_prop_nv_pairs
== 0) {
5184 output_fs(fp
, &lookup
);
5187 if (fill_in_fstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5189 if (strlen(user
.zone_fs_dir
) > 0 &&
5190 strcmp(user
.zone_fs_dir
, lookup
.zone_fs_dir
) != 0)
5191 goto loopend
; /* no match */
5192 if (strlen(user
.zone_fs_special
) > 0 &&
5193 strcmp(user
.zone_fs_special
, lookup
.zone_fs_special
) != 0)
5194 goto loopend
; /* no match */
5195 if (strlen(user
.zone_fs_type
) > 0 &&
5196 strcmp(user
.zone_fs_type
, lookup
.zone_fs_type
) != 0)
5197 goto loopend
; /* no match */
5198 output_fs(fp
, &lookup
);
5201 zonecfg_free_fs_option_list(lookup
.zone_fs_options
);
5203 (void) zonecfg_endfsent(handle
);
5205 * If a property n/v pair was specified, warn the user if there was
5206 * nothing to output.
5208 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5209 (void) printf(gettext("No such %s resource.\n"),
5214 output_net(FILE *fp
, struct zone_nwiftab
*nwiftab
)
5216 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_NET
));
5217 output_prop(fp
, PT_ADDRESS
, nwiftab
->zone_nwif_address
, B_TRUE
);
5218 output_prop(fp
, PT_ALLOWED_ADDRESS
,
5219 nwiftab
->zone_nwif_allowed_address
, B_TRUE
);
5220 output_prop(fp
, PT_PHYSICAL
, nwiftab
->zone_nwif_physical
, B_TRUE
);
5221 output_prop(fp
, PT_DEFROUTER
, nwiftab
->zone_nwif_defrouter
, B_TRUE
);
5225 info_net(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5227 struct zone_nwiftab lookup
, user
;
5228 boolean_t output
= B_FALSE
;
5230 if (zonecfg_setnwifent(handle
) != Z_OK
)
5232 while (zonecfg_getnwifent(handle
, &lookup
) == Z_OK
) {
5233 if (cmd
->cmd_prop_nv_pairs
== 0) {
5234 output_net(fp
, &lookup
);
5237 if (fill_in_nwiftab(cmd
, &user
, B_TRUE
) != Z_OK
)
5239 if (strlen(user
.zone_nwif_physical
) > 0 &&
5240 strcmp(user
.zone_nwif_physical
,
5241 lookup
.zone_nwif_physical
) != 0)
5242 continue; /* no match */
5243 /* If present make sure it matches */
5244 if (strlen(user
.zone_nwif_address
) > 0 &&
5245 !zonecfg_same_net_address(user
.zone_nwif_address
,
5246 lookup
.zone_nwif_address
))
5247 continue; /* no match */
5248 output_net(fp
, &lookup
);
5251 (void) zonecfg_endnwifent(handle
);
5253 * If a property n/v pair was specified, warn the user if there was
5254 * nothing to output.
5256 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5257 (void) printf(gettext("No such %s resource.\n"),
5262 output_dev(FILE *fp
, struct zone_devtab
*devtab
)
5264 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DEVICE
));
5265 output_prop(fp
, PT_MATCH
, devtab
->zone_dev_match
, B_TRUE
);
5269 info_dev(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5271 struct zone_devtab lookup
, user
;
5272 boolean_t output
= B_FALSE
;
5274 if (zonecfg_setdevent(handle
) != Z_OK
)
5276 while (zonecfg_getdevent(handle
, &lookup
) == Z_OK
) {
5277 if (cmd
->cmd_prop_nv_pairs
== 0) {
5278 output_dev(fp
, &lookup
);
5281 if (fill_in_devtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5283 if (strlen(user
.zone_dev_match
) > 0 &&
5284 strcmp(user
.zone_dev_match
, lookup
.zone_dev_match
) != 0)
5285 continue; /* no match */
5286 output_dev(fp
, &lookup
);
5289 (void) zonecfg_enddevent(handle
);
5291 * If a property n/v pair was specified, warn the user if there was
5292 * nothing to output.
5294 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5295 (void) printf(gettext("No such %s resource.\n"),
5296 rt_to_str(RT_DEVICE
));
5300 output_rctl(FILE *fp
, struct zone_rctltab
*rctltab
)
5302 struct zone_rctlvaltab
*valptr
;
5304 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_RCTL
));
5305 output_prop(fp
, PT_NAME
, rctltab
->zone_rctl_name
, B_TRUE
);
5306 for (valptr
= rctltab
->zone_rctl_valptr
; valptr
!= NULL
;
5307 valptr
= valptr
->zone_rctlval_next
) {
5308 fprintf(fp
, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
5309 pt_to_str(PT_VALUE
),
5310 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
5311 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
5312 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
5317 info_rctl(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5319 struct zone_rctltab lookup
, user
;
5320 boolean_t output
= B_FALSE
;
5322 if (zonecfg_setrctlent(handle
) != Z_OK
)
5324 while (zonecfg_getrctlent(handle
, &lookup
) == Z_OK
) {
5325 if (cmd
->cmd_prop_nv_pairs
== 0) {
5326 output_rctl(fp
, &lookup
);
5327 } else if (fill_in_rctltab(cmd
, &user
, B_TRUE
) == Z_OK
&&
5328 (strlen(user
.zone_rctl_name
) == 0 ||
5329 strcmp(user
.zone_rctl_name
, lookup
.zone_rctl_name
) == 0)) {
5330 output_rctl(fp
, &lookup
);
5333 zonecfg_free_rctl_value_list(lookup
.zone_rctl_valptr
);
5335 (void) zonecfg_endrctlent(handle
);
5337 * If a property n/v pair was specified, warn the user if there was
5338 * nothing to output.
5340 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5341 (void) printf(gettext("No such %s resource.\n"),
5342 rt_to_str(RT_RCTL
));
5346 output_attr(FILE *fp
, struct zone_attrtab
*attrtab
)
5348 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ATTR
));
5349 output_prop(fp
, PT_NAME
, attrtab
->zone_attr_name
, B_TRUE
);
5350 output_prop(fp
, PT_TYPE
, attrtab
->zone_attr_type
, B_TRUE
);
5351 output_prop(fp
, PT_VALUE
, attrtab
->zone_attr_value
, B_TRUE
);
5355 info_attr(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5357 struct zone_attrtab lookup
, user
;
5358 boolean_t output
= B_FALSE
;
5360 if (zonecfg_setattrent(handle
) != Z_OK
)
5362 while (zonecfg_getattrent(handle
, &lookup
) == Z_OK
) {
5363 if (cmd
->cmd_prop_nv_pairs
== 0) {
5364 output_attr(fp
, &lookup
);
5367 if (fill_in_attrtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5369 if (strlen(user
.zone_attr_name
) > 0 &&
5370 strcmp(user
.zone_attr_name
, lookup
.zone_attr_name
) != 0)
5371 continue; /* no match */
5372 if (strlen(user
.zone_attr_type
) > 0 &&
5373 strcmp(user
.zone_attr_type
, lookup
.zone_attr_type
) != 0)
5374 continue; /* no match */
5375 if (strlen(user
.zone_attr_value
) > 0 &&
5376 strcmp(user
.zone_attr_value
, lookup
.zone_attr_value
) != 0)
5377 continue; /* no match */
5378 output_attr(fp
, &lookup
);
5381 (void) zonecfg_endattrent(handle
);
5383 * If a property n/v pair was specified, warn the user if there was
5384 * nothing to output.
5386 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5387 (void) printf(gettext("No such %s resource.\n"),
5388 rt_to_str(RT_ATTR
));
5392 output_ds(FILE *fp
, struct zone_dstab
*dstab
)
5394 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DATASET
));
5395 output_prop(fp
, PT_NAME
, dstab
->zone_dataset_name
, B_TRUE
);
5399 info_ds(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5401 struct zone_dstab lookup
, user
;
5402 boolean_t output
= B_FALSE
;
5404 if (zonecfg_setdsent(handle
) != Z_OK
)
5406 while (zonecfg_getdsent(handle
, &lookup
) == Z_OK
) {
5407 if (cmd
->cmd_prop_nv_pairs
== 0) {
5408 output_ds(fp
, &lookup
);
5411 if (fill_in_dstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5413 if (strlen(user
.zone_dataset_name
) > 0 &&
5414 strcmp(user
.zone_dataset_name
,
5415 lookup
.zone_dataset_name
) != 0)
5416 continue; /* no match */
5417 output_ds(fp
, &lookup
);
5420 (void) zonecfg_enddsent(handle
);
5422 * If a property n/v pair was specified, warn the user if there was
5423 * nothing to output.
5425 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5426 (void) printf(gettext("No such %s resource.\n"),
5427 rt_to_str(RT_DATASET
));
5431 output_pset(FILE *fp
, struct zone_psettab
*psettab
)
5433 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DCPU
));
5434 if (strcmp(psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
) == 0)
5435 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_NCPUS
),
5436 psettab
->zone_ncpu_max
);
5438 (void) fprintf(fp
, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS
),
5439 psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
);
5440 if (psettab
->zone_importance
[0] != '\0')
5441 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE
),
5442 psettab
->zone_importance
);
5446 info_pset(zone_dochandle_t handle
, FILE *fp
)
5448 struct zone_psettab lookup
;
5450 if (zonecfg_getpsetent(handle
, &lookup
) == Z_OK
)
5451 output_pset(fp
, &lookup
);
5455 output_pcap(FILE *fp
)
5459 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &cap
) == Z_OK
) {
5460 float scaled
= (float)cap
/ 100;
5461 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_PCAP
));
5462 (void) fprintf(fp
, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS
),
5475 info_aliased_rctl(zone_dochandle_t handle
, FILE *fp
, char *alias
)
5479 if (zonecfg_get_aliased_rctl(handle
, alias
, &limit
) == Z_OK
) {
5480 /* convert memory based properties */
5481 if (strcmp(alias
, ALIAS_MAXSHMMEM
) == 0) {
5484 (void) snprintf(buf
, sizeof (buf
), "%llu", limit
);
5485 bytes_to_units(buf
, buf
, sizeof (buf
));
5486 (void) fprintf(fp
, "[%s: %s]\n", alias
, buf
);
5490 (void) fprintf(fp
, "[%s: %llu]\n", alias
, limit
);
5495 bytes_to_units(char *str
, char *buf
, int bufsize
)
5497 unsigned long long num
;
5498 unsigned long long save
= 0;
5499 char *units
= "BKMGT";
5502 num
= strtoll(str
, NULL
, 10);
5505 (void) snprintf(buf
, bufsize
, "%llu", num
);
5509 while ((num
>= 1024) && (*up
!= 'T')) {
5510 up
++; /* next unit of measurement */
5512 num
= (num
+ 512) >> 10;
5515 /* check if we should output a fraction. snprintf will round for us */
5516 if (save
% 1024 != 0 && ((save
>> 10) < 10))
5517 (void) snprintf(buf
, bufsize
, "%2.1f%c", ((float)save
/ 1024),
5520 (void) snprintf(buf
, bufsize
, "%llu%c", num
, *up
);
5524 output_mcap(FILE *fp
, struct zone_mcaptab
*mcaptab
, int showswap
,
5525 uint64_t maxswap
, int showlocked
, uint64_t maxlocked
)
5529 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_MCAP
));
5530 if (mcaptab
->zone_physmem_cap
[0] != '\0') {
5531 bytes_to_units(mcaptab
->zone_physmem_cap
, buf
, sizeof (buf
));
5532 output_prop(fp
, PT_PHYSICAL
, buf
, B_TRUE
);
5535 if (showswap
== Z_OK
) {
5536 (void) snprintf(buf
, sizeof (buf
), "%llu", maxswap
);
5537 bytes_to_units(buf
, buf
, sizeof (buf
));
5538 output_prop(fp
, PT_SWAP
, buf
, B_TRUE
);
5541 if (showlocked
== Z_OK
) {
5542 (void) snprintf(buf
, sizeof (buf
), "%llu", maxlocked
);
5543 bytes_to_units(buf
, buf
, sizeof (buf
));
5544 output_prop(fp
, PT_LOCKED
, buf
, B_TRUE
);
5549 info_mcap(zone_dochandle_t handle
, FILE *fp
)
5551 int res1
, res2
, res3
;
5552 uint64_t swap_limit
;
5553 uint64_t locked_limit
;
5554 struct zone_mcaptab lookup
;
5556 bzero(&lookup
, sizeof (lookup
));
5557 res1
= zonecfg_getmcapent(handle
, &lookup
);
5558 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &swap_limit
);
5559 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
5562 if (res1
== Z_OK
|| res2
== Z_OK
|| res3
== Z_OK
)
5563 output_mcap(fp
, &lookup
, res2
, swap_limit
, res3
, locked_limit
);
5567 output_auth(FILE *fp
, struct zone_admintab
*admintab
)
5569 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ADMIN
));
5570 output_prop(fp
, PT_USER
, admintab
->zone_admin_user
, B_TRUE
);
5571 output_prop(fp
, PT_AUTHS
, admintab
->zone_admin_auths
, B_TRUE
);
5575 output_secflags(FILE *fp
, struct zone_secflagstab
*sftab
)
5577 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_SECFLAGS
));
5578 output_prop(fp
, PT_DEFAULT
, sftab
->zone_secflags_default
, B_TRUE
);
5579 output_prop(fp
, PT_LOWER
, sftab
->zone_secflags_lower
, B_TRUE
);
5580 output_prop(fp
, PT_UPPER
, sftab
->zone_secflags_upper
, B_TRUE
);
5584 info_auth(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5586 struct zone_admintab lookup
, user
;
5587 boolean_t output
= B_FALSE
;
5590 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
5591 zone_perror(zone
, err
, B_TRUE
);
5594 while (zonecfg_getadminent(handle
, &lookup
) == Z_OK
) {
5595 if (cmd
->cmd_prop_nv_pairs
== 0) {
5596 output_auth(fp
, &lookup
);
5599 if (fill_in_admintab(cmd
, &user
, B_TRUE
) != Z_OK
)
5601 if (strlen(user
.zone_admin_user
) > 0 &&
5602 strcmp(user
.zone_admin_user
, lookup
.zone_admin_user
) != 0)
5603 continue; /* no match */
5604 output_auth(fp
, &lookup
);
5607 (void) zonecfg_endadminent(handle
);
5609 * If a property n/v pair was specified, warn the user if there was
5610 * nothing to output.
5612 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5613 (void) printf(gettext("No such %s resource.\n"),
5614 rt_to_str(RT_ADMIN
));
5618 info_secflags(zone_dochandle_t handle
, FILE *fp
)
5620 struct zone_secflagstab sftab
;
5622 if (zonecfg_lookup_secflags(handle
, &sftab
) == Z_OK
) {
5623 output_secflags(fp
, &sftab
);
5628 info_func(cmd_t
*cmd
)
5631 boolean_t need_to_close
= B_FALSE
;
5634 uint64_t swap_limit
;
5635 uint64_t locked_limit
;
5637 assert(cmd
!= NULL
);
5639 if (initialize(B_TRUE
) != Z_OK
)
5642 /* don't page error output */
5643 if (interactive_mode
) {
5644 if ((fp
= pager_open()) != NULL
)
5645 need_to_close
= B_TRUE
;
5652 if (!global_scope
) {
5653 switch (resource_scope
) {
5655 output_fs(fp
, &in_progress_fstab
);
5658 output_net(fp
, &in_progress_nwiftab
);
5661 output_dev(fp
, &in_progress_devtab
);
5664 output_rctl(fp
, &in_progress_rctltab
);
5667 output_attr(fp
, &in_progress_attrtab
);
5670 output_ds(fp
, &in_progress_dstab
);
5673 output_pset(fp
, &in_progress_psettab
);
5679 res1
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
5681 res2
= zonecfg_get_aliased_rctl(handle
,
5682 ALIAS_MAXLOCKEDMEM
, &locked_limit
);
5683 output_mcap(fp
, &in_progress_mcaptab
, res1
, swap_limit
,
5684 res2
, locked_limit
);
5687 output_auth(fp
, &in_progress_admintab
);
5690 output_secflags(fp
, &in_progress_secflagstab
);
5696 type
= cmd
->cmd_res_type
;
5698 if (gz_invalid_rt_property(type
)) {
5699 zerr(gettext("%s is not a valid property for the global zone."),
5704 if (gz_invalid_resource(type
)) {
5705 zerr(gettext("%s is not a valid resource for the global zone."),
5710 switch (cmd
->cmd_res_type
) {
5712 info_zonename(handle
, fp
);
5714 info_zonepath(handle
, fp
);
5715 info_brand(handle
, fp
);
5716 info_autoboot(handle
, fp
);
5717 info_bootargs(handle
, fp
);
5719 info_pool(handle
, fp
);
5721 info_limitpriv(handle
, fp
);
5722 info_sched(handle
, fp
);
5723 info_iptype(handle
, fp
);
5724 info_hostid(handle
, fp
);
5725 info_fs_allowed(handle
, fp
);
5727 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5728 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5729 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5730 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5731 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5732 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5733 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5735 info_fs(handle
, fp
, cmd
);
5736 info_net(handle
, fp
, cmd
);
5737 info_dev(handle
, fp
, cmd
);
5739 info_pset(handle
, fp
);
5741 info_mcap(handle
, fp
);
5743 info_attr(handle
, fp
, cmd
);
5744 info_ds(handle
, fp
, cmd
);
5745 info_auth(handle
, fp
, cmd
);
5747 info_rctl(handle
, fp
, cmd
);
5748 info_secflags(handle
, fp
);
5751 info_zonename(handle
, fp
);
5754 info_zonepath(handle
, fp
);
5757 info_brand(handle
, fp
);
5760 info_autoboot(handle
, fp
);
5763 info_pool(handle
, fp
);
5766 info_limitpriv(handle
, fp
);
5769 info_bootargs(handle
, fp
);
5772 info_sched(handle
, fp
);
5775 info_iptype(handle
, fp
);
5778 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5781 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5784 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5787 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5790 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5793 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5796 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5799 info_fs(handle
, fp
, cmd
);
5802 info_net(handle
, fp
, cmd
);
5805 info_dev(handle
, fp
, cmd
);
5808 info_rctl(handle
, fp
, cmd
);
5811 info_attr(handle
, fp
, cmd
);
5814 info_ds(handle
, fp
, cmd
);
5817 info_pset(handle
, fp
);
5823 info_mcap(handle
, fp
);
5826 info_hostid(handle
, fp
);
5829 info_auth(handle
, fp
, cmd
);
5832 info_fs_allowed(handle
, fp
);
5835 info_secflags(handle
, fp
);
5838 zone_perror(rt_to_str(cmd
->cmd_res_type
), Z_NO_RESOURCE_TYPE
,
5844 (void) pager_close(fp
);
5848 * Helper function for verify-- checks that a required string property
5852 check_reqd_prop(char *attr
, int rt
, int pt
, int *ret_val
)
5854 if (strlen(attr
) == 0) {
5855 zerr(gettext("%s: %s not specified"), rt_to_str(rt
),
5858 if (*ret_val
== Z_OK
)
5859 *ret_val
= Z_REQD_PROPERTY_MISSING
;
5864 do_subproc(char *cmdbuf
)
5866 char inbuf
[MAX_CMD_LEN
];
5870 file
= popen(cmdbuf
, "r");
5872 zerr(gettext("Could not launch: %s"), cmdbuf
);
5876 while (fgets(inbuf
, sizeof (inbuf
), file
) != NULL
)
5877 fprintf(stderr
, "%s", inbuf
);
5878 status
= pclose(file
);
5880 if (WIFSIGNALED(status
)) {
5881 zerr(gettext("%s unexpectedly terminated due to signal %d"),
5882 cmdbuf
, WTERMSIG(status
));
5885 assert(WIFEXITED(status
));
5886 return (WEXITSTATUS(status
));
5890 brand_verify(zone_dochandle_t handle
)
5893 char cmdbuf
[MAX_CMD_LEN
];
5895 char brand
[MAXNAMELEN
];
5898 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
5899 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
5900 return (Z_INVALID_DOCUMENT
);
5902 if ((bh
= brand_open(brand
)) == NULL
) {
5903 zerr("%s: %s\n", zone
, gettext("unknown brand."));
5904 return (Z_INVALID_DOCUMENT
);
5908 * Fetch the verify command, if any, from the brand configuration
5909 * and build the command line to execute it.
5911 strcpy(cmdbuf
, EXEC_PREFIX
);
5912 err
= brand_get_verify_cfg(bh
, cmdbuf
+ EXEC_LEN
,
5913 sizeof (cmdbuf
) - (EXEC_LEN
+ (strlen(xml_file
) + 1)));
5916 zerr("%s: %s\n", zone
,
5917 gettext("could not get brand verification command"));
5918 return (Z_INVALID_DOCUMENT
);
5922 * If the brand doesn't provide a verification routine, we just
5925 if (strlen(cmdbuf
) == EXEC_LEN
)
5929 * Dump the current config information for this zone to a file.
5931 strcpy(xml_file
, "/tmp/zonecfg_verify.XXXXXX");
5932 if (mkstemp(xml_file
) == 0)
5933 return (Z_TEMP_FILE
);
5934 if ((err
= zonecfg_verify_save(handle
, xml_file
)) != Z_OK
) {
5935 (void) unlink(xml_file
);
5940 * Execute the verification command.
5942 if ((strlcat(cmdbuf
, " ", MAX_CMD_LEN
) >= MAX_CMD_LEN
) ||
5943 (strlcat(cmdbuf
, xml_file
, MAX_CMD_LEN
) >= MAX_CMD_LEN
)) {
5944 err
= Z_BRAND_ERROR
;
5946 err
= do_subproc(cmdbuf
);
5949 (void) unlink(xml_file
);
5950 return ((err
== Z_OK
) ? Z_OK
: Z_BRAND_ERROR
);
5954 * Track the network interfaces listed in zonecfg(1m) in a linked list
5955 * so that we can later check that defrouter is specified for an exclusive IP
5956 * zone if and only if at least one allowed-address has been specified.
5959 add_nwif(struct zone_nwiftab
*nwif
)
5963 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
5964 if (strcmp(tmp
->xif_name
, nwif
->zone_nwif_physical
) == 0) {
5965 if (strlen(nwif
->zone_nwif_allowed_address
) > 0)
5966 tmp
->xif_has_address
= B_TRUE
;
5967 if (strlen(nwif
->zone_nwif_defrouter
) > 0)
5968 tmp
->xif_has_defrouter
= B_TRUE
;
5973 tmp
= malloc(sizeof (*tmp
));
5975 zerr(gettext("memory allocation failed for %s"),
5976 nwif
->zone_nwif_physical
);
5979 strlcpy(tmp
->xif_name
, nwif
->zone_nwif_physical
,
5980 sizeof (tmp
->xif_name
));
5981 tmp
->xif_has_defrouter
= (strlen(nwif
->zone_nwif_defrouter
) > 0);
5982 tmp
->xif_has_address
= (strlen(nwif
->zone_nwif_allowed_address
) > 0);
5983 tmp
->xif_next
= xif
;
5989 verify_secflags(struct zone_secflagstab
*tab
)
5991 secflagdelta_t def
= {0};
5992 secflagdelta_t upper
= {0};
5993 secflagdelta_t lower
= {0};
5994 boolean_t def_set
= B_FALSE
;
5995 boolean_t upper_set
= B_FALSE
;
5996 boolean_t lower_set
= B_FALSE
;
5997 boolean_t ret
= B_TRUE
;
5999 if (strlen(tab
->zone_secflags_default
) > 0) {
6001 if (secflags_parse(NULL
, tab
->zone_secflags_default
,
6003 zerr(gettext("default security flags '%s' are invalid"),
6004 tab
->zone_secflags_default
);
6008 secflags_zero(&def
.psd_assign
);
6009 def
.psd_ass_active
= B_TRUE
;
6012 if (strlen(tab
->zone_secflags_upper
) > 0) {
6014 if (secflags_parse(NULL
, tab
->zone_secflags_upper
,
6016 zerr(gettext("upper security flags '%s' are invalid"),
6017 tab
->zone_secflags_upper
);
6021 secflags_fullset(&upper
.psd_assign
);
6022 upper
.psd_ass_active
= B_TRUE
;
6025 if (strlen(tab
->zone_secflags_lower
) > 0) {
6027 if (secflags_parse(NULL
, tab
->zone_secflags_lower
,
6029 zerr(gettext("lower security flags '%s' are invalid"),
6030 tab
->zone_secflags_lower
);
6034 secflags_zero(&lower
.psd_assign
);
6035 lower
.psd_ass_active
= B_TRUE
;
6038 if (def_set
&& !def
.psd_ass_active
) {
6039 zerr(gettext("only assignment of security flags is "
6040 "allowed (default: %s)"), tab
->zone_secflags_default
);
6043 if (lower_set
&& !lower
.psd_ass_active
) {
6044 zerr(gettext("only assignment of security flags is "
6045 "allowed (lower: %s)"), tab
->zone_secflags_lower
);
6048 if (upper_set
&& !upper
.psd_ass_active
) {
6049 zerr(gettext("only assignment of security flags is "
6050 "allowed (upper: %s)"), tab
->zone_secflags_upper
);
6053 if (def
.psd_assign
& ~upper
.psd_assign
) { /* In default but not upper */
6054 zerr(gettext("default secflags must be within the "
6058 if (lower
.psd_assign
& ~def
.psd_assign
) { /* In lower but not default */
6059 zerr(gettext("default secflags must be above the lower limit"));
6062 if (lower
.psd_assign
& ~upper
.psd_assign
) { /* In lower but not upper */
6063 zerr(gettext("lower secflags must be within the upper limit"));
6071 * See the DTD for which attributes are required for which resources.
6073 * This function can be called by commit_func(), which needs to save things,
6074 * in addition to the general call from parse_and_run(), which doesn't need
6075 * things saved. Since the parameters are standardized, we distinguish by
6076 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6077 * that a save is needed.
6080 verify_func(cmd_t
*cmd
)
6082 struct zone_nwiftab nwiftab
;
6083 struct zone_fstab fstab
;
6084 struct zone_attrtab attrtab
;
6085 struct zone_rctltab rctltab
;
6086 struct zone_dstab dstab
;
6087 struct zone_psettab psettab
;
6088 struct zone_admintab admintab
;
6089 struct zone_secflagstab secflagstab
;
6090 char zonepath
[MAXPATHLEN
];
6091 char sched
[MAXNAMELEN
];
6092 char brand
[MAXNAMELEN
];
6093 char hostidp
[HW_HOSTID_LEN
];
6094 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
6096 char *privname
= NULL
;
6097 int err
, ret_val
= Z_OK
, arg
;
6099 boolean_t save
= B_FALSE
;
6100 boolean_t arg_err
= B_FALSE
;
6101 zone_iptype_t iptype
;
6102 boolean_t has_cpu_shares
= B_FALSE
;
6103 boolean_t has_cpu_cap
= B_FALSE
;
6107 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6110 longer_usage(CMD_VERIFY
);
6114 short_usage(CMD_VERIFY
);
6122 if (optind
> cmd
->cmd_argc
) {
6123 short_usage(CMD_VERIFY
);
6127 if (zone_is_read_only(CMD_VERIFY
))
6130 assert(cmd
!= NULL
);
6132 if (cmd
->cmd_argc
> 0 && (strcmp(cmd
->cmd_argv
[0], "save") == 0))
6134 if (initialize(B_TRUE
) != Z_OK
)
6137 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) != Z_OK
&&
6139 zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH
));
6140 ret_val
= Z_REQD_RESOURCE_MISSING
;
6143 if (strlen(zonepath
) == 0 && !global_zone
) {
6144 zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH
));
6145 ret_val
= Z_REQD_RESOURCE_MISSING
;
6149 if ((err
= zonecfg_get_brand(handle
, brand
, sizeof (brand
))) != Z_OK
) {
6150 zone_perror(zone
, err
, B_TRUE
);
6153 if ((err
= brand_verify(handle
)) != Z_OK
) {
6154 zone_perror(zone
, err
, B_TRUE
);
6158 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
6159 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE
));
6160 ret_val
= Z_REQD_RESOURCE_MISSING
;
6164 if ((privs
= priv_allocset()) == NULL
) {
6165 zerr(gettext("%s: priv_allocset failed"), zone
);
6168 if (zonecfg_get_privset(handle
, privs
, &privname
) != Z_OK
) {
6169 zerr(gettext("%s: invalid privilege: %s"), zone
, privname
);
6170 priv_freeset(privs
);
6174 priv_freeset(privs
);
6176 if (zonecfg_get_hostid(handle
, hostidp
,
6177 sizeof (hostidp
)) == Z_INVALID_PROPERTY
) {
6178 zerr(gettext("%s: invalid hostid: %s"),
6183 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
6184 sizeof (fsallowedp
)) == Z_INVALID_PROPERTY
) {
6185 zerr(gettext("%s: invalid fs-allowed: %s"),
6190 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
6191 zone_perror(zone
, err
, B_TRUE
);
6194 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
6195 check_reqd_prop(fstab
.zone_fs_dir
, RT_FS
, PT_DIR
, &ret_val
);
6196 check_reqd_prop(fstab
.zone_fs_special
, RT_FS
, PT_SPECIAL
,
6198 check_reqd_prop(fstab
.zone_fs_type
, RT_FS
, PT_TYPE
, &ret_val
);
6200 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
6202 (void) zonecfg_endfsent(handle
);
6204 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
6205 zone_perror(zone
, err
, B_TRUE
);
6208 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
6210 * physical is required in all cases.
6211 * A shared IP requires an address,
6212 * and may include a default router, while
6213 * an exclusive IP must have neither an address
6214 * nor a default router.
6215 * The physical interface name must be valid in all cases.
6217 check_reqd_prop(nwiftab
.zone_nwif_physical
, RT_NET
,
6218 PT_PHYSICAL
, &ret_val
);
6219 if (validate_net_physical_syntax(nwiftab
.zone_nwif_physical
) !=
6222 if (ret_val
== Z_OK
)
6228 check_reqd_prop(nwiftab
.zone_nwif_address
, RT_NET
,
6229 PT_ADDRESS
, &ret_val
);
6230 if (strlen(nwiftab
.zone_nwif_allowed_address
) > 0) {
6231 zerr(gettext("%s: %s cannot be specified "
6232 "for a shared IP type"),
6234 pt_to_str(PT_ALLOWED_ADDRESS
));
6236 if (ret_val
== Z_OK
)
6241 if (strlen(nwiftab
.zone_nwif_address
) > 0) {
6242 zerr(gettext("%s: %s cannot be specified "
6243 "for an exclusive IP type"),
6244 rt_to_str(RT_NET
), pt_to_str(PT_ADDRESS
));
6246 if (ret_val
== Z_OK
)
6249 if (!add_nwif(&nwiftab
)) {
6251 if (ret_val
== Z_OK
)
6258 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
6259 if (!tmp
->xif_has_address
&& tmp
->xif_has_defrouter
) {
6260 zerr(gettext("%s: %s for %s cannot be specified "
6261 "without %s for an exclusive IP type"),
6262 rt_to_str(RT_NET
), pt_to_str(PT_DEFROUTER
),
6263 tmp
->xif_name
, pt_to_str(PT_ALLOWED_ADDRESS
));
6270 (void) zonecfg_endnwifent(handle
);
6272 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
6273 zone_perror(zone
, err
, B_TRUE
);
6276 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
6277 check_reqd_prop(rctltab
.zone_rctl_name
, RT_RCTL
, PT_NAME
,
6280 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-shares") == 0)
6281 has_cpu_shares
= B_TRUE
;
6283 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-cap") == 0)
6284 has_cpu_cap
= B_TRUE
;
6286 if (rctltab
.zone_rctl_valptr
== NULL
) {
6287 zerr(gettext("%s: no %s specified"),
6288 rt_to_str(RT_RCTL
), pt_to_str(PT_VALUE
));
6290 if (ret_val
== Z_OK
)
6291 ret_val
= Z_REQD_PROPERTY_MISSING
;
6293 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
6296 (void) zonecfg_endrctlent(handle
);
6298 if ((pset_res
= zonecfg_lookup_pset(handle
, &psettab
)) == Z_OK
&&
6300 zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
6301 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6303 if (ret_val
== Z_OK
)
6304 ret_val
= Z_INCOMPATIBLE
;
6307 if (has_cpu_shares
&& zonecfg_get_sched_class(handle
, sched
,
6308 sizeof (sched
)) == Z_OK
&& strlen(sched
) > 0 &&
6309 strcmp(sched
, "FSS") != 0) {
6310 zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
6312 rt_to_str(RT_RCTL
), rt_to_str(RT_SCHED
), sched
);
6314 if (ret_val
== Z_OK
)
6315 ret_val
= Z_INCOMPATIBLE
;
6318 if (pset_res
== Z_OK
&& has_cpu_cap
) {
6319 zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
6320 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6322 if (ret_val
== Z_OK
)
6323 ret_val
= Z_INCOMPATIBLE
;
6326 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
6327 zone_perror(zone
, err
, B_TRUE
);
6330 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
6331 check_reqd_prop(attrtab
.zone_attr_name
, RT_ATTR
, PT_NAME
,
6333 check_reqd_prop(attrtab
.zone_attr_type
, RT_ATTR
, PT_TYPE
,
6335 check_reqd_prop(attrtab
.zone_attr_value
, RT_ATTR
, PT_VALUE
,
6338 (void) zonecfg_endattrent(handle
);
6340 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
6341 zone_perror(zone
, err
, B_TRUE
);
6344 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
6345 if (strlen(dstab
.zone_dataset_name
) == 0) {
6346 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6347 pt_to_str(PT_NAME
), gettext("not specified"));
6349 if (ret_val
== Z_OK
)
6350 ret_val
= Z_REQD_PROPERTY_MISSING
;
6351 } else if (!zfs_name_valid(dstab
.zone_dataset_name
,
6352 ZFS_TYPE_FILESYSTEM
)) {
6353 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6354 pt_to_str(PT_NAME
), gettext("invalid"));
6356 if (ret_val
== Z_OK
)
6357 ret_val
= Z_BAD_PROPERTY
;
6361 (void) zonecfg_enddsent(handle
);
6363 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
6364 zone_perror(zone
, err
, B_TRUE
);
6367 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
6368 check_reqd_prop(admintab
.zone_admin_user
, RT_ADMIN
,
6370 check_reqd_prop(admintab
.zone_admin_auths
, RT_ADMIN
,
6371 PT_AUTHS
, &ret_val
);
6372 if ((ret_val
== Z_OK
) && (getpwnam(admintab
.zone_admin_user
)
6374 zerr(gettext("%s %s is not a valid username"),
6376 admintab
.zone_admin_user
);
6377 ret_val
= Z_BAD_PROPERTY
;
6379 if ((ret_val
== Z_OK
) && (!zonecfg_valid_auths(
6380 admintab
.zone_admin_auths
, zone
))) {
6381 ret_val
= Z_BAD_PROPERTY
;
6384 (void) zonecfg_endadminent(handle
);
6386 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
6388 * No properties are required, but any specified should be
6391 if (verify_secflags(&secflagstab
) != B_TRUE
) {
6392 /* Error is reported from verify_secflags */
6393 ret_val
= Z_BAD_PROPERTY
;
6397 if (!global_scope
) {
6398 zerr(gettext("resource specification incomplete"));
6400 if (ret_val
== Z_OK
)
6401 ret_val
= Z_INSUFFICIENT_SPEC
;
6405 if (ret_val
== Z_OK
) {
6406 if ((ret_val
= zonecfg_save(handle
)) == Z_OK
) {
6407 need_to_commit
= B_FALSE
;
6408 (void) strlcpy(revert_zone
, zone
,
6409 sizeof (revert_zone
));
6412 zerr(gettext("Zone %s failed to verify"), zone
);
6415 if (ret_val
!= Z_OK
)
6416 zone_perror(zone
, ret_val
, B_TRUE
);
6420 cancel_func(cmd_t
*cmd
)
6423 boolean_t arg_err
= B_FALSE
;
6425 assert(cmd
!= NULL
);
6428 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6431 longer_usage(CMD_CANCEL
);
6435 short_usage(CMD_CANCEL
);
6443 if (optind
!= cmd
->cmd_argc
) {
6444 short_usage(CMD_CANCEL
);
6449 scope_usage(CMD_CANCEL
);
6450 global_scope
= B_TRUE
;
6451 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6452 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
6453 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
6454 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
6455 zonecfg_free_rctl_value_list(in_progress_rctltab
.zone_rctl_valptr
);
6456 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
6457 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
6458 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
6462 validate_attr_name(char *name
)
6466 if (!isalnum(name
[0])) {
6467 zerr(gettext("Invalid %s %s %s: must start with an alpha-"
6468 "numeric character."), rt_to_str(RT_ATTR
),
6469 pt_to_str(PT_NAME
), name
);
6472 for (i
= 1; name
[i
]; i
++)
6473 if (!isalnum(name
[i
]) && name
[i
] != '-' && name
[i
] != '.') {
6474 zerr(gettext("Invalid %s %s %s: can only contain "
6475 "alpha-numeric characters, plus '-' and '.'."),
6476 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
), name
);
6483 validate_attr_type_val(struct zone_attrtab
*attrtab
)
6487 char strval
[MAXNAMELEN
];
6490 if (strcmp(attrtab
->zone_attr_type
, "boolean") == 0) {
6491 if (zonecfg_get_attr_boolean(attrtab
, &boolval
) == Z_OK
)
6493 zerr(gettext("invalid %s value for %s=%s"),
6494 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "boolean");
6498 if (strcmp(attrtab
->zone_attr_type
, "int") == 0) {
6499 if (zonecfg_get_attr_int(attrtab
, &intval
) == Z_OK
)
6501 zerr(gettext("invalid %s value for %s=%s"),
6502 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "int");
6506 if (strcmp(attrtab
->zone_attr_type
, "string") == 0) {
6507 if (zonecfg_get_attr_string(attrtab
, strval
,
6508 sizeof (strval
)) == Z_OK
)
6510 zerr(gettext("invalid %s value for %s=%s"),
6511 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "string");
6515 if (strcmp(attrtab
->zone_attr_type
, "uint") == 0) {
6516 if (zonecfg_get_attr_uint(attrtab
, &uintval
) == Z_OK
)
6518 zerr(gettext("invalid %s value for %s=%s"),
6519 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "uint");
6523 zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR
),
6524 pt_to_str(PT_TYPE
), attrtab
->zone_attr_type
);
6529 * Helper function for end_func-- checks the existence of a given property
6530 * and emits a message if not specified.
6533 end_check_reqd(char *attr
, int pt
, boolean_t
*validation_failed
)
6535 if (strlen(attr
) == 0) {
6536 *validation_failed
= B_TRUE
;
6537 zerr(gettext("%s not specified"), pt_to_str(pt
));
6544 net_exists_error(struct zone_nwiftab nwif
)
6546 if (strlen(nwif
.zone_nwif_address
) > 0) {
6547 zerr(gettext("A %s resource with the %s '%s', "
6548 "and %s '%s' already exists."),
6550 pt_to_str(PT_PHYSICAL
),
6551 nwif
.zone_nwif_physical
,
6552 pt_to_str(PT_ADDRESS
),
6553 in_progress_nwiftab
.zone_nwif_address
);
6555 zerr(gettext("A %s resource with the %s '%s', "
6556 "and %s '%s' already exists."),
6558 pt_to_str(PT_PHYSICAL
),
6559 nwif
.zone_nwif_physical
,
6560 pt_to_str(PT_ALLOWED_ADDRESS
),
6561 nwif
.zone_nwif_allowed_address
);
6566 end_func(cmd_t
*cmd
)
6568 boolean_t validation_failed
= B_FALSE
;
6569 boolean_t arg_err
= B_FALSE
;
6570 struct zone_fstab tmp_fstab
;
6571 struct zone_nwiftab tmp_nwiftab
;
6572 struct zone_devtab tmp_devtab
;
6573 struct zone_rctltab tmp_rctltab
;
6574 struct zone_attrtab tmp_attrtab
;
6575 struct zone_dstab tmp_dstab
;
6576 struct zone_admintab tmp_admintab
;
6577 int err
, arg
, res1
, res2
, res3
;
6578 uint64_t swap_limit
;
6579 uint64_t locked_limit
;
6582 assert(cmd
!= NULL
);
6585 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6588 longer_usage(CMD_END
);
6592 short_usage(CMD_END
);
6600 if (optind
!= cmd
->cmd_argc
) {
6601 short_usage(CMD_END
);
6606 scope_usage(CMD_END
);
6610 assert(end_op
== CMD_ADD
|| end_op
== CMD_SELECT
);
6612 switch (resource_scope
) {
6614 /* First make sure everything was filled in. */
6615 if (end_check_reqd(in_progress_fstab
.zone_fs_dir
,
6616 PT_DIR
, &validation_failed
) == Z_OK
) {
6617 if (in_progress_fstab
.zone_fs_dir
[0] != '/') {
6618 zerr(gettext("%s %s is not an absolute path."),
6620 in_progress_fstab
.zone_fs_dir
);
6621 validation_failed
= B_TRUE
;
6625 (void) end_check_reqd(in_progress_fstab
.zone_fs_special
,
6626 PT_SPECIAL
, &validation_failed
);
6628 if (in_progress_fstab
.zone_fs_raw
[0] != '\0' &&
6629 in_progress_fstab
.zone_fs_raw
[0] != '/') {
6630 zerr(gettext("%s %s is not an absolute path."),
6632 in_progress_fstab
.zone_fs_raw
);
6633 validation_failed
= B_TRUE
;
6636 (void) end_check_reqd(in_progress_fstab
.zone_fs_type
, PT_TYPE
,
6637 &validation_failed
);
6639 if (validation_failed
) {
6644 if (end_op
== CMD_ADD
) {
6645 /* Make sure there isn't already one like this. */
6646 bzero(&tmp_fstab
, sizeof (tmp_fstab
));
6647 (void) strlcpy(tmp_fstab
.zone_fs_dir
,
6648 in_progress_fstab
.zone_fs_dir
,
6649 sizeof (tmp_fstab
.zone_fs_dir
));
6650 err
= zonecfg_lookup_filesystem(handle
, &tmp_fstab
);
6651 zonecfg_free_fs_option_list(tmp_fstab
.zone_fs_options
);
6653 zerr(gettext("A %s resource "
6654 "with the %s '%s' already exists."),
6655 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
6656 in_progress_fstab
.zone_fs_dir
);
6660 err
= zonecfg_add_filesystem(handle
,
6661 &in_progress_fstab
);
6663 err
= zonecfg_modify_filesystem(handle
, &old_fstab
,
6664 &in_progress_fstab
);
6666 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6667 in_progress_fstab
.zone_fs_options
= NULL
;
6672 * First make sure everything was filled in.
6673 * Since we don't know whether IP will be shared
6674 * or exclusive here, some checks are deferred until
6675 * the verify command.
6677 (void) end_check_reqd(in_progress_nwiftab
.zone_nwif_physical
,
6678 PT_PHYSICAL
, &validation_failed
);
6680 if (validation_failed
) {
6684 if (end_op
== CMD_ADD
) {
6685 /* Make sure there isn't already one like this. */
6686 bzero(&tmp_nwiftab
, sizeof (tmp_nwiftab
));
6687 (void) strlcpy(tmp_nwiftab
.zone_nwif_physical
,
6688 in_progress_nwiftab
.zone_nwif_physical
,
6689 sizeof (tmp_nwiftab
.zone_nwif_physical
));
6690 (void) strlcpy(tmp_nwiftab
.zone_nwif_address
,
6691 in_progress_nwiftab
.zone_nwif_address
,
6692 sizeof (tmp_nwiftab
.zone_nwif_address
));
6693 (void) strlcpy(tmp_nwiftab
.zone_nwif_allowed_address
,
6694 in_progress_nwiftab
.zone_nwif_allowed_address
,
6695 sizeof (tmp_nwiftab
.zone_nwif_allowed_address
));
6696 (void) strlcpy(tmp_nwiftab
.zone_nwif_defrouter
,
6697 in_progress_nwiftab
.zone_nwif_defrouter
,
6698 sizeof (tmp_nwiftab
.zone_nwif_defrouter
));
6699 if (zonecfg_lookup_nwif(handle
, &tmp_nwiftab
) == Z_OK
) {
6700 net_exists_error(in_progress_nwiftab
);
6704 err
= zonecfg_add_nwif(handle
, &in_progress_nwiftab
);
6706 err
= zonecfg_modify_nwif(handle
, &old_nwiftab
,
6707 &in_progress_nwiftab
);
6712 /* First make sure everything was filled in. */
6713 (void) end_check_reqd(in_progress_devtab
.zone_dev_match
,
6714 PT_MATCH
, &validation_failed
);
6716 if (validation_failed
) {
6721 if (end_op
== CMD_ADD
) {
6722 /* Make sure there isn't already one like this. */
6723 (void) strlcpy(tmp_devtab
.zone_dev_match
,
6724 in_progress_devtab
.zone_dev_match
,
6725 sizeof (tmp_devtab
.zone_dev_match
));
6726 if (zonecfg_lookup_dev(handle
, &tmp_devtab
) == Z_OK
) {
6727 zerr(gettext("A %s resource with the %s '%s' "
6728 "already exists."), rt_to_str(RT_DEVICE
),
6729 pt_to_str(PT_MATCH
),
6730 in_progress_devtab
.zone_dev_match
);
6734 err
= zonecfg_add_dev(handle
, &in_progress_devtab
);
6736 err
= zonecfg_modify_dev(handle
, &old_devtab
,
6737 &in_progress_devtab
);
6742 /* First make sure everything was filled in. */
6743 (void) end_check_reqd(in_progress_rctltab
.zone_rctl_name
,
6744 PT_NAME
, &validation_failed
);
6746 if (in_progress_rctltab
.zone_rctl_valptr
== NULL
) {
6747 zerr(gettext("no %s specified"), pt_to_str(PT_VALUE
));
6748 validation_failed
= B_TRUE
;
6751 if (validation_failed
) {
6756 if (end_op
== CMD_ADD
) {
6757 /* Make sure there isn't already one like this. */
6758 (void) strlcpy(tmp_rctltab
.zone_rctl_name
,
6759 in_progress_rctltab
.zone_rctl_name
,
6760 sizeof (tmp_rctltab
.zone_rctl_name
));
6761 tmp_rctltab
.zone_rctl_valptr
= NULL
;
6762 err
= zonecfg_lookup_rctl(handle
, &tmp_rctltab
);
6763 zonecfg_free_rctl_value_list(
6764 tmp_rctltab
.zone_rctl_valptr
);
6766 zerr(gettext("A %s resource "
6767 "with the %s '%s' already exists."),
6768 rt_to_str(RT_RCTL
), pt_to_str(PT_NAME
),
6769 in_progress_rctltab
.zone_rctl_name
);
6773 err
= zonecfg_add_rctl(handle
, &in_progress_rctltab
);
6775 err
= zonecfg_modify_rctl(handle
, &old_rctltab
,
6776 &in_progress_rctltab
);
6779 zonecfg_free_rctl_value_list(
6780 in_progress_rctltab
.zone_rctl_valptr
);
6781 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
6786 /* First make sure everything was filled in. */
6787 (void) end_check_reqd(in_progress_attrtab
.zone_attr_name
,
6788 PT_NAME
, &validation_failed
);
6789 (void) end_check_reqd(in_progress_attrtab
.zone_attr_type
,
6790 PT_TYPE
, &validation_failed
);
6791 (void) end_check_reqd(in_progress_attrtab
.zone_attr_value
,
6792 PT_VALUE
, &validation_failed
);
6794 if (validate_attr_name(in_progress_attrtab
.zone_attr_name
) !=
6796 validation_failed
= B_TRUE
;
6798 if (validate_attr_type_val(&in_progress_attrtab
) != Z_OK
)
6799 validation_failed
= B_TRUE
;
6801 if (validation_failed
) {
6805 if (end_op
== CMD_ADD
) {
6806 /* Make sure there isn't already one like this. */
6807 bzero(&tmp_attrtab
, sizeof (tmp_attrtab
));
6808 (void) strlcpy(tmp_attrtab
.zone_attr_name
,
6809 in_progress_attrtab
.zone_attr_name
,
6810 sizeof (tmp_attrtab
.zone_attr_name
));
6811 if (zonecfg_lookup_attr(handle
, &tmp_attrtab
) == Z_OK
) {
6812 zerr(gettext("An %s resource "
6813 "with the %s '%s' already exists."),
6814 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
),
6815 in_progress_attrtab
.zone_attr_name
);
6819 err
= zonecfg_add_attr(handle
, &in_progress_attrtab
);
6821 err
= zonecfg_modify_attr(handle
, &old_attrtab
,
6822 &in_progress_attrtab
);
6826 /* First make sure everything was filled in. */
6827 if (strlen(in_progress_dstab
.zone_dataset_name
) == 0) {
6828 zerr("%s %s", pt_to_str(PT_NAME
),
6829 gettext("not specified"));
6831 validation_failed
= B_TRUE
;
6833 if (validation_failed
)
6835 if (end_op
== CMD_ADD
) {
6836 /* Make sure there isn't already one like this. */
6837 bzero(&tmp_dstab
, sizeof (tmp_dstab
));
6838 (void) strlcpy(tmp_dstab
.zone_dataset_name
,
6839 in_progress_dstab
.zone_dataset_name
,
6840 sizeof (tmp_dstab
.zone_dataset_name
));
6841 err
= zonecfg_lookup_ds(handle
, &tmp_dstab
);
6843 zerr(gettext("A %s resource "
6844 "with the %s '%s' already exists."),
6845 rt_to_str(RT_DATASET
), pt_to_str(PT_NAME
),
6846 in_progress_dstab
.zone_dataset_name
);
6850 err
= zonecfg_add_ds(handle
, &in_progress_dstab
);
6852 err
= zonecfg_modify_ds(handle
, &old_dstab
,
6853 &in_progress_dstab
);
6857 /* Make sure everything was filled in. */
6858 if (end_check_reqd(in_progress_psettab
.zone_ncpu_min
,
6859 PT_NCPUS
, &validation_failed
) != Z_OK
) {
6864 if (end_op
== CMD_ADD
) {
6865 err
= zonecfg_add_pset(handle
, &in_progress_psettab
);
6867 err
= zonecfg_modify_pset(handle
, &in_progress_psettab
);
6871 /* Make sure everything was filled in. */
6872 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &proc_cap
)
6874 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS
));
6876 validation_failed
= B_TRUE
;
6882 /* Make sure everything was filled in. */
6883 res1
= strlen(in_progress_mcaptab
.zone_physmem_cap
) == 0 ?
6885 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
6887 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
6890 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
6891 zerr(gettext("No property was specified. One of %s, "
6892 "%s or %s is required."), pt_to_str(PT_PHYSICAL
),
6893 pt_to_str(PT_SWAP
), pt_to_str(PT_LOCKED
));
6898 /* if phys & locked are both set, verify locked <= phys */
6899 if (res1
== Z_OK
&& res3
== Z_OK
) {
6900 uint64_t phys_limit
;
6903 phys_limit
= strtoull(
6904 in_progress_mcaptab
.zone_physmem_cap
, &endp
, 10);
6905 if (phys_limit
< locked_limit
) {
6906 zerr(gettext("The %s cap must be less than or "
6907 "equal to the %s cap."),
6908 pt_to_str(PT_LOCKED
),
6909 pt_to_str(PT_PHYSICAL
));
6918 * We could be ending from either an add operation
6919 * or a select operation. Since all of the properties
6920 * within this resource are optional, we always use
6921 * modify on the mcap entry. zonecfg_modify_mcap()
6922 * will handle both adding and modifying a memory cap.
6924 err
= zonecfg_modify_mcap(handle
, &in_progress_mcaptab
);
6925 } else if (end_op
== CMD_SELECT
) {
6927 * If we're ending from a select and the physical
6928 * memory cap is empty then the user could have cleared
6929 * the physical cap value, so try to delete the entry.
6931 (void) zonecfg_delete_mcap(handle
);
6935 /* First make sure everything was filled in. */
6936 if (end_check_reqd(in_progress_admintab
.zone_admin_user
,
6937 PT_USER
, &validation_failed
) == Z_OK
) {
6938 if (getpwnam(in_progress_admintab
.zone_admin_user
)
6940 zerr(gettext("%s %s is not a valid username"),
6942 in_progress_admintab
.zone_admin_user
);
6943 validation_failed
= B_TRUE
;
6947 if (end_check_reqd(in_progress_admintab
.zone_admin_auths
,
6948 PT_AUTHS
, &validation_failed
) == Z_OK
) {
6949 if (!zonecfg_valid_auths(
6950 in_progress_admintab
.zone_admin_auths
,
6952 validation_failed
= B_TRUE
;
6956 if (validation_failed
) {
6961 if (end_op
== CMD_ADD
) {
6962 /* Make sure there isn't already one like this. */
6963 bzero(&tmp_admintab
, sizeof (tmp_admintab
));
6964 (void) strlcpy(tmp_admintab
.zone_admin_user
,
6965 in_progress_admintab
.zone_admin_user
,
6966 sizeof (tmp_admintab
.zone_admin_user
));
6967 err
= zonecfg_lookup_admin(
6968 handle
, &tmp_admintab
);
6970 zerr(gettext("A %s resource "
6971 "with the %s '%s' already exists."),
6972 rt_to_str(RT_ADMIN
),
6974 in_progress_admintab
.zone_admin_user
);
6978 err
= zonecfg_add_admin(handle
,
6979 &in_progress_admintab
, zone
);
6981 err
= zonecfg_modify_admin(handle
,
6982 &old_admintab
, &in_progress_admintab
,
6987 if (verify_secflags(&in_progress_secflagstab
) != B_TRUE
) {
6992 if (end_op
== CMD_ADD
) {
6993 err
= zonecfg_add_secflags(handle
,
6994 &in_progress_secflagstab
);
6996 err
= zonecfg_modify_secflags(handle
,
6997 &old_secflagstab
, &in_progress_secflagstab
);
7001 zone_perror(rt_to_str(resource_scope
), Z_NO_RESOURCE_TYPE
,
7008 zone_perror(zone
, err
, B_TRUE
);
7010 need_to_commit
= B_TRUE
;
7011 global_scope
= B_TRUE
;
7017 commit_func(cmd_t
*cmd
)
7020 boolean_t arg_err
= B_FALSE
;
7023 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
7026 longer_usage(CMD_COMMIT
);
7030 short_usage(CMD_COMMIT
);
7038 if (optind
!= cmd
->cmd_argc
) {
7039 short_usage(CMD_COMMIT
);
7043 if (zone_is_read_only(CMD_COMMIT
))
7046 assert(cmd
!= NULL
);
7050 * cmd_arg normally comes from a strdup() in the lexer, and the
7051 * whole cmd structure and its (char *) attributes are freed at
7052 * the completion of each command, so the strdup() below is needed
7053 * to match this and prevent a core dump from trying to free()
7054 * something that can't be.
7056 if ((cmd
->cmd_argv
[0] = strdup("save")) == NULL
) {
7057 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7060 cmd
->cmd_argv
[1] = NULL
;
7065 revert_func(cmd_t
*cmd
)
7067 char line
[128]; /* enough to ask a question */
7068 boolean_t force
= B_FALSE
;
7069 boolean_t arg_err
= B_FALSE
;
7070 int err
, arg
, answer
;
7073 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
7076 longer_usage(CMD_REVERT
);
7083 short_usage(CMD_REVERT
);
7091 if (optind
!= cmd
->cmd_argc
) {
7092 short_usage(CMD_REVERT
);
7096 if (zone_is_read_only(CMD_REVERT
))
7099 if (!global_scope
) {
7100 zerr(gettext("You can only use %s in the global scope.\nUse"
7101 " '%s' to cancel changes to a resource specification."),
7102 cmd_to_str(CMD_REVERT
), cmd_to_str(CMD_CANCEL
));
7107 if (zonecfg_check_handle(handle
) != Z_OK
) {
7108 zerr(gettext("No changes to revert."));
7114 (void) snprintf(line
, sizeof (line
),
7115 gettext("Are you sure you want to revert"));
7116 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
7117 zerr(gettext("Input not from terminal and -F not "
7118 "specified:\n%s command ignored, exiting."),
7119 cmd_to_str(CMD_REVERT
));
7127 * Reset any pending admins that were
7128 * removed from the previous zone
7130 zonecfg_remove_userauths(handle
, "", zone
, B_FALSE
);
7133 * Time for a new handle: finish the old one off first
7134 * then get a new one properly to avoid leaks.
7136 zonecfg_fini_handle(handle
);
7137 if ((handle
= zonecfg_init_handle()) == NULL
) {
7138 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7142 if ((err
= zonecfg_get_handle(revert_zone
, handle
)) != Z_OK
) {
7144 got_handle
= B_FALSE
;
7145 if (err
== Z_NO_ZONE
)
7146 zerr(gettext("%s: no such saved zone to revert to."),
7149 zone_perror(zone
, err
, B_TRUE
);
7151 (void) strlcpy(zone
, revert_zone
, sizeof (zone
));
7155 help_func(cmd_t
*cmd
)
7159 assert(cmd
!= NULL
);
7161 if (cmd
->cmd_argc
== 0) {
7162 usage(B_TRUE
, global_scope
? HELP_SUBCMDS
: HELP_RES_SCOPE
);
7165 if (strcmp(cmd
->cmd_argv
[0], "usage") == 0) {
7166 usage(B_TRUE
, HELP_USAGE
);
7169 if (strcmp(cmd
->cmd_argv
[0], "commands") == 0) {
7170 usage(B_TRUE
, HELP_SUBCMDS
);
7173 if (strcmp(cmd
->cmd_argv
[0], "syntax") == 0) {
7174 usage(B_TRUE
, HELP_SYNTAX
| HELP_RES_PROPS
);
7177 if (strcmp(cmd
->cmd_argv
[0], "-?") == 0) {
7178 longer_usage(CMD_HELP
);
7182 for (i
= 0; i
<= CMD_MAX
; i
++) {
7183 if (strcmp(cmd
->cmd_argv
[0], cmd_to_str(i
)) == 0) {
7188 /* We do not use zerr() here because we do not want its extra \n. */
7189 (void) fprintf(stderr
, gettext("Unknown help subject %s. "),
7191 usage(B_FALSE
, HELP_META
);
7195 string_to_yyin(char *string
)
7197 if ((yyin
= tmpfile()) == NULL
) {
7198 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7201 if (fwrite(string
, strlen(string
), 1, yyin
) != 1) {
7202 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7205 if (fseek(yyin
, 0, SEEK_SET
) != 0) {
7206 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7212 /* This is the back-end helper function for read_input() below. */
7220 if (!interactive_mode
&& !cmd_file_mode
) {
7222 * If we're not in interactive mode, and we're not in command
7223 * file mode, then we must be in commands-from-the-command-line
7224 * mode. As such, we can't loop back and ask for more input.
7225 * It was OK to prompt for such things as whether or not to
7226 * really delete a zone in the command handler called from
7227 * yyparse() above, but "really quit?" makes no sense in this
7228 * context. So disable prompting.
7230 ok_to_prompt
= B_FALSE
;
7232 if (!global_scope
) {
7233 if (!time_to_exit
) {
7235 * Just print a simple error message in the -1 case,
7236 * since exit_func() already handles that case, and
7237 * EOF means we are finished anyway.
7239 answer
= ask_yesno(B_FALSE
,
7240 gettext("Resource incomplete; really quit"));
7242 zerr(gettext("Resource incomplete."));
7254 * Make sure we tried something and that the handle checks
7255 * out, or we would get a false error trying to commit.
7257 if (need_to_commit
&& zonecfg_check_handle(handle
) == Z_OK
) {
7258 if ((cmd
= alloc_cmd()) == NULL
) {
7259 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7263 cmd
->cmd_argv
[0] = NULL
;
7267 * need_to_commit will get set back to FALSE if the
7268 * configuration is saved successfully.
7270 if (need_to_commit
) {
7272 zerr(gettext("Configuration not saved."));
7275 answer
= ask_yesno(B_FALSE
,
7276 gettext("Configuration not saved; really quit"));
7278 zerr(gettext("Configuration not saved."));
7282 time_to_exit
= B_FALSE
;
7288 return ((need_to_commit
|| saw_error
) ? Z_ERR
: Z_OK
);
7292 * read_input() is the driver of this program. It is a wrapper around
7293 * yyparse(), printing appropriate prompts when needed, checking for
7294 * exit conditions and reacting appropriately [the latter in its cleanup()
7297 * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
7298 * so do_interactive() knows that we are not really done (i.e, we asked
7299 * the user if we should really quit and the user said no).
7304 boolean_t yyin_is_a_tty
= isatty(fileno(yyin
));
7306 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
7307 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
7309 char prompt
[MAXPATHLEN
+ ZONENAME_MAX
+ MAX_RT_STRLEN
+ 5], *line
;
7311 /* yyin should have been set to the appropriate (FILE *) if not stdin */
7312 newline_terminated
= B_TRUE
;
7314 if (yyin_is_a_tty
) {
7315 if (newline_terminated
) {
7317 (void) snprintf(prompt
, sizeof (prompt
),
7318 "%s:%s> ", execname
, zone
);
7320 (void) snprintf(prompt
, sizeof (prompt
),
7321 "%s:%s:%s> ", execname
, zone
,
7322 rt_to_str(resource_scope
));
7325 * If the user hits ^C then we want to catch it and
7326 * start over. If the user hits EOF then we want to
7329 line
= gl_get_line(gl
, prompt
, NULL
, -1);
7330 if (gl_return_status(gl
) == GLR_SIGNAL
) {
7331 gl_abandon_line(gl
);
7336 (void) string_to_yyin(line
);
7342 /* Bail out on an error in command file mode. */
7343 if (saw_error
&& cmd_file_mode
&& !interactive_mode
)
7344 time_to_exit
= B_TRUE
;
7345 if (time_to_exit
|| (!yyin_is_a_tty
&& feof(yyin
)))
7352 * This function is used in the zonecfg-interactive-mode scenario: it just
7353 * calls read_input() until we are done.
7357 do_interactive(void)
7361 interactive_mode
= B_TRUE
;
7362 if (!read_only_mode
) {
7364 * Try to set things up proactively in interactive mode, so
7365 * that if the zone in question does not exist yet, we can
7366 * provide the user with a clue.
7368 (void) initialize(B_FALSE
);
7372 } while (err
== Z_REPEAT
);
7377 * cmd_file is slightly more complicated, as it has to open the command file
7378 * and set yyin appropriately. Once that is done, though, it just calls
7379 * read_input(), and only once, since prompting is not possible.
7383 cmd_file(char *file
)
7387 struct stat statbuf
;
7388 boolean_t using_real_file
= (strcmp(file
, "-") != 0);
7390 if (using_real_file
) {
7392 * zerr() prints a line number in cmd_file_mode, which we do
7393 * not want here, so temporarily unset it.
7395 cmd_file_mode
= B_FALSE
;
7396 if ((infile
= fopen(file
, "r")) == NULL
) {
7397 zerr(gettext("could not open file %s: %s"),
7398 file
, strerror(errno
));
7401 if ((err
= fstat(fileno(infile
), &statbuf
)) != 0) {
7402 zerr(gettext("could not stat file %s: %s"),
7403 file
, strerror(errno
));
7407 if (!S_ISREG(statbuf
.st_mode
)) {
7408 zerr(gettext("%s is not a regular file."), file
);
7413 cmd_file_mode
= B_TRUE
;
7414 ok_to_prompt
= B_FALSE
;
7417 * "-f -" is essentially the same as interactive mode,
7418 * so treat it that way.
7420 interactive_mode
= B_TRUE
;
7422 /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
7423 if ((err
= read_input()) == Z_REPEAT
)
7426 if (using_real_file
)
7427 (void) fclose(infile
);
7432 * Since yacc is based on reading from a (FILE *) whereas what we get from
7433 * the command line is in argv format, we need to convert when the user
7434 * gives us commands directly from the command line. That is done here by
7435 * concatenating the argv list into a space-separated string, writing it
7436 * to a temp file, and rewinding the file so yyin can be set to it. Then
7437 * we call read_input(), and only once, since prompting about whether to
7438 * continue or quit would make no sense in this context.
7442 one_command_at_a_time(int argc
, char *argv
[])
7445 size_t len
= 2; /* terminal \n\0 */
7448 for (i
= 0; i
< argc
; i
++)
7449 len
+= strlen(argv
[i
]) + 1;
7450 if ((command
= malloc(len
)) == NULL
) {
7451 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7454 (void) strlcpy(command
, argv
[0], len
);
7455 for (i
= 1; i
< argc
; i
++) {
7456 (void) strlcat(command
, " ", len
);
7457 (void) strlcat(command
, argv
[i
], len
);
7459 (void) strlcat(command
, "\n", len
);
7460 err
= string_to_yyin(command
);
7470 get_execbasename(char *execfullname
)
7472 char *last_slash
, *execbasename
;
7474 /* guard against '/' at end of command invocation */
7476 last_slash
= strrchr(execfullname
, '/');
7477 if (last_slash
== NULL
) {
7478 execbasename
= execfullname
;
7481 execbasename
= last_slash
+ 1;
7482 if (*execbasename
== '\0') {
7489 return (execbasename
);
7493 main(int argc
, char *argv
[])
7498 /* This must be before anything goes to stdout. */
7499 setbuf(stdout
, NULL
);
7501 saw_error
= B_FALSE
;
7502 cmd_file_mode
= B_FALSE
;
7503 execname
= get_execbasename(argv
[0]);
7505 (void) setlocale(LC_ALL
, "");
7506 (void) textdomain(TEXT_DOMAIN
);
7508 if (getzoneid() != GLOBAL_ZONEID
) {
7509 zerr(gettext("%s can only be run from the global zone."),
7515 usage(B_FALSE
, HELP_USAGE
| HELP_SUBCMDS
);
7518 if (strcmp(argv
[1], cmd_to_str(CMD_HELP
)) == 0) {
7519 (void) one_command_at_a_time(argc
- 1, &(argv
[1]));
7523 while ((arg
= getopt(argc
, argv
, "?f:R:z:")) != EOF
) {
7527 usage(B_TRUE
, HELP_USAGE
| HELP_SUBCMDS
);
7529 usage(B_FALSE
, HELP_USAGE
);
7533 cmd_file_name
= optarg
;
7534 cmd_file_mode
= B_TRUE
;
7537 if (*optarg
!= '/') {
7538 zerr(gettext("root path must be absolute: %s"),
7542 if (stat(optarg
, &st
) == -1 || !S_ISDIR(st
.st_mode
)) {
7544 "root path must be a directory: %s"),
7548 zonecfg_set_root(optarg
);
7551 if (strcmp(optarg
, GLOBAL_ZONENAME
) == 0) {
7552 global_zone
= B_TRUE
;
7553 } else if (zonecfg_validate_zonename(optarg
) != Z_OK
) {
7554 zone_perror(optarg
, Z_BOGUS_ZONE_NAME
, B_TRUE
);
7555 usage(B_FALSE
, HELP_SYNTAX
);
7558 (void) strlcpy(zone
, optarg
, sizeof (zone
));
7559 (void) strlcpy(revert_zone
, optarg
, sizeof (zone
));
7562 usage(B_FALSE
, HELP_USAGE
);
7567 if (optind
> argc
|| strcmp(zone
, "") == 0) {
7568 usage(B_FALSE
, HELP_USAGE
);
7572 if ((err
= zonecfg_access(zone
, W_OK
)) == Z_OK
) {
7573 read_only_mode
= B_FALSE
;
7574 } else if (err
== Z_ACCES
) {
7575 read_only_mode
= B_TRUE
;
7576 /* skip this message in one-off from command line mode */
7578 (void) fprintf(stderr
, gettext("WARNING: you do not "
7579 "have write access to this zone's configuration "
7580 "file;\ngoing into read-only mode.\n"));
7582 fprintf(stderr
, "%s: Could not access zone configuration "
7583 "store: %s\n", execname
, zonecfg_strerror(err
));
7587 if ((handle
= zonecfg_init_handle()) == NULL
) {
7588 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7593 * This may get set back to FALSE again in cmd_file() if cmd_file_name
7594 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
7596 if (isatty(STDIN_FILENO
))
7597 ok_to_prompt
= B_TRUE
;
7598 if ((gl
= new_GetLine(MAX_LINE_LEN
, MAX_CMD_HIST
)) == NULL
)
7600 if (gl_customize_completion(gl
, NULL
, cmd_cpl_fn
) != 0)
7602 (void) sigset(SIGINT
, SIG_IGN
);
7603 if (optind
== argc
) {
7605 err
= do_interactive();
7607 err
= cmd_file(cmd_file_name
);
7609 err
= one_command_at_a_time(argc
- optind
, &(argv
[optind
]));
7611 zonecfg_fini_handle(handle
);
7614 (void) del_GetLine(gl
);